From a565859ee95b99634cac98fab82dc771d294a2ee Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2013 10:41:49 -0700 Subject: [PATCH 001/147] config: Set PARANOID_NETWORK and NET_ACTIVITY_STATS as default ANDROID While ANDROID_PARNOID_NETWORK and NET_ACTIVITY_STATS should default to yes for Android devices, they aren't completely appropriate as a default y option in non-android enviornments. Thus set the default to ANDROID. Change-Id: Ie8b1f32ef82aaa8ac347f40ea8fff44f0ce79a64 Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/Kconfig b/net/Kconfig index c5e34cf623c4..2a680dadfd6c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -83,13 +83,13 @@ endif # if INET config ANDROID_PARANOID_NETWORK bool "Only allow certain groups to create sockets" - default y + default ANDROID help none config NET_ACTIVITY_STATS bool "Network activity statistics tracking" - default y + default ANDROID help Network activity statistics are useful for tracking wireless modem activity on 2G, 3G, 4G wireless networks. Counts number of From 82099ce8cd9af79f7ef1140c33f0d53ca72f124b Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2013 10:45:09 -0700 Subject: [PATCH 002/147] config: Set CPU_FREQ_GOV_INTERACTIVE default n The CPU_FREQ_GOV_INTERACTIVE text states: "If in doubt, say N." however the option defaults to Y. Make this consistent by defaulting to n. Change-Id: I9625aa6b083c8ca0a99deb81c1e91b720fc76943 Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- drivers/cpufreq/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 62236d633391..e86900b03c8e 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -172,6 +172,7 @@ config CPU_FREQ_GOV_ONDEMAND config CPU_FREQ_GOV_INTERACTIVE tristate "'interactive' cpufreq policy governor" + default n help 'interactive' - This driver adds a dynamic cpufreq policy governor designed for latency-sensitive workloads. From 24821455e30931094b7bc73ea5f3dcb90b5c19c0 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 8 May 2013 13:50:33 -0700 Subject: [PATCH 003/147] Revert "ARM: convert build of appended dtb zImage to list of dtbs" This reverts commit 5e9468632ea81e7d17fc9bd4457acbaffda7b370. Tixy was seeing trouble with "make dtbs" and "make my-boards.dtb", and found reverting this resolves the issue. So for now lets revert this. Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- arch/arm/Kconfig | 14 +++++++------- arch/arm/Makefile | 5 +---- arch/arm/boot/.gitignore | 1 - arch/arm/boot/Makefile | 12 ------------ arch/arm/boot/dts/Makefile | 11 ++--------- scripts/Makefile.lib | 16 +++++++++++----- 6 files changed, 21 insertions(+), 38 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 99887aaa04bb..351e48e45cbb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1861,16 +1861,16 @@ config BUILD_ARM_APPENDED_DTB_IMAGE bool "Build a concatenated zImage/dtb by default" depends on OF help - Enabling this option will cause a concatenated zImage and list of - DTBs to be built by default (instead of a standalone zImage.) - The image will built in arch/arm/boot/zImage-dtb + Enabling this option will cause a concatenated zImage and DTB to + be built by default (instead of a standalone zImage.) The image + will built in arch/arm/boot/zImage-dtb. -config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES - string "Default dtb names" +config BUILD_ARM_APPENDED_DTB_IMAGE_NAME + string "Default dtb name" depends on BUILD_ARM_APPENDED_DTB_IMAGE help - Space separated list of names of dtbs to append when - building a concatenated zImage-dtb. + name of the dtb to append when building a concatenated + zImage/dtb. # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 314c7be492a9..883e4bec807f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -265,7 +265,7 @@ libs-y := arch/arm/lib/ $(libs-y) ifeq ($(CONFIG_XIP_KERNEL),y) KBUILD_IMAGE := xipImage else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y) -KBUILD_IMAGE := zImage-dtb +KBUILD_IMAGE := zImage-dtb.$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAME) else KBUILD_IMAGE := zImage endif @@ -297,9 +297,6 @@ zinstall uinstall install: vmlinux dtbs: scripts $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs -zImage-dtb: vmlinux scripts dtbs - $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ - # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore index ad7a0253ea96..3c79f85975aa 100644 --- a/arch/arm/boot/.gitignore +++ b/arch/arm/boot/.gitignore @@ -4,4 +4,3 @@ xipImage bootpImage uImage *.dtb -zImage-dtb \ No newline at end of file diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 3310df3a0569..84aa2caf07ed 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -27,14 +27,6 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS targets := Image zImage xipImage bootpImage uImage -DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) -ifneq ($(DTB_NAMES),) -DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) -else -DTB_LIST := $(dtb-y) -endif -DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST)) - ifeq ($(CONFIG_XIP_KERNEL),y) $(obj)/xipImage: vmlinux FORCE @@ -63,10 +55,6 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @$(kecho) ' Kernel: $@ is ready' -$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE - $(call if_changed,cat) - @echo ' Kernel: $@ is ready' - endif ifneq ($(LOADADDR),) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b83cc5083a2c..f0895c581a89 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -210,20 +210,13 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ wm8850-w70v2.dtb dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb -DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) -ifneq ($(DTB_NAMES),) -DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) -else -DTB_LIST := $(dtb-y) -endif - targets += dtbs -targets += $(DTB_LIST) +targets += $(dtb-y) endif # *.dtb used to be generated in the directory above. Clean out the # old build results so people don't accidentally use them. -dtbs: $(addprefix $(obj)/, $(DTB_LIST)) +dtbs: $(addprefix $(obj)/, $(dtb-y)) $(Q)rm -f $(obj)/../*.dtb clean-files := *.dtb diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ef2142a61593..bd161eff6921 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -273,11 +273,17 @@ $(obj)/%.dtb: $(src)/%.dts FORCE dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) -# cat -# --------------------------------------------------------------------------- -# Concatentate multiple files together -quiet_cmd_cat = CAT $@ -cmd_cat = (cat $(filter-out FORCE,$^) > $@) || (rm -f $@; false) +$(obj)/%.dtb: $(src)/%.dts FORCE + $(call if_changed_dep,dtc) + +dtc-tmp = $(subst $(comma),_,$(dot-target).dts) + +quiet_cmd_dtc_cpp = DTC+CPP $@ +cmd_dtc_cpp = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ + $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp) + +$(obj)/%.dtb: $(src)/%.dtsp FORCE + $(call if_changed_dep,dtc_cpp) # Bzip2 # --------------------------------------------------------------------------- From fe4a42e66e87c1cd3c195c14ef1f8bb22b02c7fb Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 May 2013 10:00:44 -0700 Subject: [PATCH 004/147] Revert "ARM: Make low-level printk work" This reverts commit 63d454ab530bb3ab5412aabd6be6ee8cd340888e. Per Andy's request, Andy's rational: "I don't think that makes any sense any more and should be removed, unless there's some case on Android side that really needs it. Vanilla has better DEBUG_LL support now since 2005 when that patch was introduced and the Android kernels will inherit it. I've reverted it in my tree since we commonly need DEBUG_LL on (but we don't need printascii garbling all our logging as if there was an echo in there). ...[It] basically forces all printk output down printascii() which is not what we want. earlyprintk=1 earlycon=ttyO2,115200n8 On your commandline will get you going [without this]" Change-Id: I1da455354b4a8ff3bc9c5f66f5a174b13e179ae6 Signed-off-by: John Stultz --- kernel/printk.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index 9cb84eb1a9de..8212c1aef125 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -51,10 +51,6 @@ #define CREATE_TRACE_POINTS #include -#ifdef CONFIG_DEBUG_LL -extern void printascii(char *); -#endif - /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL @@ -1556,10 +1552,6 @@ asmlinkage int vprintk_emit(int facility, int level, */ text_len = vscnprintf(text, sizeof(textbuf), fmt, args); -#ifdef CONFIG_DEBUG_LL - printascii(text); -#endif - /* mark and strip a trailing newline */ if (text_len && text[text_len-1] == '\n') { text_len--; From 31366efc298e297b72db4e83a1822aa3eff15e81 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 8 May 2013 16:06:16 -0700 Subject: [PATCH 005/147] dcc_tty: Build fixups Fix spinlock declaration and tty_insert/flip arguments. Signed-off-by: John Stultz --- drivers/char/dcc_tty.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c index a787accdcb14..0a62d410286f 100644 --- a/drivers/char/dcc_tty.c +++ b/drivers/char/dcc_tty.c @@ -26,7 +26,7 @@ MODULE_DESCRIPTION("DCC TTY Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); -static spinlock_t g_dcc_tty_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(g_dcc_tty_lock); static struct hrtimer g_dcc_timer; static char g_dcc_buffer[16]; static int g_dcc_buffer_head; @@ -80,8 +80,8 @@ static void dcc_poll_locked(void) ); if (rch >= 0) { ch = rch; - tty_insert_flip_string(g_dcc_tty, &ch, 1); - tty_flip_buffer_push(g_dcc_tty); + tty_insert_flip_string(g_dcc_tty->port, &ch, 1); + tty_flip_buffer_push(g_dcc_tty->port); } } From bb00c9ddc5f63be7bb5893ee6aaeabd1f059130f Mon Sep 17 00:00:00 2001 From: Bintian Wang Date: Thu, 27 Jun 2013 12:40:08 +0800 Subject: [PATCH 006/147] vfat: Add compat_ioctl support for VFAT_IOCTL_GET_VOLUME_ID Add VFAT_IOCTL_GET_VOLUME_ID to vfat dir compat_ioctl() interface, which enable you read vfat volume ID from a 32bit app on a 64bit kernel Change-Id: Ic12ac9d2d46aa50c0597fbedff32de7c8fdeac51 Signed-off-by: Bintian Wang [jstultz: commit message tweaks] Signed-off-by: John Stultz --- fs/fat/dir.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/fat/dir.c b/fs/fat/dir.c index ddfa4529e6ea..4b775e606fc8 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -841,6 +841,8 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd, short_only = 0; both = 1; break; + case VFAT_IOCTL_GET_VOLUME_ID: + return fat_ioctl_volume_id(inode); default: return fat_generic_ioctl(filp, cmd, (unsigned long)arg); } From 8c02283ab5983c9f6ef278faa5b803b22e864a41 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:48:32 -0700 Subject: [PATCH 007/147] mm: vmscan: Fix up build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's an unused var warning /projects/linaro/linux-2.6/mm/vmscan.c: In function ‘debug_shrinker_show’: /projects/linaro/linux-2.6/mm/vmscan.c:170:8: warning: unused variable ‘name’ [-Wunused-variable] introduced from this patch from androidization series --> commit ad42da0cc73761e405128e71c58eda40c25367d4 Author: Rebecca Schultz Zavin Date: Fri Oct 5 13:54:59 2012 -0700 mm: vmscan: Add a debug file for shrinkers this patch cleans it out Signed-off-by: Andy Green Signed-off-by: John Stultz --- mm/vmscan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 80c0b17373f7..5d41059e1e92 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -167,7 +167,6 @@ static int debug_shrinker_show(struct seq_file *s, void *unused) down_read(&shrinker_rwsem); list_for_each_entry(shrinker, &shrinker_list, list) { - char name[64]; int num_objs; num_objs = shrinker->shrink(shrinker, &sc); From 0476131fb9ae1c40735abce1894c56688a34884f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:50:26 -0700 Subject: [PATCH 008/147] staging: android: binder: Fix build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit in mainline (now) causes a couple of warnings commit 975a1ac9a9fe65d66ee1726c0db6dc58e53d232a Author: Arve Hjønnevåg Date: Tue Oct 16 15:29:53 2012 -0700 Staging: android: binder: Add some tracepoints This patch fixes them Signed-off-by: Andy Green Signed-off-by: John Stultz --- drivers/staging/android/binder_trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h index 82a567c2af67..c661e376398f 100644 --- a/drivers/staging/android/binder_trace.h +++ b/drivers/staging/android/binder_trace.h @@ -159,7 +159,7 @@ TRACE_EVENT(binder_transaction_node_to_ref, TP_fast_assign( __entry->debug_id = t->debug_id; __entry->node_debug_id = node->debug_id; - __entry->node_ptr = node->ptr; + __entry->node_ptr = (void __user *)node->ptr; __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; ), @@ -184,7 +184,7 @@ TRACE_EVENT(binder_transaction_ref_to_node, __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; __entry->node_debug_id = ref->node->debug_id; - __entry->node_ptr = ref->node->ptr; + __entry->node_ptr = (void __user *)ref->node->ptr; ), TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p", __entry->debug_id, __entry->node_debug_id, From 80475b849b90d8bed1fe768c496280f4b5c11410 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:59:25 -0700 Subject: [PATCH 009/147] ion: Use size_t-specific format struct ion_platform_heap .size is a size_t, use %zu instead of %lu Signed-off-by: Andy Green Signed-off-by: John Stultz --- drivers/gpu/ion/ion_chunk_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/ion/ion_chunk_heap.c b/drivers/gpu/ion/ion_chunk_heap.c index d5e7379a6f46..8c8f5c3c5537 100644 --- a/drivers/gpu/ion/ion_chunk_heap.c +++ b/drivers/gpu/ion/ion_chunk_heap.c @@ -185,8 +185,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - pr_info("%s: base %lu size %u align %ld\n", __func__, chunk_heap->base, - heap_data->size, heap_data->align); + pr_info("%s: base %lu size %zu align %ld\n", __func__, + chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; From c457bb048e4ba70527e0f0bd2e4e55359905a29f Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 8 May 2013 16:06:16 -0700 Subject: [PATCH 010/147] dcc_tty: Build fixups Fix spinlock declaration and tty_insert/flip arguments. Signed-off-by: John Stultz --- drivers/char/dcc_tty.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c index a787accdcb14..0a62d410286f 100644 --- a/drivers/char/dcc_tty.c +++ b/drivers/char/dcc_tty.c @@ -26,7 +26,7 @@ MODULE_DESCRIPTION("DCC TTY Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); -static spinlock_t g_dcc_tty_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(g_dcc_tty_lock); static struct hrtimer g_dcc_timer; static char g_dcc_buffer[16]; static int g_dcc_buffer_head; @@ -80,8 +80,8 @@ static void dcc_poll_locked(void) ); if (rch >= 0) { ch = rch; - tty_insert_flip_string(g_dcc_tty, &ch, 1); - tty_flip_buffer_push(g_dcc_tty); + tty_insert_flip_string(g_dcc_tty->port, &ch, 1); + tty_flip_buffer_push(g_dcc_tty->port); } } From aecff9d0c1a87b5cd9af1c91b79a3d8fba82ffba Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:50:26 -0700 Subject: [PATCH 011/147] staging: android: binder: Fix build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit in mainline (now) causes a couple of warnings commit 975a1ac9a9fe65d66ee1726c0db6dc58e53d232a Author: Arve Hjønnevåg Date: Tue Oct 16 15:29:53 2012 -0700 Staging: android: binder: Add some tracepoints This patch fixes them Signed-off-by: Andy Green Signed-off-by: John Stultz --- drivers/staging/android/binder_trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h index 82a567c2af67..c661e376398f 100644 --- a/drivers/staging/android/binder_trace.h +++ b/drivers/staging/android/binder_trace.h @@ -159,7 +159,7 @@ TRACE_EVENT(binder_transaction_node_to_ref, TP_fast_assign( __entry->debug_id = t->debug_id; __entry->node_debug_id = node->debug_id; - __entry->node_ptr = node->ptr; + __entry->node_ptr = (void __user *)node->ptr; __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; ), @@ -184,7 +184,7 @@ TRACE_EVENT(binder_transaction_ref_to_node, __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; __entry->node_debug_id = ref->node->debug_id; - __entry->node_ptr = ref->node->ptr; + __entry->node_ptr = (void __user *)ref->node->ptr; ), TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p", __entry->debug_id, __entry->node_debug_id, From de95de8f56ea0740944a18f500d50b41543e50af Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:59:25 -0700 Subject: [PATCH 012/147] ion: Use size_t-specific format struct ion_platform_heap .size is a size_t, use %zu instead of %lu Signed-off-by: Andy Green Signed-off-by: John Stultz --- drivers/gpu/ion/ion_chunk_heap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/ion/ion_chunk_heap.c b/drivers/gpu/ion/ion_chunk_heap.c index 15c9d7ad2502..cd01aad6ac2d 100644 --- a/drivers/gpu/ion/ion_chunk_heap.c +++ b/drivers/gpu/ion/ion_chunk_heap.c @@ -188,8 +188,8 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) chunk_heap->heap.ops = &chunk_heap_ops; chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; - pr_info("%s: base %lu size %u align %ld\n", __func__, chunk_heap->base, - heap_data->size, heap_data->align); + pr_info("%s: base %lu size %zu align %ld\n", __func__, + chunk_heap->base, heap_data->size, heap_data->align); return &chunk_heap->heap; From 1f518e8958dfb9dd6248a920f7219e066a0a84b4 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 5 Aug 2013 19:48:32 -0700 Subject: [PATCH 013/147] mm: vmscan: Fix up build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's an unused var warning /projects/linaro/linux-2.6/mm/vmscan.c: In function ‘debug_shrinker_show’: /projects/linaro/linux-2.6/mm/vmscan.c:170:8: warning: unused variable ‘name’ [-Wunused-variable] introduced from this patch from androidization series --> commit ad42da0cc73761e405128e71c58eda40c25367d4 Author: Rebecca Schultz Zavin Date: Fri Oct 5 13:54:59 2012 -0700 mm: vmscan: Add a debug file for shrinkers this patch cleans it out Signed-off-by: Andy Green Signed-off-by: John Stultz --- mm/vmscan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 80c0b17373f7..5d41059e1e92 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -167,7 +167,6 @@ static int debug_shrinker_show(struct seq_file *s, void *unused) down_read(&shrinker_rwsem); list_for_each_entry(shrinker, &shrinker_list, list) { - char name[64]; int num_objs; num_objs = shrinker->shrink(shrinker, &sc); From 7904f1f74f7958fd0e640eabf0a7f56a5139c6d1 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 8 May 2013 13:50:33 -0700 Subject: [PATCH 014/147] Revert "ARM: convert build of appended dtb zImage to list of dtbs" This reverts commit 5e9468632ea81e7d17fc9bd4457acbaffda7b370. Tixy was seeing trouble with "make dtbs" and "make my-boards.dtb", and found reverting this resolves the issue. So for now lets revert this. Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- arch/arm/Kconfig | 14 +++++++------- arch/arm/Makefile | 5 +---- arch/arm/boot/.gitignore | 1 - arch/arm/boot/Makefile | 12 ------------ arch/arm/boot/dts/Makefile | 11 ++--------- scripts/Makefile.lib | 16 +++++++++++----- 6 files changed, 21 insertions(+), 38 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 99887aaa04bb..351e48e45cbb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1861,16 +1861,16 @@ config BUILD_ARM_APPENDED_DTB_IMAGE bool "Build a concatenated zImage/dtb by default" depends on OF help - Enabling this option will cause a concatenated zImage and list of - DTBs to be built by default (instead of a standalone zImage.) - The image will built in arch/arm/boot/zImage-dtb + Enabling this option will cause a concatenated zImage and DTB to + be built by default (instead of a standalone zImage.) The image + will built in arch/arm/boot/zImage-dtb. -config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES - string "Default dtb names" +config BUILD_ARM_APPENDED_DTB_IMAGE_NAME + string "Default dtb name" depends on BUILD_ARM_APPENDED_DTB_IMAGE help - Space separated list of names of dtbs to append when - building a concatenated zImage-dtb. + name of the dtb to append when building a concatenated + zImage/dtb. # Compressed boot loader in ROM. Yes, we really want to ask about # TEXT and BSS so we preserve their values in the config files. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 314c7be492a9..883e4bec807f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -265,7 +265,7 @@ libs-y := arch/arm/lib/ $(libs-y) ifeq ($(CONFIG_XIP_KERNEL),y) KBUILD_IMAGE := xipImage else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y) -KBUILD_IMAGE := zImage-dtb +KBUILD_IMAGE := zImage-dtb.$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAME) else KBUILD_IMAGE := zImage endif @@ -297,9 +297,6 @@ zinstall uinstall install: vmlinux dtbs: scripts $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs -zImage-dtb: vmlinux scripts dtbs - $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ - # We use MRPROPER_FILES and CLEAN_FILES now archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore index ad7a0253ea96..3c79f85975aa 100644 --- a/arch/arm/boot/.gitignore +++ b/arch/arm/boot/.gitignore @@ -4,4 +4,3 @@ xipImage bootpImage uImage *.dtb -zImage-dtb \ No newline at end of file diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 3310df3a0569..84aa2caf07ed 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -27,14 +27,6 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS targets := Image zImage xipImage bootpImage uImage -DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) -ifneq ($(DTB_NAMES),) -DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) -else -DTB_LIST := $(dtb-y) -endif -DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST)) - ifeq ($(CONFIG_XIP_KERNEL),y) $(obj)/xipImage: vmlinux FORCE @@ -63,10 +55,6 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @$(kecho) ' Kernel: $@ is ready' -$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE - $(call if_changed,cat) - @echo ' Kernel: $@ is ready' - endif ifneq ($(LOADADDR),) diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b83cc5083a2c..f0895c581a89 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -210,20 +210,13 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ wm8850-w70v2.dtb dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb -DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES)) -ifneq ($(DTB_NAMES),) -DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES)) -else -DTB_LIST := $(dtb-y) -endif - targets += dtbs -targets += $(DTB_LIST) +targets += $(dtb-y) endif # *.dtb used to be generated in the directory above. Clean out the # old build results so people don't accidentally use them. -dtbs: $(addprefix $(obj)/, $(DTB_LIST)) +dtbs: $(addprefix $(obj)/, $(dtb-y)) $(Q)rm -f $(obj)/../*.dtb clean-files := *.dtb diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index ef2142a61593..bd161eff6921 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -273,11 +273,17 @@ $(obj)/%.dtb: $(src)/%.dts FORCE dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) -# cat -# --------------------------------------------------------------------------- -# Concatentate multiple files together -quiet_cmd_cat = CAT $@ -cmd_cat = (cat $(filter-out FORCE,$^) > $@) || (rm -f $@; false) +$(obj)/%.dtb: $(src)/%.dts FORCE + $(call if_changed_dep,dtc) + +dtc-tmp = $(subst $(comma),_,$(dot-target).dts) + +quiet_cmd_dtc_cpp = DTC+CPP $@ +cmd_dtc_cpp = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ + $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) $(dtc-tmp) + +$(obj)/%.dtb: $(src)/%.dtsp FORCE + $(call if_changed_dep,dtc_cpp) # Bzip2 # --------------------------------------------------------------------------- From 9f0c3ccfa97d84ee50a248574980b43d8a47e118 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 May 2013 10:00:44 -0700 Subject: [PATCH 015/147] Revert "ARM: Make low-level printk work" This reverts commit 63d454ab530bb3ab5412aabd6be6ee8cd340888e. Per Andy's request, Andy's rational: "I don't think that makes any sense any more and should be removed, unless there's some case on Android side that really needs it. Vanilla has better DEBUG_LL support now since 2005 when that patch was introduced and the Android kernels will inherit it. I've reverted it in my tree since we commonly need DEBUG_LL on (but we don't need printascii garbling all our logging as if there was an echo in there). ...[It] basically forces all printk output down printascii() which is not what we want. earlyprintk=1 earlycon=ttyO2,115200n8 On your commandline will get you going [without this]" Change-Id: I1da455354b4a8ff3bc9c5f66f5a174b13e179ae6 Signed-off-by: John Stultz --- kernel/printk.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/kernel/printk.c b/kernel/printk.c index 9cb84eb1a9de..8212c1aef125 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -51,10 +51,6 @@ #define CREATE_TRACE_POINTS #include -#ifdef CONFIG_DEBUG_LL -extern void printascii(char *); -#endif - /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL @@ -1556,10 +1552,6 @@ asmlinkage int vprintk_emit(int facility, int level, */ text_len = vscnprintf(text, sizeof(textbuf), fmt, args); -#ifdef CONFIG_DEBUG_LL - printascii(text); -#endif - /* mark and strip a trailing newline */ if (text_len && text[text_len-1] == '\n') { text_len--; From 098a70966b110210762117b9ba9d8781a5f7a462 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2013 10:41:49 -0700 Subject: [PATCH 016/147] config: Set PARANOID_NETWORK and NET_ACTIVITY_STATS as default ANDROID While ANDROID_PARNOID_NETWORK and NET_ACTIVITY_STATS should default to yes for Android devices, they aren't completely appropriate as a default y option in non-android enviornments. Thus set the default to ANDROID. Change-Id: Ie8b1f32ef82aaa8ac347f40ea8fff44f0ce79a64 Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/Kconfig b/net/Kconfig index c5e34cf623c4..2a680dadfd6c 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -83,13 +83,13 @@ endif # if INET config ANDROID_PARANOID_NETWORK bool "Only allow certain groups to create sockets" - default y + default ANDROID help none config NET_ACTIVITY_STATS bool "Network activity statistics tracking" - default y + default ANDROID help Network activity statistics are useful for tracking wireless modem activity on 2G, 3G, 4G wireless networks. Counts number of From 84bb63eb93e4448e891108195ba0a8f654329779 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2013 10:45:09 -0700 Subject: [PATCH 017/147] config: Set CPU_FREQ_GOV_INTERACTIVE default n The CPU_FREQ_GOV_INTERACTIVE text states: "If in doubt, say N." however the option defaults to Y. Make this consistent by defaulting to n. Change-Id: I9625aa6b083c8ca0a99deb81c1e91b720fc76943 Reported-by: Jon Medhurst (Tixy) Signed-off-by: John Stultz --- drivers/cpufreq/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 62236d633391..e86900b03c8e 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -172,6 +172,7 @@ config CPU_FREQ_GOV_ONDEMAND config CPU_FREQ_GOV_INTERACTIVE tristate "'interactive' cpufreq policy governor" + default n help 'interactive' - This driver adds a dynamic cpufreq policy governor designed for latency-sensitive workloads. From ce5c776ed5ed5c8619930387c5c10ec3f0d53047 Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Fri, 18 Oct 2013 17:16:38 -0700 Subject: [PATCH 018/147] usb: gadget: android: Remove device if probe fails Make sure the android0 device is removed before we can destroy the class. Change-Id: Id584888c407beb80a1df4990f73fe31ccb9d4767 Signed-off-by: Benoit Goby Signed-off-by: John Stultz --- drivers/usb/gadget/android.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index d0ec54b810c1..04cbeb134814 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -1490,7 +1490,7 @@ static int __init init(void) err = usb_composite_probe(&android_usb_driver); if (err) { pr_err("%s: failed to probe driver %d", __func__, err); - goto err_create; + goto err_probe; } /* HACK: exchange composite's setup with ours */ @@ -1499,6 +1499,8 @@ static int __init init(void) return 0; +err_probe: + device_destroy(android_class, dev->dev->devt); err_create: kfree(dev); err_dev: From 90a332678deb2d8b2aae19aee8b9181f298b503a Mon Sep 17 00:00:00 2001 From: Amit Pundir Date: Fri, 15 Nov 2013 12:56:31 +0530 Subject: [PATCH 019/147] epoll: drop EPOLLWAKEUP if PM_SLEEP is disabled Drop EPOLLWAKEUP from epoll events mask if CONFIG_PM_SLEEP is disabled. Signed-off-by: Amit Pundir Signed-off-by: John Stultz --- fs/eventpoll.c | 3 +-- include/uapi/linux/eventpoll.h | 13 ++++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 0cff4434880d..db10e00c971a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1819,8 +1819,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, goto error_tgt_fput; /* Check if EPOLLWAKEUP is allowed */ - if ((epds.events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND)) - epds.events &= ~EPOLLWAKEUP; + ep_take_care_of_epollwakeup(&epds); /* * We have to check that the file structure underneath the file descriptor diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h index 2c267bcbb85c..bc81fb2e1f0e 100644 --- a/include/uapi/linux/eventpoll.h +++ b/include/uapi/linux/eventpoll.h @@ -61,5 +61,16 @@ struct epoll_event { __u64 data; } EPOLL_PACKED; - +#ifdef CONFIG_PM_SLEEP +static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev) +{ + if ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND)) + epev->events &= ~EPOLLWAKEUP; +} +#else +static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev) +{ + epev->events &= ~EPOLLWAKEUP; +} +#endif #endif /* _UAPI_LINUX_EVENTPOLL_H */ From c240c24f343f6e2b919bdfc1ee4f1d2ba6b07d79 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 12 Dec 2013 19:09:47 -0800 Subject: [PATCH 020/147] ion: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add #include to fix the following warning. In file included from drivers/staging/android/ion/ion_heap.c:26:0: drivers/staging/android/ion/ion_priv.h:358:21: warning: ‘struct device’ declared inside parameter list [enabled by default] drivers/staging/android/ion/ion_priv.h:358:21: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_priv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 19691c0d24c7..ffc8a1c8b221 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "ion.h" From e89d9fc608d3c8a1cf21174a713d2ff7e88e7e00 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 22 Nov 2013 17:29:57 -0800 Subject: [PATCH 021/147] android: configs: require TCPMSS, remove SCHED_TRACER and TIMER_STATS TCPMSS is required for the Android Vpn service to correctly handle the MTU on tun/ppp devices. Bug: 11579326 We don't really need SCHED_TRACER and the TIMER_STATS. Change-Id: I10c5767a6324a496713752d4fe9eff361dc8e06a (cherry picked from commit 23f01e8e81f3c53985958fa291b39c84293ad047) --- android/configs/android-base.cfg | 1 + android/configs/android-recommended.cfg | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 25162024f889..a9597658ef14 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -85,6 +85,7 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_TARGET_NFLOG=y CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y CONFIG_NETFILTER_XT_TARGET_TPROXY=y CONFIG_NETFILTER_XT_TARGET_TRACE=y CONFIG_NET_CLS_ACT=y diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index b0120f678cc4..1bd9f6f4b959 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -95,7 +95,6 @@ CONFIG_PM_RUNTIME=y CONFIG_PM_WAKELOCKS_LIMIT=0 CONFIG_POWER_SUPPLY=y CONFIG_SCHEDSTATS=y -CONFIG_SCHED_TRACER=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_SND=y CONFIG_SOUND=y @@ -106,7 +105,6 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_TABLET_USB_WACOM=y -CONFIG_TIMER_STATS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_UHID=y From a8694287f5cbd0585ac653924a4459d3f1aa5b29 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 13 Dec 2013 13:02:31 -0800 Subject: [PATCH 022/147] timerfd: support CLOCK_BOOTTIME clock Add CLOCK_BOOTTIME support to timerfd Change-Id: I14dee6d1104f15a05f463a632268ac4564753faf Signed-off-by: Greg Hackmann --- fs/timerfd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/timerfd.c b/fs/timerfd.c index 929312180dd0..0013142c0475 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -317,6 +317,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) (clockid != CLOCK_MONOTONIC && clockid != CLOCK_REALTIME && clockid != CLOCK_REALTIME_ALARM && + clockid != CLOCK_BOOTTIME && clockid != CLOCK_BOOTTIME_ALARM)) return -EINVAL; From f2b94c52648fa1bb7cba053ab0f4a85e066485a1 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Sat, 14 Dec 2013 12:06:45 -0800 Subject: [PATCH 023/147] ion: Don't allow building ION as a module. ION doesn't export the proper symbols for it to be a module. This causes build issues when ION is configured as a module. Since Andorid kernels rarely use modules (I think recent policy requires no modules?), go ahead and set the ION config to a bool from the tristate option. If folks decide ION as a module is important, we will have to go through and export the various needed symbols. Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index a342d96ee4f0..b95281eef2aa 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,5 @@ menuconfig ION - tristate "Ion Memory Manager" + bool "Ion Memory Manager" select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- From 8d9bc1404990afcc1fa73f1412f2b653fc3ecd31 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 16 Dec 2013 16:33:00 -0800 Subject: [PATCH 024/147] ion: remove ion_user_handle_t from ion_test.h ion_test.h should not define ion_user_handle_t, and defining it causes a warning: In file included from drivers/staging/android/ion/ion_test.c:31: drivers/staging/android/ion/../uapi/ion_test.h:23: error: redefinition of typedef 'ion_user_handle_t' drivers/staging/android/ion/../uapi/ion.h:23: note: previous declaration of 'ion_user_handle_t' was here Change-Id: I541897745a5ff128790a7e51b23f3034f5d3d6d9 Reported-by: Andrew Morton Signed-off-by: Colin Cross --- drivers/staging/android/uapi/ion_test.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index 352379a02690..614d1e36f72c 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -20,8 +20,6 @@ #include #include -typedef int ion_user_handle_t; - /** * struct ion_test_rw_data - metadata passed to the kernel to read handle * @ptr: a pointer to an area at least as large as size From e513299f8dc0a79e6e3f5ee79615426edaf086b9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 12 Dec 2013 19:09:47 -0800 Subject: [PATCH 025/147] ion: Fix build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add #include to fix the following warning seen with gcc 4.7.3: In file included from drivers/staging/android/ion/ion_heap.c:26:0: drivers/staging/android/ion/ion_priv.h:358:21: warning: ‘struct device’ declared inside parameter list [enabled by default] drivers/staging/android/ion/ion_priv.h:358:21: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] Change-Id: Icc249b32d877a5b76b1669c99bef2b05d9e322da Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_priv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 19691c0d24c7..ac625b115057 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -17,6 +17,7 @@ #ifndef _ION_PRIV_H #define _ION_PRIV_H +#include #include #include #include From a1eabac6e216f8ecee7668ad4468990e465392ba Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Fri, 4 Oct 2013 10:59:57 -0700 Subject: [PATCH 026/147] gpiolib: safer implementation of desc_to_gpio() The current implementation of desc_to_gpio() relies on the chip pointer to be set to a valid value in order to compute the GPIO number. This was done in the hope that we can get rid of the gpio_desc global array, but this is not happening anytime soon. This patch reimplements desc_to_gpio() in a fashion similar to that of gpio_to_desc(). As a result, desc_to_gpio(gpio_to_desc(gpio)) == gpio is now always true. This allows to call desc_to_gpio() on non-initialized descriptors as some error-handling code currently does. Signed-off-by: Alexandre Courbot Reported-by: Dr. H. Nikolaus Schaller Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c2534d62911c..4aff349386d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -136,7 +136,7 @@ static struct gpio_desc *gpio_to_desc(unsigned gpio) */ static int desc_to_gpio(const struct gpio_desc *desc) { - return desc->chip->base + gpio_chip_hwgpio(desc); + return desc - &gpio_desc[0]; } From 39293584f8a423bcb4efba635cddacc3d4d0b85e Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 4 Dec 2013 15:23:41 -0800 Subject: [PATCH 027/147] android: configs: Add HIDRAW to recommended set The Logitech unifying driver depends on hidraw being available. Recommending one without the other will cause the Logitech driver to silently fail when connecting Logitech devices. Change-Id: I92ed2b6803537d9da6eed7fcada8f329cb4469a2 Signed-off-by: Michael Wright --- android/configs/android-recommended.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 1bd9f6f4b959..32596bc2e199 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -18,6 +18,7 @@ CONFIG_EXT4_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_FUSE_FS=y CONFIG_GREENASIA_FF=y +CONFIG_HIDRAW=y CONFIG_HID_A4TECH=y CONFIG_HID_ACRUX=y CONFIG_HID_ACRUX_FF=y From d214ac7202b30062bf3164b61fc466793d359f7b Mon Sep 17 00:00:00 2001 From: Zhangfei Gao Date: Sun, 9 Jun 2013 11:08:32 +0800 Subject: [PATCH 028/147] gpiolib: remove warnning of allocations with IRQs disabled Move of_gpiochip_add outof spin_lock, since kzalloc inside of_gpiochip_add -> of_gpiochip_add_pin_range -> gpiochip_add_pin_range -> kzalloc WARNING: at kernel/lockdep.c:2740 lockdep_trace_alloc+0xf8/0xfc() DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) Signed-off-by: Zhangfei Gao Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4aff349386d8..a35c5b932eba 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1214,15 +1214,14 @@ int gpiochip_add(struct gpio_chip *chip) } } + spin_unlock_irqrestore(&gpio_lock, flags); + #ifdef CONFIG_PINCTRL INIT_LIST_HEAD(&chip->pin_ranges); #endif of_gpiochip_add(chip); -unlock: - spin_unlock_irqrestore(&gpio_lock, flags); - if (status) goto fail; @@ -1235,6 +1234,9 @@ int gpiochip_add(struct gpio_chip *chip) chip->label ? : "generic"); return 0; + +unlock: + spin_unlock_irqrestore(&gpio_lock, flags); fail: /* failures here can mean systems won't boot... */ pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", From 0a7dde3d881d173c9300bf1d46017cb593d3e52b Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:16:41 +0800 Subject: [PATCH 029/147] gpu: ion: use module_platform_driver to simplify the code module_platform_driver() makes the code simpler by eliminating boilerplate code. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 0849600bcc00..4b3d93fbf9a5 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -81,16 +81,5 @@ static struct platform_driver ion_driver = { .driver = { .name = "ion-tegra" } }; -static int __init ion_init(void) -{ - return platform_driver_register(&ion_driver); -} - -static void __exit ion_exit(void) -{ - platform_driver_unregister(&ion_driver); -} - -module_init(ion_init); -module_exit(ion_exit); +module_platform_driver(ion_driver); From ddd0ec0672e38c79e815588bfd725d50bd15d657 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 17 Dec 2013 11:20:22 +0800 Subject: [PATCH 030/147] gpu: ion: fix sparse non static symbol warnings Fixes the following sparse warnings: drivers/staging/android/ion/tegra/tegra_ion.c:23:19: warning: symbol 'idev' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:24:19: warning: symbol 'tegra_user_mapper' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:25:5: warning: symbol 'num_heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:26:17: warning: symbol 'heaps' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:28:5: warning: symbol 'tegra_ion_probe' was not declared. Should it be static? drivers/staging/android/ion/tegra/tegra_ion.c:66:5: warning: symbol 'tegra_ion_remove' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/tegra/tegra_ion.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/tegra/tegra_ion.c b/drivers/staging/android/ion/tegra/tegra_ion.c index 4b3d93fbf9a5..3474c65f87fa 100644 --- a/drivers/staging/android/ion/tegra/tegra_ion.c +++ b/drivers/staging/android/ion/tegra/tegra_ion.c @@ -20,12 +20,11 @@ #include "../ion.h" #include "../ion_priv.h" -struct ion_device *idev; -struct ion_mapper *tegra_user_mapper; -int num_heaps; -struct ion_heap **heaps; +static struct ion_device *idev; +static int num_heaps; +static struct ion_heap **heaps; -int tegra_ion_probe(struct platform_device *pdev) +static int tegra_ion_probe(struct platform_device *pdev) { struct ion_platform_data *pdata = pdev->dev.platform_data; int err; @@ -63,7 +62,7 @@ int tegra_ion_probe(struct platform_device *pdev) return err; } -int tegra_ion_remove(struct platform_device *pdev) +static int tegra_ion_remove(struct platform_device *pdev) { struct ion_device *idev = platform_get_drvdata(pdev); int i; From d232ba2bea468a7d12d826d0fe62b3f8a9ba8d10 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:51 -0800 Subject: [PATCH 031/147] staging: ion: Add HAVE_MEMBLOCK config dependency The kbuild test robot reported a build issue w/ ION on m68k: drivers/staging/android/ion/ion.c: In function 'ion_reserve': drivers/staging/android/ion/ion.c:1526:4: error: implicit declaration of function 'memblock_alloc_base' [-Werror=implicit-function-declaration] drivers/staging/android/ion/ion.c:1528:11: error: 'MEMBLOCK_ALLOC_ANYWHERE' undeclared (first use in this function) drivers/staging/android/ion/ion.c:1528:11: note: each undeclared identifier is reported only once for each function it appears in drivers/staging/android/ion/ion.c:1537:4: error: implicit declaration of function 'memblock_reserve' [-Werror=implicit-function-declaration] cc1: some warnings being treated as errors This is caused by ION using memblock functionality which m68k doesn't support. This patch adds a HAVE_MEMBLOCK dependency to the ION config. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index b95281eef2aa..a9a64ea2343f 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -1,5 +1,6 @@ menuconfig ION bool "Ion Memory Manager" + depends on HAVE_MEMBLOCK select GENERIC_ALLOCATOR select DMA_SHARED_BUFFER ---help--- From 60e11dfc002962181fe4f0db54b33c65fee02c52 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 16 Dec 2013 21:07:52 -0800 Subject: [PATCH 032/147] staging: ion: Fix possible null pointer dereference The kbuild test robot reported: drivers/staging/android/ion/ion_system_heap.c:122 alloc_largest_available() error: potential null dereference 'info'. (kmalloc returns null) Where the pointer returned from kmalloc goes unchecked for failure. This patch checks the return for NULL, and reworks the logic, as suggested by Colin, so we allocate the page_info structure first. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: kbuild test robot Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 05e9dc93980f..5bccf9e2c93c 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -108,6 +108,10 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, struct page_info *info; int i; + info = kmalloc(sizeof(struct page_info), GFP_KERNEL); + if (!info) + return NULL; + for (i = 0; i < num_orders; i++) { if (size < order_to_size(orders[i])) continue; @@ -118,11 +122,12 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, if (!page) continue; - info = kmalloc(sizeof(struct page_info), GFP_KERNEL); info->page = page; info->order = orders[i]; return info; } + kfree(info); + return NULL; } From c6448537fe9e8b684b214e89c6c68c3b209f549e Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 17 Dec 2013 17:04:29 -0800 Subject: [PATCH 033/147] staging: ion: Avoid using rt_mutexes directly RT_MUTEXES can be configured out of the kernel, causing compile problems with ION. To quote Colin: "rt_mutexes were added with the deferred freeing feature. Heaps need to return zeroed memory to userspace, but zeroing the memory on every allocation was causing performance issues. We added a SCHED_IDLE thread to zero memory in the background after freeing, but locking the heap from the SCHED_IDLE thread might block a high priority allocation thread for a long time. The lock is only used to protect the heap's free_list and free_list_size members, and is not held for any long or sleeping operations. Converting to a spinlock should prevent priority inversion without using the rt_mutex. I'd also rename it to free_lock to so it doesn't get used as a general heap lock." Thus this patch converts the rt_mutex usage to a spinlock and renames the lock free_lock to be more clear as to its use. I also had to change a bit of logic in ion_heap_freelist_drain() to safely avoid list corruption. Acked-by: Colin Cross Cc: Android Kernel Team Reported-by: Jim Davis Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_heap.c | 28 +++++++++++++++----------- drivers/staging/android/ion/ion_priv.h | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 5b01e9e30a4f..96feebb6ad79 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -160,10 +160,10 @@ int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot) void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer) { - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); list_add(&buffer->list, &heap->free_list); heap->free_list_size += buffer->size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); wake_up(&heap->waitqueue); } @@ -171,34 +171,38 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) { size_t size; - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); size = heap->free_list_size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); return size; } size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) { - struct ion_buffer *buffer, *tmp; + struct ion_buffer *buffer; size_t total_drained = 0; if (ion_heap_freelist_size(heap) == 0) return 0; - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); if (size == 0) size = heap->free_list_size; - list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) { + while (!list_empty(&heap->free_list)) { if (total_drained >= size) break; + buffer = list_first_entry(&heap->free_list, struct ion_buffer, + list); list_del(&buffer->list); heap->free_list_size -= buffer->size; total_drained += buffer->size; + spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); + spin_lock(&heap->free_lock); } - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); return total_drained; } @@ -213,16 +217,16 @@ static int ion_heap_deferred_free(void *data) wait_event_freezable(heap->waitqueue, ion_heap_freelist_size(heap) > 0); - rt_mutex_lock(&heap->lock); + spin_lock(&heap->free_lock); if (list_empty(&heap->free_list)) { - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); continue; } buffer = list_first_entry(&heap->free_list, struct ion_buffer, list); list_del(&buffer->list); heap->free_list_size -= buffer->size; - rt_mutex_unlock(&heap->lock); + spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); } @@ -235,7 +239,7 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) INIT_LIST_HEAD(&heap->free_list); heap->free_list_size = 0; - rt_mutex_init(&heap->lock); + spin_lock_init(&heap->free_lock); init_waitqueue_head(&heap->waitqueue); heap->task = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index ac625b115057..58e84cc81486 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -160,7 +160,7 @@ struct ion_heap { struct shrinker shrinker; struct list_head free_list; size_t free_list_size; - struct rt_mutex lock; + spinlock_t free_lock; wait_queue_head_t waitqueue; struct task_struct *task; int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *); From 892e1580141cde0f80180e43f6c8c3dc356ddaf2 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 19 Dec 2013 15:56:23 -0800 Subject: [PATCH 034/147] ion_test: Add compat_ioctl support (v2) Prior to subitting this, Colin reworked the compat_ioctl support for the ion_test driver, moving the structure to be the same size on both 32 and 64 bit architectures. Two small things were left out. The compat_ioctl ptr assignment, and the fact that despite having uniform sized types in the structure, the structure pads out to different sizes on different arches. This patch resolves this issue by adding a padding entry after the write flag, and adding the compat_ioctl ptr. Changes in v2: - Add a padding int rather then making write a u64 Cc: Colin Cross Cc: Greg KH Cc: Android Kernel Team Signed-off-by: John Stultz --- drivers/staging/android/ion/ion_test.c | 1 + drivers/staging/android/uapi/ion_test.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c index 3e20349baf7c..654acb5c8eba 100644 --- a/drivers/staging/android/ion/ion_test.c +++ b/drivers/staging/android/ion/ion_test.c @@ -231,6 +231,7 @@ static int ion_test_release(struct inode *inode, struct file *file) static const struct file_operations ion_test_fops = { .owner = THIS_MODULE, .unlocked_ioctl = ion_test_ioctl, + .compat_ioctl = ion_test_ioctl, .open = ion_test_open, .release = ion_test_release, }; diff --git a/drivers/staging/android/uapi/ion_test.h b/drivers/staging/android/uapi/ion_test.h index 614d1e36f72c..ffef06f63133 100644 --- a/drivers/staging/android/uapi/ion_test.h +++ b/drivers/staging/android/uapi/ion_test.h @@ -32,6 +32,7 @@ struct ion_test_rw_data { __u64 offset; __u64 size; int write; + int __padding; }; #define ION_IOC_MAGIC 'I' From f3ae9a8286d63f13715d2082965d6b8849af05a5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 12 Dec 2013 17:50:35 -0800 Subject: [PATCH 035/147] ion: move shrinker out of heaps Every heap that uses deferred frees is going to need a shrinker to shrink the freelist under memory pressure. Rather than requiring each heap to implement a shrinker, automatically register a shrinker if the deferred free flag is set. The system heap also needs to shrink its page pools, so add a shrink function to the heap ops that will be called after shrinking the freelists. Change-Id: Icda722d683426fadb8ddd1c8e9499264ab682c57 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion.c | 3 + drivers/staging/android/ion/ion_heap.c | 38 +++++++++++ drivers/staging/android/ion/ion_page_pool.c | 7 +- drivers/staging/android/ion/ion_priv.h | 21 +++--- drivers/staging/android/ion/ion_system_heap.c | 66 +++++-------------- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7522b0be1749..1a85724ab22d 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1451,6 +1451,9 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_init_deferred_free(heap); + if ((heap->flags & ION_HEAP_FLAG_DEFER_FREE) || heap->ops->shrink) + ion_heap_init_shrinker(heap); + heap->dev = dev; down_write(&dev->lock); /* use negative heap->id to reverse the priority -- when traversing diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 96feebb6ad79..5c14bc2a1822 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -252,6 +252,44 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) return 0; } +static int ion_heap_shrink(struct shrinker *shrinker, struct shrink_control *sc) +{ + struct ion_heap *heap = container_of(shrinker, struct ion_heap, + shrinker); + int total = 0; + int freed = 0; + int to_scan = sc->nr_to_scan; + + if (to_scan == 0) + goto out; + + /* + * shrink the free list first, no point in zeroing the memory if we're + * just going to reclaim it + */ + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) + freed = ion_heap_freelist_drain(heap, to_scan * PAGE_SIZE) / + PAGE_SIZE; + + to_scan -= freed; + if (to_scan < 0) + to_scan = 0; + +out: + total = ion_heap_freelist_size(heap) / PAGE_SIZE; + if (heap->ops->shrink) + total += heap->ops->shrink(heap, sc->gfp_mask, to_scan); + return total; +} + +void ion_heap_init_shrinker(struct ion_heap *heap) +{ + heap->shrinker.shrink = ion_heap_shrink; + heap->shrinker.seeks = DEFAULT_SEEKS; + heap->shrinker.batch = 0; + register_shrinker(&heap->shrinker); +} + struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) { struct ion_heap *heap = NULL; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index f087a02770a8..0e20e62ec4bc 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -130,15 +130,11 @@ static int ion_page_pool_total(struct ion_page_pool *pool, bool high) int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, int nr_to_scan) { - int nr_freed = 0; int i; bool high; high = !!(gfp_mask & __GFP_HIGHMEM); - if (nr_to_scan == 0) - return ion_page_pool_total(pool, high); - for (i = 0; i < nr_to_scan; i++) { struct page *page; @@ -153,10 +149,9 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, } mutex_unlock(&pool->mutex); ion_page_pool_free_pages(pool, page); - nr_freed += (1 << pool->order); } - return nr_freed; + return ion_page_pool_total(pool, high); } struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 58e84cc81486..85866e6d2f92 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -114,6 +114,7 @@ struct ion_heap_ops { void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma); + int (*shrink)(struct ion_heap *heap, gfp_t gfp_mask, int nr_to_scan); }; /** @@ -132,10 +133,7 @@ struct ion_heap_ops { * allocating. These are specified by platform data and * MUST be unique * @name: used for debugging - * @shrinker: a shrinker for the heap, if the heap caches system - * memory, it must define a shrinker to return it on low - * memory conditions, this includes system memory cached - * in the deferred free lists for heaps that support it + * @shrinker: a shrinker for the heap * @free_list: free list head if deferred free is used * @free_list_size size of the deferred free list in bytes * @lock: protects the free list @@ -218,6 +216,16 @@ int ion_heap_map_user(struct ion_heap *, struct ion_buffer *, int ion_heap_buffer_zero(struct ion_buffer *buffer); int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot); +/** + * ion_heap_init_shrinker + * @heap: the heap + * + * If a heap sets the ION_HEAP_FLAG_DEFER_FREE flag or defines the shrink op + * this function will be called to setup a shrinker to shrink the freelists + * and call the heap's shrink op. + */ +void ion_heap_init_shrinker(struct ion_heap *heap); + /** * ion_heap_init_deferred_free -- initialize deferred free functionality * @heap: the heap @@ -305,13 +313,8 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr, * @low_count: number of lowmem items in the pool * @high_items: list of highmem items * @low_items: list of lowmem items - * @shrinker: a shrinker for the items * @mutex: lock protecting this struct and especially the count * item list - * @alloc: function to be used to allocate pageory when the pool - * is empty - * @free: function to be used to free pageory back to the system - * when the shrinker fires * @gfp_mask: gfp_mask to use from alloc * @order: order of pages in the pool * @list: plist node for list of pools diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 5bccf9e2c93c..4a87fcf53266 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -227,6 +227,23 @@ static void ion_system_heap_unmap_dma(struct ion_heap *heap, return; } +static int ion_system_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask, + int nr_to_scan) +{ + struct ion_system_heap *sys_heap; + int nr_total = 0; + int i; + + sys_heap = container_of(heap, struct ion_system_heap, heap); + + for (i = 0; i < num_orders; i++) { + struct ion_page_pool *pool = sys_heap->pools[i]; + nr_total += ion_page_pool_shrink(pool, gfp_mask, nr_to_scan); + } + + return nr_total; +} + static struct ion_heap_ops system_heap_ops = { .allocate = ion_system_heap_allocate, .free = ion_system_heap_free, @@ -235,52 +252,9 @@ static struct ion_heap_ops system_heap_ops = { .map_kernel = ion_heap_map_kernel, .unmap_kernel = ion_heap_unmap_kernel, .map_user = ion_heap_map_user, + .shrink = ion_system_heap_shrink, }; -static int ion_system_heap_shrink(struct shrinker *shrinker, - struct shrink_control *sc) { - - struct ion_heap *heap = container_of(shrinker, struct ion_heap, - shrinker); - struct ion_system_heap *sys_heap = container_of(heap, - struct ion_system_heap, - heap); - int nr_total = 0; - int nr_freed = 0; - int i; - - if (sc->nr_to_scan == 0) - goto end; - - /* shrink the free list first, no point in zeroing the memory if - we're just going to reclaim it */ - nr_freed += ion_heap_freelist_drain(heap, sc->nr_to_scan * PAGE_SIZE) / - PAGE_SIZE; - - if (nr_freed >= sc->nr_to_scan) - goto end; - - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - - nr_freed += ion_page_pool_shrink(pool, sc->gfp_mask, - sc->nr_to_scan); - if (nr_freed >= sc->nr_to_scan) - break; - } - -end: - /* total number of items is whatever the page pools are holding - plus whatever's in the freelist */ - for (i = 0; i < num_orders; i++) { - struct ion_page_pool *pool = sys_heap->pools[i]; - nr_total += ion_page_pool_shrink(pool, sc->gfp_mask, 0); - } - nr_total += ion_heap_freelist_size(heap) / PAGE_SIZE; - return nr_total; - -} - static int ion_system_heap_debug_show(struct ion_heap *heap, struct seq_file *s, void *unused) { @@ -328,10 +302,6 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *unused) heap->pools[i] = pool; } - heap->heap.shrinker.shrink = ion_system_heap_shrink; - heap->heap.shrinker.seeks = DEFAULT_SEEKS; - heap->heap.shrinker.batch = 0; - register_shrinker(&heap->heap.shrinker); heap->heap.debug_show = ion_system_heap_debug_show; return &heap->heap; err_create_pool: From 5ec06794e17b3c9ee1c59fa4ff6448a7f4384860 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Thu, 29 Aug 2013 15:28:58 -0700 Subject: [PATCH 036/147] gpu: ion: create separate heap and client debugfs directories It can be slightly annoying to figure out which files under the ion debugfs directory are heap debug files and which ones are client debug files. Create separate subdirectories under ion to hold the different types of debug files. Change-Id: Ic773ab619ef94b9b4d0f3794def9d37645c7c212 Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 57 ++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 1a85724ab22d..09a373f4afe9 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -59,6 +59,8 @@ struct ion_device { unsigned long arg); struct rb_root clients; struct dentry *debug_root; + struct dentry *heaps_debug_root; + struct dentry *clients_debug_root; }; /** @@ -763,8 +765,15 @@ struct ion_client *ion_client_create(struct ion_device *dev, snprintf(debug_name, 64, "%u", client->pid); client->debug_root = debugfs_create_file(debug_name, 0664, - dev->debug_root, client, - &debug_client_fops); + dev->clients_debug_root, + client, &debug_client_fops); + if (!client->debug_root) { + char buf[256], *path; + path = dentry_path(dev->clients_debug_root, buf, 256); + pr_err("Failed to create client debugfs at %s/%s\n", + path, debug_name); + } + up_write(&dev->lock); return client; @@ -1443,6 +1452,8 @@ DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get, void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) { + struct dentry *debug_file; + if (!heap->ops->allocate || !heap->ops->free || !heap->ops->map_dma || !heap->ops->unmap_dma) pr_err("%s: can not add heap with invalid ops struct.\n", @@ -1460,15 +1471,31 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) the list later attempt higher id numbers first */ plist_node_init(&heap->node, -heap->id); plist_add(&heap->node, &dev->heaps); - debugfs_create_file(heap->name, 0664, dev->debug_root, heap, - &debug_heap_fops); + debug_file = debugfs_create_file(heap->name, 0664, + dev->heaps_debug_root, heap, + &debug_heap_fops); + + if (!debug_file) { + char buf[256], *path; + path = dentry_path(dev->heaps_debug_root, buf, 256); + pr_err("Failed to create heap debugfs at %s/%s\n", + path, heap->name); + } + #ifdef DEBUG_HEAP_SHRINKER if (heap->shrinker.shrink) { char debug_name[64]; snprintf(debug_name, 64, "%s_shrink", heap->name); - debugfs_create_file(debug_name, 0644, dev->debug_root, heap, - &debug_shrink_fops); + debug_file = debugfs_create_file( + debug_name, 0644, dev->heaps_debug_root, heap, + &debug_shrink_fops); + if (!debug_file) { + char buf[256], *path; + path = dentry_path(dev->heaps_debug_root, buf, 256); + pr_err("Failed to create heap shrinker debugfs at %s/%s\n", + path, debug_name); + } } #endif up_write(&dev->lock); @@ -1497,8 +1524,21 @@ struct ion_device *ion_device_create(long (*custom_ioctl) } idev->debug_root = debugfs_create_dir("ion", NULL); - if (!idev->debug_root) - pr_err("ion: failed to create debug files.\n"); + if (!idev->debug_root) { + pr_err("ion: failed to create debugfs root directory.\n"); + goto debugfs_done; + } + idev->heaps_debug_root = debugfs_create_dir("heaps", idev->debug_root); + if (!idev->heaps_debug_root) { + pr_err("ion: failed to create debugfs heaps directory.\n"); + goto debugfs_done; + } + idev->clients_debug_root = debugfs_create_dir("clients", + idev->debug_root); + if (!idev->clients_debug_root) + pr_err("ion: failed to create debugfs clients directory.\n"); + +debugfs_done: idev->custom_ioctl = custom_ioctl; idev->buffers = RB_ROOT; @@ -1512,6 +1552,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) void ion_device_destroy(struct ion_device *dev) { misc_deregister(&dev->dev); + debugfs_remove_recursive(dev->debug_root); /* XXX need to free the heaps and clients ? */ kfree(dev); } From c95cd575f4ae04dbf59745f6f6f9e24f86571558 Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Mon, 5 Dec 2011 15:32:36 -0800 Subject: [PATCH 037/147] gpu: ion: Fix debugfs handling of multiple kernel clients Currently, Ion registers all debugfs entries for clients via pid. If there are multiple kernel clients, this means the debugfs entry only gets created for the first one. Fix this by creating debugfs entries by name always. When creating user clients, specify the name via the pid. Change-Id: I00cbb284d1c53b3362bb7be9c0275620a9fac167 Signed-off-by: Laura Abbott Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 09a373f4afe9..ada4a02e1ef2 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -718,7 +718,6 @@ struct ion_client *ion_client_create(struct ion_device *dev, struct rb_node **p; struct rb_node *parent = NULL; struct ion_client *entry; - char debug_name[64]; pid_t pid; get_task_struct(current->group_leader); @@ -763,15 +762,14 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_link_node(&client->node, parent, p); rb_insert_color(&client->node, &dev->clients); - snprintf(debug_name, 64, "%u", client->pid); - client->debug_root = debugfs_create_file(debug_name, 0664, + client->debug_root = debugfs_create_file(name, 0664, dev->clients_debug_root, client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, debug_name); + path, name); } up_write(&dev->lock); @@ -1302,9 +1300,11 @@ static int ion_open(struct inode *inode, struct file *file) struct miscdevice *miscdev = file->private_data; struct ion_device *dev = container_of(miscdev, struct ion_device, dev); struct ion_client *client; + char debug_name[64]; pr_debug("%s: %d\n", __func__, __LINE__); - client = ion_client_create(dev, "user"); + snprintf(debug_name, 64, "%u", task_pid_nr(current->group_leader)); + client = ion_client_create(dev, debug_name); if (IS_ERR(client)) return PTR_ERR(client); file->private_data = client; From 0d8b5323f86e992177e9995a7e5e0ee163575ee9 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Wed, 18 Dec 2013 22:10:07 -0800 Subject: [PATCH 038/147] ion: store a copy of the client name on client creation Currently, we copy the pointer passed in to ion_client_create without making a copy of the string itself. This approach is problematic since it relies on the client keeping the name string in working order. Change-Id: I62d79c7539b2c857a5a625339d49c9c892e8622d Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index ada4a02e1ef2..7627ffbc8360 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -734,19 +734,18 @@ struct ion_client *ion_client_create(struct ion_device *dev, task_unlock(current->group_leader); client = kzalloc(sizeof(struct ion_client), GFP_KERNEL); - if (!client) { - if (task) - put_task_struct(current->group_leader); - return ERR_PTR(-ENOMEM); - } + if (!client) + goto err_put_task_struct; client->dev = dev; client->handles = RB_ROOT; idr_init(&client->idr); mutex_init(&client->lock); - client->name = name; client->task = task; client->pid = pid; + client->name = kstrdup(name, GFP_KERNEL); + if (!client->name) + goto err_free_client; down_write(&dev->lock); p = &dev->clients.rb_node; @@ -775,6 +774,13 @@ struct ion_client *ion_client_create(struct ion_device *dev, up_write(&dev->lock); return client; + +err_free_client: + kfree(client); +err_put_task_struct: + if (task) + put_task_struct(current->group_leader); + return ERR_PTR(-ENOMEM); } EXPORT_SYMBOL(ion_client_create); @@ -799,6 +805,7 @@ void ion_client_destroy(struct ion_client *client) debugfs_remove_recursive(client->debug_root); up_write(&dev->lock); + kfree(client->name); kfree(client); } EXPORT_SYMBOL(ion_client_destroy); From 550640ca7aec7789cdd52742b4c1d9dd712a5dd8 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Mon, 7 Oct 2013 09:24:29 -0700 Subject: [PATCH 039/147] gpu: ion: make sure all clients are exposed in debugfs Currently, if multiple Ion clients are created with the same name, only the first one shows up in debugfs. Rectify this by adding a monotonically-increasing serial number to the debug names of Ion clients. Change-Id: I000e45055d5029c7bccd88c36b238736929da3a5 Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion.c | 38 +++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 7627ffbc8360..48774e3974aa 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -71,6 +71,8 @@ struct ion_device { * @idr: an idr space for allocating handle ids * @lock: lock protecting the tree of handles * @name: used for debugging + * @display_name: used for debugging (unique version of @name) + * @display_serial: used for debugging (to make display_name unique) * @task: used for debugging * * A client represents a list of buffers this client may access. @@ -84,6 +86,8 @@ struct ion_client { struct idr idr; struct mutex lock; const char *name; + char *display_name; + int display_serial; struct task_struct *task; pid_t pid; struct dentry *debug_root; @@ -710,6 +714,21 @@ static const struct file_operations debug_client_fops = { .release = single_release, }; +static int ion_get_client_serial(const struct rb_root *root, + const unsigned char *name) +{ + int serial = -1; + struct rb_node *node; + for (node = rb_first(root); node; node = rb_next(node)) { + struct ion_client *client = rb_entry(node, struct ion_client, + node); + if (strcmp(client->name, name)) + continue; + serial = max(serial, client->display_serial); + } + return serial + 1; +} + struct ion_client *ion_client_create(struct ion_device *dev, const char *name) { @@ -720,6 +739,11 @@ struct ion_client *ion_client_create(struct ion_device *dev, struct ion_client *entry; pid_t pid; + if (!name) { + pr_err("%s: Name cannot be null\n", __func__); + return ERR_PTR(-EINVAL); + } + get_task_struct(current->group_leader); task_lock(current->group_leader); pid = task_pid_nr(current->group_leader); @@ -748,6 +772,13 @@ struct ion_client *ion_client_create(struct ion_device *dev, goto err_free_client; down_write(&dev->lock); + client->display_serial = ion_get_client_serial(&dev->clients, name); + client->display_name = kasprintf( + GFP_KERNEL, "%s-%d", name, client->display_serial); + if (!client->display_name) { + up_write(&dev->lock); + goto err_free_client_name; + } p = &dev->clients.rb_node; while (*p) { parent = *p; @@ -761,20 +792,22 @@ struct ion_client *ion_client_create(struct ion_device *dev, rb_link_node(&client->node, parent, p); rb_insert_color(&client->node, &dev->clients); - client->debug_root = debugfs_create_file(name, 0664, + client->debug_root = debugfs_create_file(client->display_name, 0664, dev->clients_debug_root, client, &debug_client_fops); if (!client->debug_root) { char buf[256], *path; path = dentry_path(dev->clients_debug_root, buf, 256); pr_err("Failed to create client debugfs at %s/%s\n", - path, name); + path, client->display_name); } up_write(&dev->lock); return client; +err_free_client_name: + kfree(client->name); err_free_client: kfree(client); err_put_task_struct: @@ -805,6 +838,7 @@ void ion_client_destroy(struct ion_client *client) debugfs_remove_recursive(client->debug_root); up_write(&dev->lock); + kfree(client->display_name); kfree(client->name); kfree(client); } From 14f162cb64a8beca59f06cd94d5569bd550dc99d Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Tue, 6 Aug 2013 15:08:23 -0700 Subject: [PATCH 040/147] ion: Add private buffer flag to skip page pooling on free Currently, when we free a buffer it might actually just go back into a heap-specific page pool rather than going back to the system. This poses a problem because sometimes (like when we're running a shrinker in low memory conditions) we need to force the memory associated with the buffer to truly be relinquished to the system rather than just going back into a page pool. There isn't a use case for this flag by Ion clients, so make it a private flag. The main use case right now is to provide a mechanism for the deferred free code to force stale buffers to bypass page pooling. Change-Id: I724f89cc037083fe8576784363caa18a34e8705a Signed-off-by: Mitchel Humpherys --- drivers/staging/android/ion/ion_heap.c | 19 +++++++-- drivers/staging/android/ion/ion_priv.h | 42 ++++++++++++++++++- drivers/staging/android/ion/ion_system_heap.c | 4 +- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 5c14bc2a1822..750b76af0cf3 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -178,7 +178,8 @@ size_t ion_heap_freelist_size(struct ion_heap *heap) return size; } -size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) +static size_t _ion_heap_freelist_drain(struct ion_heap *heap, size_t size, + bool skip_pools) { struct ion_buffer *buffer; size_t total_drained = 0; @@ -197,6 +198,8 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) list); list_del(&buffer->list); heap->free_list_size -= buffer->size; + if (skip_pools) + buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; total_drained += buffer->size; spin_unlock(&heap->free_lock); ion_buffer_destroy(buffer); @@ -207,6 +210,16 @@ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) return total_drained; } +size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size) +{ + return _ion_heap_freelist_drain(heap, size, false); +} + +size_t ion_heap_freelist_shrink(struct ion_heap *heap, size_t size) +{ + return _ion_heap_freelist_drain(heap, size, true); +} + static int ion_heap_deferred_free(void *data) { struct ion_heap *heap = data; @@ -265,10 +278,10 @@ static int ion_heap_shrink(struct shrinker *shrinker, struct shrink_control *sc) /* * shrink the free list first, no point in zeroing the memory if we're - * just going to reclaim it + * just going to reclaim it. Also, skip any possible page pooling. */ if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) - freed = ion_heap_freelist_drain(heap, to_scan * PAGE_SIZE) / + freed = ion_heap_freelist_shrink(heap, to_scan * PAGE_SIZE) / PAGE_SIZE; to_scan -= freed; diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h index 85866e6d2f92..18ef365e7552 100644 --- a/drivers/staging/android/ion/ion_priv.h +++ b/drivers/staging/android/ion/ion_priv.h @@ -38,6 +38,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); * @dev: back pointer to the ion_device * @heap: back pointer to the heap the buffer came from * @flags: buffer specific flags + * @private_flags: internal buffer specific flags * @size: size of the buffer * @priv_virt: private data to the buffer representable as * a void * @@ -66,6 +67,7 @@ struct ion_buffer { struct ion_device *dev; struct ion_heap *heap; unsigned long flags; + unsigned long private_flags; size_t size; union { void *priv_virt; @@ -98,7 +100,11 @@ void ion_buffer_destroy(struct ion_buffer *buffer); * @map_user map memory to userspace * * allocate, phys, and map_user return 0 on success, -errno on error. - * map_dma and map_kernel return pointer on success, ERR_PTR on error. + * map_dma and map_kernel return pointer on success, ERR_PTR on + * error. @free will be called with ION_PRIV_FLAG_SHRINKER_FREE set in + * the buffer's private_flags when called from a shrinker. In that + * case, the pages being free'd must be truly free'd back to the + * system, not put in a page pool or otherwise cached. */ struct ion_heap_ops { int (*allocate) (struct ion_heap *heap, @@ -122,6 +128,17 @@ struct ion_heap_ops { */ #define ION_HEAP_FLAG_DEFER_FREE (1 << 0) +/** + * private flags - flags internal to ion + */ +/* + * Buffer is being freed from a shrinker function. Skip any possible + * heap-specific caching mechanism (e.g. page pools). Guarantees that + * any buffer storage that came from the system allocator will be + * returned to the system allocator. + */ +#define ION_PRIV_FLAG_SHRINKER_FREE (1 << 0) + /** * struct ion_heap - represents a heap in the system * @node: rb node to put the heap on the device's tree of heaps @@ -257,6 +274,29 @@ void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); */ size_t ion_heap_freelist_drain(struct ion_heap *heap, size_t size); +/** + * ion_heap_freelist_shrink - drain the deferred free + * list, skipping any heap-specific + * pooling or caching mechanisms + * + * @heap: the heap + * @size: amount of memory to drain in bytes + * + * Drains the indicated amount of memory from the deferred freelist immediately. + * Returns the total amount freed. The total freed may be higher depending + * on the size of the items in the list, or lower if there is insufficient + * total memory on the freelist. + * + * Unlike with @ion_heap_freelist_drain, don't put any pages back into + * page pools or otherwise cache the pages. Everything must be + * genuinely free'd back to the system. If you're free'ing from a + * shrinker you probably want to use this. Note that this relies on + * the heap.ops.free callback honoring the ION_PRIV_FLAG_SHRINKER_FREE + * flag. + */ +size_t ion_heap_freelist_shrink(struct ion_heap *heap, + size_t size); + /** * ion_heap_freelist_size - returns the size of the freelist in bytes * @heap: the heap diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 4a87fcf53266..a2c8968104f8 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -90,7 +90,7 @@ static void free_buffer_page(struct ion_system_heap *heap, { bool cached = ion_buffer_cached(buffer); - if (!cached) { + if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) { struct ion_page_pool *pool = heap->pools[order_to_index(order)]; ion_page_pool_free(pool, page); } else { @@ -205,7 +205,7 @@ static void ion_system_heap_free(struct ion_buffer *buffer) /* uncached pages come from the page pools, zero them before returning for security purposes (other allocations are zerod at alloc time */ - if (!cached) + if (!cached && !(buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)) ion_heap_buffer_zero(buffer); for_each_sg(table->sgl, sg, table->nents, i) From c69de844c80884167bb42243b36498dde81eebf6 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 19 Dec 2013 18:37:49 -0800 Subject: [PATCH 041/147] ion: fix overflow and list bugs in system heap Fix a few bugs in ion_system_heap: Initialize the list node in the info block. Don't store size_remaining in a signed long, allocating >2GB could overflow, resulting in a call to sg_alloc_table with nents=0 which panics. alloc_largest_available will never return a block larger than size_remanining, so it can never go negative. Limit a single allocation to half of all memory. Prevents a large allocation from taking down the whole system. Change-Id: I7fcbd7e1d5b4d482d7612d80b6c9e8e24466f1d8 Signed-off-by: Colin Cross --- drivers/staging/android/ion/ion_system_heap.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index a2c8968104f8..a052418d2efc 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -124,6 +124,7 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap, info->page = page; info->order = orders[i]; + INIT_LIST_HEAD(&info->list); return info; } kfree(info); @@ -145,12 +146,15 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct list_head pages; struct page_info *info, *tmp_info; int i = 0; - long size_remaining = PAGE_ALIGN(size); + unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; if (align > PAGE_SIZE) return -EINVAL; + if (size / PAGE_SIZE > totalram_pages / 2) + return -ENOMEM; + INIT_LIST_HEAD(&pages); while (size_remaining > 0) { info = alloc_largest_available(sys_heap, buffer, size_remaining, From c5149b1e38ecd5c3f3d3add7fc118fb47b719929 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 27 Dec 2013 15:20:32 -0800 Subject: [PATCH 042/147] android: configs: add TIMER_STATS back, helps with sysrq t. Change-Id: I8fe033090e38523152225dcfb7a1828f530a0757 Signed-off-by: JP Abgrall (cherry picked from commit 7aee29d6482954ac9fecae3ce8a90b6759158107) --- android/configs/android-recommended.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 32596bc2e199..9caa089c5d19 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -106,6 +106,7 @@ CONFIG_TABLET_USB_GTCO=y CONFIG_TABLET_USB_HANWANG=y CONFIG_TABLET_USB_KBTAB=y CONFIG_TABLET_USB_WACOM=y +CONFIG_TIMER_STATS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_UHID=y From 0715d10b9e6c04327adb189e13ecd6a3c2df48ce Mon Sep 17 00:00:00 2001 From: Chih-Wei Huang Date: Tue, 24 Dec 2013 17:51:55 +0800 Subject: [PATCH 043/147] cpufreq: interactive: fix compiling warnings The gcc warns like: cpufreq_interactive.c:745:6: warning: operation on 'ret' may be undefined [-Wsequence-point] It was introduced by commit cf0fad49d17cb8273ce555dd5b7afab67d7923bf. Since sprintf(...) just return 1 (one character) in this case, ret should not changed. Just discarding the result of sprintf(...) leads to the result that the committer of cf0fad49d17cb8273ce555dd5b7afab67d7923bf wants. Change-Id: Ifed1cef6d6a31c3ed23dad03a567b3b9eddf3a57 Signed-off-by: Chih-Wei Huang --- drivers/cpufreq/cpufreq_interactive.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index d72e8c458f69..9f63bd1e4fee 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -752,7 +752,7 @@ static ssize_t show_target_loads( ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i], i & 0x1 ? ":" : " "); - ret += sprintf(buf + --ret, "\n"); + sprintf(buf + ret - 1, "\n"); spin_unlock_irqrestore(&tunables->target_loads_lock, flags); return ret; } @@ -792,7 +792,7 @@ static ssize_t show_above_hispeed_delay( tunables->above_hispeed_delay[i], i & 0x1 ? ":" : " "); - ret += sprintf(buf + --ret, "\n"); + sprintf(buf + ret - 1, "\n"); spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); return ret; } From 7bb429f0dc58fbb1248e986638d2b117650025da Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Tue, 7 Jan 2014 14:25:28 -0800 Subject: [PATCH 044/147] android: configs: add IPV6 ROUTE INFO Change-Id: I54cba86bce703647c4be8eee5592d55374ad02ef Signed-off-by: JP Abgrall (cherry picked from commit 5e35d662616142d308ce24c9d552e469f60d8695) --- android/configs/android-base.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index a9597658ef14..1fb9bb5b1ac6 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -35,6 +35,7 @@ CONFIG_IPV6_MIP6=y CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_OPTIMISTIC_DAD=y CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTE_INFO=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y From b77f9f883dea9d7c73687bb400d5f8ce89aea182 Mon Sep 17 00:00:00 2001 From: Ajay Nandakumar Date: Thu, 25 Apr 2013 14:12:29 +0530 Subject: [PATCH 045/147] Revert "PM / Sleep: Require CAP_BLOCK_SUSPEND to use wake_lock/wake_unlock" This reverts commit 11388c87d2abca1f01975ced28ce9eacea239104. The issue is that no wake lock is held at the user space i.e by Power Manager service.This is because the PowerManagerService fails to acquire the Wakelock.In 3.8 the wakelock module in the kernel expects the user process to have the capability of CAP_BLOCK_SUSPEND.Which the powermangersevice does not have. Bug 1274297 Bug 1384311 Change-Id: I3b696108d47278cf40abce8d5a9bd012f98f2925 Signed-off-by: Ajay Nandakumar (cherry picked from commit e8464e785027a15279a13e6e32cd1aecd22d5a00) Reviewed-on: http://git-master/r/282698 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bharat Nihalani Tested-by: Bharat Nihalani --- kernel/power/wakelock.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c index 8f50de394d22..c8fba3380076 100644 --- a/kernel/power/wakelock.c +++ b/kernel/power/wakelock.c @@ -9,7 +9,6 @@ * manipulate wakelocks on Android. */ -#include #include #include #include @@ -189,9 +188,6 @@ int pm_wake_lock(const char *buf) size_t len; int ret = 0; - if (!capable(CAP_BLOCK_SUSPEND)) - return -EPERM; - while (*str && !isspace(*str)) str++; @@ -235,9 +231,6 @@ int pm_wake_unlock(const char *buf) size_t len; int ret = 0; - if (!capable(CAP_BLOCK_SUSPEND)) - return -EPERM; - len = strlen(buf); if (!len) return -EINVAL; From 984f4ccce87f652d2effeb5cbaf87a9c16c869d9 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Thu, 7 Nov 2013 16:08:52 -0800 Subject: [PATCH 046/147] ion: Add dummy driver for testing Provide a basic dummy driver to register the ion device and to install basic SYSTEM and SYSTEM_CONTIG heaps. This allows for basic testing with ION without having access to drivers or systems that have been enabled to use ION. Cc: Colin Cross Cc: Greg KH Cc: Jesse Barker Cc: Android Kernel Team Signed-off-by: John Stultz --- drivers/staging/android/ion/Kconfig | 10 ++ drivers/staging/android/ion/Makefile | 3 + .../staging/android/ion/ion_dummy_driver.c | 93 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 drivers/staging/android/ion/ion_dummy_driver.c diff --git a/drivers/staging/android/ion/Kconfig b/drivers/staging/android/ion/Kconfig index a9a64ea2343f..0f8fec1f84e5 100644 --- a/drivers/staging/android/ion/Kconfig +++ b/drivers/staging/android/ion/Kconfig @@ -17,6 +17,16 @@ config ION_TEST Choose this option to create a device that can be used to test the kernel and device side ION functions. +config ION_DUMMY + bool "Dummy Ion driver" + depends on ION + help + Provides a dummy ION driver that registers the + /dev/ion device and some basic heaps. This can + be used for testing the ION infrastructure if + one doesn't have access to hardware drivers that + use ION. + config ION_TEGRA tristate "Ion for Tegra" depends on ARCH_TEGRA && ION diff --git a/drivers/staging/android/ion/Makefile b/drivers/staging/android/ion/Makefile index 75039b98eebb..b56fd2bf2b4f 100644 --- a/drivers/staging/android/ion/Makefile +++ b/drivers/staging/android/ion/Makefile @@ -4,4 +4,7 @@ obj-$(CONFIG_ION_TEST) += ion_test.o ifdef CONFIG_COMPAT obj-$(CONFIG_ION) += compat_ion.o endif + +obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o obj-$(CONFIG_ION_TEGRA) += tegra/ + diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c new file mode 100644 index 000000000000..6749d29d6004 --- /dev/null +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -0,0 +1,93 @@ +/* + * drivers/gpu/ion/ion_dummy_driver.c + * + * Copyright (C) 2013 Linaro, Inc + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "ion.h" +#include "ion_priv.h" + +struct ion_device *idev; +struct ion_heap **heaps; + +struct ion_platform_heap dummy_heaps[] = { + { + .id = ION_HEAP_TYPE_SYSTEM, + .type = ION_HEAP_TYPE_SYSTEM, + .name = "system", + }, + { + .id = ION_HEAP_TYPE_SYSTEM_CONTIG, + .type = ION_HEAP_TYPE_SYSTEM_CONTIG, + .name = "system contig", + }, +}; + +struct ion_platform_data dummy_ion_pdata = { + .nr = 2, + .heaps = dummy_heaps, +}; + +static int __init ion_dummy_init(void) +{ + int i, err; + + idev = ion_device_create(NULL); + heaps = kzalloc(sizeof(struct ion_heap *) * dummy_ion_pdata.nr, + GFP_KERNEL); + if (!heaps) + return PTR_ERR(heaps); + + for (i = 0; i < dummy_ion_pdata.nr; i++) { + struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i]; + + heaps[i] = ion_heap_create(heap_data); + if (IS_ERR_OR_NULL(heaps[i])) { + err = PTR_ERR(heaps[i]); + goto err; + } + ion_device_add_heap(idev, heaps[i]); + } + return 0; +err: + for (i = 0; i < dummy_ion_pdata.nr; i++) { + if (heaps[i]) + ion_heap_destroy(heaps[i]); + } + kfree(heaps); + + return err; +} + +static void __exit ion_dummy_exit(void) +{ + int i; + + ion_device_destroy(idev); + + for (i = 0; i < dummy_ion_pdata.nr; i++) + ion_heap_destroy(heaps[i]); + kfree(heaps); + + return; +} + +module_init(ion_dummy_init); +module_exit(ion_dummy_exit); + From ec0700adad5625639db1cacc32e2f20c0d627413 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 22 Nov 2013 19:45:31 -0800 Subject: [PATCH 047/147] ion: Add carveout and chunk heaps to dummy driver Add support to the dummy driver for basic carveout and chunk heaps. Since we're generating these heaps at module_init, and we want this driver to be generic enough to be tested on any arch, we don't have the ability to alloc bootmem, so both of these heaps are conventionally allocated using alloc_pages(), which limits us to 4M in size. Should look into using CMA for heap allocation eventually, but this provides enough to test the basic functionality of the heaps. Cc: Colin Cross Cc: Greg KH Cc: Jesse Barker Cc: Android Kernel Team Signed-off-by: John Stultz --- .../staging/android/ion/ion_dummy_driver.c | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_dummy_driver.c b/drivers/staging/android/ion/ion_dummy_driver.c index 6749d29d6004..55b2002753f2 100644 --- a/drivers/staging/android/ion/ion_dummy_driver.c +++ b/drivers/staging/android/ion/ion_dummy_driver.c @@ -26,6 +26,9 @@ struct ion_device *idev; struct ion_heap **heaps; +void *carveout_ptr; +void *chunk_ptr; + struct ion_platform_heap dummy_heaps[] = { { .id = ION_HEAP_TYPE_SYSTEM, @@ -37,10 +40,24 @@ struct ion_platform_heap dummy_heaps[] = { .type = ION_HEAP_TYPE_SYSTEM_CONTIG, .name = "system contig", }, + { + .id = ION_HEAP_TYPE_CARVEOUT, + .type = ION_HEAP_TYPE_CARVEOUT, + .name = "carveout", + .size = SZ_4M, + }, + { + .id = ION_HEAP_TYPE_CHUNK, + .type = ION_HEAP_TYPE_CHUNK, + .name = "chunk", + .size = SZ_4M, + .align = SZ_16K, + .priv = (void *)(SZ_16K), + }, }; struct ion_platform_data dummy_ion_pdata = { - .nr = 2, + .nr = 4, .heaps = dummy_heaps, }; @@ -54,9 +71,36 @@ static int __init ion_dummy_init(void) if (!heaps) return PTR_ERR(heaps); + + /* Allocate a dummy carveout heap */ + carveout_ptr = alloc_pages_exact( + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size, + GFP_KERNEL); + if (carveout_ptr) + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].base = + virt_to_phys(carveout_ptr); + else + pr_err("ion_dummy: Could not allocate carveout\n"); + + /* Allocate a dummy chunk heap */ + chunk_ptr = alloc_pages_exact( + dummy_heaps[ION_HEAP_TYPE_CHUNK].size, + GFP_KERNEL); + if (chunk_ptr) + dummy_heaps[ION_HEAP_TYPE_CHUNK].base = virt_to_phys(chunk_ptr); + else + pr_err("ion_dummy: Could not allocate chunk\n"); + for (i = 0; i < dummy_ion_pdata.nr; i++) { struct ion_platform_heap *heap_data = &dummy_ion_pdata.heaps[i]; + if (heap_data->type == ION_HEAP_TYPE_CARVEOUT && + !heap_data->base) + continue; + + if (heap_data->type == ION_HEAP_TYPE_CHUNK && !heap_data->base) + continue; + heaps[i] = ion_heap_create(heap_data); if (IS_ERR_OR_NULL(heaps[i])) { err = PTR_ERR(heaps[i]); @@ -72,6 +116,16 @@ static int __init ion_dummy_init(void) } kfree(heaps); + if (carveout_ptr) { + free_pages_exact(carveout_ptr, + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + carveout_ptr = NULL; + } + if (chunk_ptr) { + free_pages_exact(chunk_ptr, + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + chunk_ptr = NULL; + } return err; } @@ -85,6 +139,17 @@ static void __exit ion_dummy_exit(void) ion_heap_destroy(heaps[i]); kfree(heaps); + if (carveout_ptr) { + free_pages_exact(carveout_ptr, + dummy_heaps[ION_HEAP_TYPE_CARVEOUT].size); + carveout_ptr = NULL; + } + if (chunk_ptr) { + free_pages_exact(chunk_ptr, + dummy_heaps[ION_HEAP_TYPE_CHUNK].size); + chunk_ptr = NULL; + } + return; } From 7b397ae09a9d11abdbb6c3d2f1ce52cd58db3aca Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:43 +0100 Subject: [PATCH 048/147] staging: android: binder: modify struct binder_write_read to use size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change mirrors the userspace operation where struct binder_write_read members that specify the buffer size and consumed size are size_t elements. The patch also fixes the binder_thread_write() and binder_thread_read() functions prototypes to conform with the definition of binder_write_read. The changes do not affect existing 32bit ABI. Change-Id: I987246d507b9c5e4627c62a1da971d11869ac5a0 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 10 +++++----- drivers/staging/android/uapi/binder.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index f8d5b03f5444..59e714cd8e1b 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1719,7 +1719,7 @@ static void binder_transaction(struct binder_proc *proc, } int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, signed long *consumed) + void __user *buffer, size_t size, size_t *consumed) { uint32_t cmd; void __user *ptr = buffer + *consumed; @@ -2099,8 +2099,8 @@ static int binder_has_thread_work(struct binder_thread *thread) static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, - signed long *consumed, int non_block) + void __user *buffer, size_t size, + size_t *consumed, int non_block) { void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2597,7 +2597,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %ld at %08lx, read %ld at %08lx\n", + "%d:%d write %zd at %08lx, read %zd at %08lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); @@ -2623,7 +2623,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d wrote %ld of %ld, read return %ld of %ld\n", + "%d:%d wrote %zd of %zd, read return %zd of %zd\n", proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index b6cb483592ca..9e19f64e25aa 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -67,11 +67,11 @@ struct flat_binder_object { */ struct binder_write_read { - signed long write_size; /* bytes to write */ - signed long write_consumed; /* bytes consumed by driver */ + size_t write_size; /* bytes to write */ + size_t write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; - signed long read_size; /* bytes to read */ - signed long read_consumed; /* bytes consumed by driver */ + size_t read_size; /* bytes to read */ + size_t read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; }; From b91bf7c0044e13ff0e28bf96c2a8265d3438ba11 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:44 +0100 Subject: [PATCH 049/147] staging: android: binder: fix BINDER_SET_MAX_THREADS declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change will fix the BINDER_SET_MAX_THREADS ioctl to use __u32 instead of size_t for setting the max threads. Thus using the same handler for 32 and 64bit kernels. This value is stored internally in struct binder_proc and set to 15 on open_binder() in the libbinder API(thus no need for a 64bit size_t on 64bit platforms). The change does not affect existing 32bit ABI. Change-Id: Ibdfe10a70d475a91c247dc36e9cfd74a259d50e4 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 9e19f64e25aa..db9abe37ac94 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -86,7 +86,7 @@ struct binder_version { #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) -#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t) +#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) From 6fcd5e8cd07c1abc3ed37bd4cc5d87451b3ae191 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:45 +0100 Subject: [PATCH 050/147] staging: android: binder: fix BC_FREE_BUFFER ioctl declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BinderDriverCommands mirror the ioctl usage. Thus the size of the structure passed through the interface should be used to generate the ioctl No. The change reflects the type being passed from the user space-a pointer to a binder_buffer. This change should not affect the existing 32bit user space since BC_FREE_BUFFER is computed as: #define _IOW(type,nr,size) \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) and for a 32bit compiler BC_FREE_BUFFER will have the same computed value. This change will also ease our work in differentiating BC_FREE_BUFFER from COMPAT_BC_FREE_BUFFER. The change does not affect existing 32bit ABI. Change-Id: I2e0ae87bc4e913225a8eb2912913f7e3617cb575 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index db9abe37ac94..3de85afb5b69 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -265,7 +265,7 @@ enum binder_driver_command_protocol { * Else you have acquired a primary reference on the object. */ - BC_FREE_BUFFER = _IOW('c', 3, int), + BC_FREE_BUFFER = _IOW('c', 3, void *), /* * void *: ptr to transaction data received on a read */ From 6780a236302cc482c3261d03aec4f54437533500 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:46 +0100 Subject: [PATCH 051/147] staging: android: binder: fix alignment issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Android userspace aligns the data written to the binder buffers to 4bytes. Thus for 32bit platforms or 64bit platforms running an 32bit Android userspace we can have a buffer looking like this: platform buffer(binder_cmd pointer) size 32/32 32b 32b 8B 64/32 32b 64b 12B 64/64 32b 64b 12B Thus the kernel needs to check that the buffer size is aligned to 4bytes not to (void *) that will be 8bytes on 64bit machines. The change does not affect existing 32bit ABI. Change-Id: I7535f07301519623ea6334f525d312d687407ed4 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 59e714cd8e1b..6e8b0e742405 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1249,7 +1249,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { pr_err("transaction release %d bad offset %zd, size %zd\n", debug_id, *offp, buffer->data_size); continue; @@ -1502,7 +1502,7 @@ static void binder_transaction(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { binder_user_error("%d:%d got transaction with invalid offset, %zd\n", proc->pid, thread->pid, *offp); return_error = BR_FAILED_REPLY; From 7e3039eda270f9820a3840f74057dd856bdeff1b Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:47 +0100 Subject: [PATCH 052/147] staging: android: binder: replace types with portable ones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this driver is meant to be used on different types of processors and a portable driver should specify the size a variable expects to be this patch changes the types used throughout the binder interface. We use "userspace" types since this header will be exported and used by the Android filesystem. The patch does not change in any way the functionality of the binder driver. Change-Id: Ib26daab8bc44b92d4a09badc8ecb64d37ee8773b Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 3de85afb5b69..e1f547bb485f 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -123,10 +123,10 @@ struct binder_transaction_data { void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ - unsigned int code; /* transaction command */ + __u32 code; /* transaction command */ /* General information about the transaction. */ - unsigned int flags; + __u32 flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ @@ -143,7 +143,7 @@ struct binder_transaction_data { /* offsets from buffer to flat_binder_object structs */ const void __user *offsets; } ptr; - uint8_t buf[8]; + __u8 buf[8]; } data; }; @@ -153,18 +153,18 @@ struct binder_ptr_cookie { }; struct binder_pri_desc { - int priority; - int desc; + __s32 priority; + __s32 desc; }; struct binder_pri_ptr_cookie { - int priority; + __s32 priority; void *ptr; void *cookie; }; enum binder_driver_return_protocol { - BR_ERROR = _IOR('r', 0, int), + BR_ERROR = _IOR('r', 0, __s32), /* * int: error code */ @@ -178,7 +178,7 @@ enum binder_driver_return_protocol { * binder_transaction_data: the received command. */ - BR_ACQUIRE_RESULT = _IOR('r', 4, int), + BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), /* * not currently supported * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. @@ -258,7 +258,7 @@ enum binder_driver_command_protocol { * binder_transaction_data: the sent command. */ - BC_ACQUIRE_RESULT = _IOW('c', 2, int), + BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), /* * not currently supported * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. @@ -270,10 +270,10 @@ enum binder_driver_command_protocol { * void *: ptr to transaction data received on a read */ - BC_INCREFS = _IOW('c', 4, int), - BC_ACQUIRE = _IOW('c', 5, int), - BC_RELEASE = _IOW('c', 6, int), - BC_DECREFS = _IOW('c', 7, int), + BC_INCREFS = _IOW('c', 4, __u32), + BC_ACQUIRE = _IOW('c', 5, __u32), + BC_RELEASE = _IOW('c', 6, __u32), + BC_DECREFS = _IOW('c', 7, __u32), /* * int: descriptor */ From c44aa763f58444937c8320171e08ceffde811ba7 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:48 +0100 Subject: [PATCH 053/147] staging: android: binder: fix binder interface for 64bit compat layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes in this patch will fix the binder interface for use on 64bit machines and stand as the base of the 64bit compat support. The changes apply to the structures that are passed between the kernel and userspace. Most of the changes applied mirror the change to struct binder_version where there is no need for a 64bit wide protocol_version(on 64bit machines). The change inlines with the existing 32bit userspace(the structure has the same size) and simplifies the compat layer such that the same handler can service the BINDER_VERSION ioctl. Other changes make use of kernel types as well as user-exportable ones and fix format specifier issues. The changes do not affect existing 32bit ABI. Change-Id: Icccc8d47c302930cc61cddc5749b4cc74dc84117 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 20 ++++++++++---------- drivers/staging/android/uapi/binder.h | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 6e8b0e742405..b9a7d9347784 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1273,7 +1273,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - pr_err("transaction release %d bad handle %ld\n", + pr_err("transaction release %d bad handle %d\n", debug_id, fp->handle); break; } @@ -1285,13 +1285,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_FD: binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld\n", fp->handle); + " fd %d\n", fp->handle); if (failed_at) task_close_fd(proc, fp->handle); break; default: - pr_err("transaction release %d bad object type %lx\n", + pr_err("transaction release %d bad object type %x\n", debug_id, fp->type); break; } @@ -1557,7 +1557,7 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - binder_user_error("%d:%d got transaction with invalid handle, %ld\n", + binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; @@ -1604,13 +1604,13 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { - binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if (!target_node->accept_fds) { - binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; @@ -1618,7 +1618,7 @@ static void binder_transaction(struct binder_proc *proc, file = fget(fp->handle); if (file == NULL) { - binder_user_error("%d:%d got transaction with invalid fd, %ld\n", + binder_user_error("%d:%d got transaction with invalid fd, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fget_failed; @@ -1637,13 +1637,13 @@ static void binder_transaction(struct binder_proc *proc, task_fd_install(target_proc, target_fd, file); trace_binder_transaction_fd(t, fp->handle, target_fd); binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld -> %d\n", fp->handle, target_fd); + " fd %d -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; default: - binder_user_error("%d:%d got transaction with invalid object type, %lx\n", + binder_user_error("%d:%d got transaction with invalid object type, %x\n", proc->pid, thread->pid, fp->type); return_error = BR_FAILED_REPLY; goto err_bad_object_type; @@ -2597,7 +2597,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %zd at %08lx, read %zd at %08lx\n", + "%d:%d write %zd at %016lx, read %zd at %016lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index e1f547bb485f..e76cfa876daa 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -48,13 +48,13 @@ enum { */ struct flat_binder_object { /* 8 bytes for large_flat_header. */ - unsigned long type; - unsigned long flags; + __u32 type; + __u32 flags; /* 8 bytes of data. */ union { void __user *binder; /* local object */ - signed long handle; /* remote object */ + __u32 handle; /* remote object */ }; /* extra data associated with local object */ @@ -78,7 +78,7 @@ struct binder_write_read { /* Use with BINDER_VERSION, driver fills in fields. */ struct binder_version { /* driver protocol version -- increment with incompatible change */ - signed long protocol_version; + __s32 protocol_version; }; /* This is the current protocol version. */ @@ -119,7 +119,7 @@ struct binder_transaction_data { * identifying the target and contents of the transaction. */ union { - size_t handle; /* target descriptor of command transaction */ + __u32 handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ @@ -154,7 +154,7 @@ struct binder_ptr_cookie { struct binder_pri_desc { __s32 priority; - __s32 desc; + __u32 desc; }; struct binder_pri_ptr_cookie { From e6395fe2411c2dda02c6052c7bbca32b56f10026 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 15 Jan 2014 11:28:36 +0000 Subject: [PATCH 054/147] staging: android: binder: fix ABI for 64bit Android This patch fixes the ABI for 64bit Android userspace. BC_REQUEST_DEATH_NOTIFICATION and BC_CLEAR_DEATH_NOTIFICATION claim to be using struct binder_ptr_cookie, but they are using a 32bit handle and a pointer. On 32bit systems the payload size is the same as the size of struct binder_ptr_cookie, however for 64bit systems this will differ. This patch adds struct binder_handle_cookie that fixes this issue for 64bit Android. Since there are no 64bit users of this interface that we know of this change should not affect any existing systems. Change-Id: I8909cbc50aad48ccf371270bad6f69ff242a8c22 Signed-off-by: Serban Constantinescu --- drivers/staging/android/uapi/binder.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index e76cfa876daa..008722a249bc 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -152,6 +152,11 @@ struct binder_ptr_cookie { void *cookie; }; +struct binder_handle_cookie { + __u32 handle; + void *cookie; +} __attribute__((packed)); + struct binder_pri_desc { __s32 priority; __u32 desc; @@ -308,15 +313,15 @@ enum binder_driver_command_protocol { * of looping threads it has available. */ - BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie), + BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), /* - * void *: ptr to binder + * int: handle * void *: cookie */ - BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie), + BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), /* - * void *: ptr to binder + * int: handle * void *: cookie */ From 9dcd36a520ecc9a56ffb8897e741b6fee59b43c7 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:33 +0000 Subject: [PATCH 055/147] staging: android: binder: Move some of the logic into subfunction This patch moves some of the logic for binder_thread_write() into subfunctions. This way we can share more code with the binder compat layer. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 408 +++++++++++++++++-------------- 1 file changed, 223 insertions(+), 185 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index b9a7d9347784..1b9ebe6577f1 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1718,7 +1718,219 @@ static void binder_transaction(struct binder_proc *proc, thread->return_error = return_error; } -int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, +static void bc_increfs_done(struct binder_proc *proc, + struct binder_thread *thread, uint32_t cmd, + void __user *node_ptr, void __user *cookie) +{ + struct binder_node *node; + + node = binder_get_node(proc, node_ptr); + if (node == NULL) { + binder_user_error("%d:%d %s u%p no match\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : + "BC_ACQUIRE_DONE", + node_ptr); + return; + } + if (cookie != node->cookie) { + binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", + node_ptr, node->debug_id, + cookie, node->cookie); + return; + } + if (cmd == BC_ACQUIRE_DONE) { + if (node->pending_strong_ref == 0) { + binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", + proc->pid, thread->pid, + node->debug_id); + return; + } + node->pending_strong_ref = 0; + } else { + if (node->pending_weak_ref == 0) { + binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", + proc->pid, thread->pid, + node->debug_id); + return; + } + node->pending_weak_ref = 0; + } + binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); + binder_debug(BINDER_DEBUG_USER_REFS, + "%d:%d %s node %d ls %d lw %d\n", + proc->pid, thread->pid, + cmd == BC_INCREFS_DONE ? + "BC_INCREFS_DONE" : + "BC_ACQUIRE_DONE", + node->debug_id, node->local_strong_refs, + node->local_weak_refs); + return; +} + +static void bc_free_buffer(struct binder_proc *proc, + struct binder_thread *thread, void __user *data_ptr) +{ + struct binder_buffer *buffer; + + buffer = binder_buffer_lookup(proc, data_ptr); + if (buffer == NULL) { + binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n", + proc->pid, thread->pid, data_ptr); + return; + } + if (!buffer->allow_user_free) { + binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n", + proc->pid, thread->pid, data_ptr); + return; + } + binder_debug(BINDER_DEBUG_FREE_BUFFER, + "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", + proc->pid, thread->pid, data_ptr, buffer->debug_id, + buffer->transaction ? "active" : "finished"); + + if (buffer->transaction) { + buffer->transaction->buffer = NULL; + buffer->transaction = NULL; + } + if (buffer->async_transaction && buffer->target_node) { + BUG_ON(!buffer->target_node->has_async_transaction); + if (list_empty(&buffer->target_node->async_todo)) + buffer->target_node->has_async_transaction = 0; + else + list_move_tail(buffer->target_node->async_todo.next, &thread->todo); + } + trace_binder_transaction_buffer_release(buffer); + binder_transaction_buffer_release(proc, buffer, NULL); + binder_free_buf(proc, buffer); + return; +} + +static void bc_clear_death_notif(struct binder_proc *proc, + struct binder_thread *thread, uint32_t cmd, + uint32_t target, void __user *cookie) +{ + struct binder_ref *ref; + struct binder_ref_death *death; + + ref = binder_get_ref(proc, target); + if (ref == NULL) { + binder_user_error("%d:%d %s invalid ref %d\n", + proc->pid, thread->pid, + cmd == BC_REQUEST_DEATH_NOTIFICATION ? + "BC_REQUEST_DEATH_NOTIFICATION" : + "BC_CLEAR_DEATH_NOTIFICATION", + target); + return; + } + + binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, + "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", + proc->pid, thread->pid, + cmd == BC_REQUEST_DEATH_NOTIFICATION ? + "BC_REQUEST_DEATH_NOTIFICATION" : + "BC_CLEAR_DEATH_NOTIFICATION", + cookie, ref->debug_id, ref->desc, + ref->strong, ref->weak, ref->node->debug_id); + + if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { + if (ref->death) { + binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", + proc->pid, thread->pid); + return; + } + death = kzalloc(sizeof(*death), GFP_KERNEL); + if (death == NULL) { + thread->return_error = BR_ERROR; + binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, + "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", + proc->pid, thread->pid); + return; + } + binder_stats_created(BINDER_STAT_DEATH); + INIT_LIST_HEAD(&death->work.entry); + death->cookie = cookie; + ref->death = death; + if (ref->node->proc == NULL) { + ref->death->work.type = BINDER_WORK_DEAD_BINDER; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&ref->death->work.entry, &thread->todo); + } else { + list_add_tail(&ref->death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } + } else { + if (ref->death == NULL) { + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", + proc->pid, thread->pid); + return; + } + death = ref->death; + if (death->cookie != cookie) { + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", + proc->pid, thread->pid, + death->cookie, cookie); + return; + } + ref->death = NULL; + if (list_empty(&death->work.entry)) { + death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&death->work.entry, &thread->todo); + } else { + list_add_tail(&death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } else { + BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); + death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; + } + } + return; +} + +static void bc_dead_binder_done(struct binder_proc *proc, + struct binder_thread *thread, void __user *cookie) +{ + struct binder_work *w; + struct binder_ref_death *death = NULL; + + list_for_each_entry(w, &proc->delivered_death, entry) { + struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); + if (tmp_death->cookie == cookie) { + death = tmp_death; + return; + } + } + binder_debug(BINDER_DEBUG_DEAD_BINDER, + "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", + proc->pid, thread->pid, cookie, death); + if (death == NULL) { + binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n", + proc->pid, thread->pid, cookie); + return; + } + + list_del_init(&death->work.entry); + if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { + death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; + if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { + list_add_tail(&death->work.entry, &thread->todo); + } else { + list_add_tail(&death->work.entry, &proc->todo); + wake_up_interruptible(&proc->wait); + } + } + return; +} + +static int binder_thread_write(struct binder_proc *proc, + struct binder_thread *thread, void __user *buffer, size_t size, size_t *consumed) { uint32_t cmd; @@ -1791,8 +2003,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, case BC_INCREFS_DONE: case BC_ACQUIRE_DONE: { void __user *node_ptr; - void *cookie; - struct binder_node *node; + void __user *cookie; if (get_user(node_ptr, (void * __user *)ptr)) return -EFAULT; @@ -1800,48 +2011,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (get_user(cookie, (void * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - node = binder_get_node(proc, node_ptr); - if (node == NULL) { - binder_user_error("%d:%d %s u%p no match\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : - "BC_ACQUIRE_DONE", - node_ptr); - break; - } - if (cookie != node->cookie) { - binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node_ptr, node->debug_id, - cookie, node->cookie); - break; - } - if (cmd == BC_ACQUIRE_DONE) { - if (node->pending_strong_ref == 0) { - binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", - proc->pid, thread->pid, - node->debug_id); - break; - } - node->pending_strong_ref = 0; - } else { - if (node->pending_weak_ref == 0) { - binder_user_error("%d:%d BC_INCREFS_DONE node %d has no pending increfs request\n", - proc->pid, thread->pid, - node->debug_id); - break; - } - node->pending_weak_ref = 0; - } - binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); - binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s node %d ls %d lw %d\n", - proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node->debug_id, node->local_strong_refs, node->local_weak_refs); + bc_increfs_done(proc, thread, cmd, node_ptr, cookie); break; } case BC_ATTEMPT_ACQUIRE: @@ -1853,42 +2023,11 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, case BC_FREE_BUFFER: { void __user *data_ptr; - struct binder_buffer *buffer; if (get_user(data_ptr, (void * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - - buffer = binder_buffer_lookup(proc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n", - proc->pid, thread->pid, data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n", - proc->pid, thread->pid, data_ptr); - break; - } - binder_debug(BINDER_DEBUG_FREE_BUFFER, - "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", - proc->pid, thread->pid, data_ptr, buffer->debug_id, - buffer->transaction ? "active" : "finished"); - - if (buffer->transaction) { - buffer->transaction->buffer = NULL; - buffer->transaction = NULL; - } - if (buffer->async_transaction && buffer->target_node) { - BUG_ON(!buffer->target_node->has_async_transaction); - if (list_empty(&buffer->target_node->async_todo)) - buffer->target_node->has_async_transaction = 0; - else - list_move_tail(buffer->target_node->async_todo.next, &thread->todo); - } - trace_binder_transaction_buffer_release(buffer); - binder_transaction_buffer_release(proc, buffer, NULL); - binder_free_buf(proc, buffer); + bc_free_buffer(proc, thread, data_ptr); break; } @@ -1943,8 +2082,6 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, case BC_CLEAR_DEATH_NOTIFICATION: { uint32_t target; void __user *cookie; - struct binder_ref *ref; - struct binder_ref_death *death; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; @@ -1952,117 +2089,18 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, if (get_user(cookie, (void __user * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - ref = binder_get_ref(proc, target); - if (ref == NULL) { - binder_user_error("%d:%d %s invalid ref %d\n", - proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - target); - break; - } - - binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", - proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? - "BC_REQUEST_DEATH_NOTIFICATION" : - "BC_CLEAR_DEATH_NOTIFICATION", - cookie, ref->debug_id, ref->desc, - ref->strong, ref->weak, ref->node->debug_id); - - if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { - if (ref->death) { - binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", - proc->pid, thread->pid); - break; - } - death = kzalloc(sizeof(*death), GFP_KERNEL); - if (death == NULL) { - thread->return_error = BR_ERROR; - binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d BC_REQUEST_DEATH_NOTIFICATION failed\n", - proc->pid, thread->pid); - break; - } - binder_stats_created(BINDER_STAT_DEATH); - INIT_LIST_HEAD(&death->work.entry); - death->cookie = cookie; - ref->death = death; - if (ref->node->proc == NULL) { - ref->death->work.type = BINDER_WORK_DEAD_BINDER; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&ref->death->work.entry, &thread->todo); - } else { - list_add_tail(&ref->death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - } else { - if (ref->death == NULL) { - binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification not active\n", - proc->pid, thread->pid); - break; - } - death = ref->death; - if (death->cookie != cookie) { - binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", - proc->pid, thread->pid, - death->cookie, cookie); - break; - } - ref->death = NULL; - if (list_empty(&death->work.entry)) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } else { - BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER); - death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR; - } - } - } break; + bc_clear_death_notif(proc, thread, cmd, target, cookie); + break; + } case BC_DEAD_BINDER_DONE: { - struct binder_work *w; void __user *cookie; - struct binder_ref_death *death = NULL; + if (get_user(cookie, (void __user * __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - list_for_each_entry(w, &proc->delivered_death, entry) { - struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work); - if (tmp_death->cookie == cookie) { - death = tmp_death; - break; - } - } - binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", - proc->pid, thread->pid, cookie, death); - if (death == NULL) { - binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n", - proc->pid, thread->pid, cookie); - break; - } - - list_del_init(&death->work.entry); - if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) { - death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION; - if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) { - list_add_tail(&death->work.entry, &thread->todo); - } else { - list_add_tail(&death->work.entry, &proc->todo); - wake_up_interruptible(&proc->wait); - } - } - } break; - + bc_dead_binder_done(proc, thread, cookie); + break; + } default: pr_err("%d:%d unknown command %d\n", proc->pid, thread->pid, cmd); From 8b88117ca6327329e7e0880ef854e6ade9d7b605 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:34 +0000 Subject: [PATCH 056/147] staging: android: binder: Add binder_copy_to_user() This patch adds binder_copy_to_user() to be used for copying binder commands to user address space. This way we can abstract away the copy_to_user() calls and add separate handling for the compat layer. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 39 +++++++++++++++++--------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 1b9ebe6577f1..7d6f0b150e40 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2135,6 +2135,18 @@ static int binder_has_thread_work(struct binder_thread *thread) (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } +static int binder_copy_to_user(uint32_t cmd, void *parcel, + void __user **ptr, size_t size) +{ + if (put_user(cmd, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (copy_to_user(*ptr, parcel, size)) + return -EFAULT; + *ptr += size; + return 0; +} + static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, void __user *buffer, size_t size, @@ -2281,15 +2293,12 @@ static int binder_thread_read(struct binder_proc *proc, node->has_weak_ref = 0; } if (cmd != BR_NOOP) { - if (put_user(cmd, (uint32_t __user *)ptr)) + struct binder_ptr_cookie tmp; + + tmp.ptr = node->ptr; + tmp.cookie = node->cookie; + if (binder_copy_to_user(cmd, &tmp, &ptr, sizeof(struct binder_ptr_cookie))) return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(node->ptr, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); - if (put_user(node->cookie, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_USER_REFS, @@ -2324,12 +2333,10 @@ static int binder_thread_read(struct binder_proc *proc, cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE; else cmd = BR_DEAD_BINDER; - if (put_user(cmd, (uint32_t __user *)ptr)) + + if (binder_copy_to_user(cmd, &death->cookie, &ptr, sizeof(void *))) return -EFAULT; - ptr += sizeof(uint32_t); - if (put_user(death->cookie, (void * __user *)ptr)) - return -EFAULT; - ptr += sizeof(void *); + binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, "%d:%d %s %p\n", @@ -2391,12 +2398,8 @@ static int binder_thread_read(struct binder_proc *proc, ALIGN(t->buffer->data_size, sizeof(void *)); - if (put_user(cmd, (uint32_t __user *)ptr)) + if (binder_copy_to_user(cmd, &tr, &ptr, sizeof(struct binder_transaction_data))) return -EFAULT; - ptr += sizeof(uint32_t); - if (copy_to_user(ptr, &tr, sizeof(tr))) - return -EFAULT; - ptr += sizeof(tr); trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd); From d1b83dd27f1ec80da678d2db00a54ff07de9a5fd Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:35 +0000 Subject: [PATCH 057/147] staging: android: binder: Add cmd == CMD_NAME handling This patch modifies the functions that need to be passed the explicit command to use a boolean flag. This way we can reuse the code for 64bit compat commands. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7d6f0b150e40..392283d4b21c 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1719,7 +1719,7 @@ static void binder_transaction(struct binder_proc *proc, } static void bc_increfs_done(struct binder_proc *proc, - struct binder_thread *thread, uint32_t cmd, + struct binder_thread *thread, bool acquire, void __user *node_ptr, void __user *cookie) { struct binder_node *node; @@ -1728,22 +1728,22 @@ static void bc_increfs_done(struct binder_proc *proc, if (node == NULL) { binder_user_error("%d:%d %s u%p no match\n", proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : - "BC_ACQUIRE_DONE", + acquire ? + "BC_ACQUIRE_DONE" : + "BC_INCREFS_DONE", node_ptr); return; } if (cookie != node->cookie) { binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", + acquire ? + "BC_ACQUIRE_DONE" : "BC_INCREFS_DONE", node_ptr, node->debug_id, cookie, node->cookie); return; } - if (cmd == BC_ACQUIRE_DONE) { + if (acquire) { if (node->pending_strong_ref == 0) { binder_user_error("%d:%d BC_ACQUIRE_DONE node %d has no pending acquire request\n", proc->pid, thread->pid, @@ -1760,13 +1760,13 @@ static void bc_increfs_done(struct binder_proc *proc, } node->pending_weak_ref = 0; } - binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0); + binder_dec_node(node, acquire, 0); binder_debug(BINDER_DEBUG_USER_REFS, "%d:%d %s node %d ls %d lw %d\n", proc->pid, thread->pid, - cmd == BC_INCREFS_DONE ? - "BC_INCREFS_DONE" : - "BC_ACQUIRE_DONE", + acquire ? + "BC_ACQUIRE_DONE" : + "BC_INCREFS_DONE", node->debug_id, node->local_strong_refs, node->local_weak_refs); return; @@ -1811,7 +1811,7 @@ static void bc_free_buffer(struct binder_proc *proc, } static void bc_clear_death_notif(struct binder_proc *proc, - struct binder_thread *thread, uint32_t cmd, + struct binder_thread *thread, bool request, uint32_t target, void __user *cookie) { struct binder_ref *ref; @@ -1821,7 +1821,7 @@ static void bc_clear_death_notif(struct binder_proc *proc, if (ref == NULL) { binder_user_error("%d:%d %s invalid ref %d\n", proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? + request ? "BC_REQUEST_DEATH_NOTIFICATION" : "BC_CLEAR_DEATH_NOTIFICATION", target); @@ -1831,13 +1831,13 @@ static void bc_clear_death_notif(struct binder_proc *proc, binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", proc->pid, thread->pid, - cmd == BC_REQUEST_DEATH_NOTIFICATION ? + request ? "BC_REQUEST_DEATH_NOTIFICATION" : "BC_CLEAR_DEATH_NOTIFICATION", cookie, ref->debug_id, ref->desc, ref->strong, ref->weak, ref->node->debug_id); - if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { + if (request) { if (ref->death) { binder_user_error("%d:%d BC_REQUEST_DEATH_NOTIFICATION death notification already set\n", proc->pid, thread->pid); @@ -2011,7 +2011,7 @@ static int binder_thread_write(struct binder_proc *proc, if (get_user(cookie, (void * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - bc_increfs_done(proc, thread, cmd, node_ptr, cookie); + bc_increfs_done(proc, thread, cmd == BC_ACQUIRE_DONE, node_ptr, cookie); break; } case BC_ATTEMPT_ACQUIRE: @@ -2089,7 +2089,8 @@ static int binder_thread_write(struct binder_proc *proc, if (get_user(cookie, (void __user * __user *)ptr)) return -EFAULT; ptr += sizeof(void *); - bc_clear_death_notif(proc, thread, cmd, target, cookie); + bc_clear_death_notif(proc, thread, cmd == BC_REQUEST_DEATH_NOTIFICATION, + target, cookie); break; } case BC_DEAD_BINDER_DONE: { From a4cffaa5e848445430acc0a51e843f6209b8cda2 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:36 +0000 Subject: [PATCH 058/147] staging: android: binder: Add align_helper() macro This patch adds align_helper() macro that will be used for enforcing the desired alignment on 64bit systems where the alignment will differ depending on the userspace used (32bit /64bit). This patch is a temporary patch that will be extended with 32bit compat handling. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 392283d4b21c..8a4e252ece9e 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -141,6 +141,8 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, binder_stop_on_user_error = 2; \ } while (0) +#define align_helper(ptr) ALIGN(ptr, sizeof(void *)) + enum binder_stat_types { BINDER_STAT_PROC, BINDER_STAT_THREAD, @@ -1240,7 +1242,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, if (buffer->target_node) binder_dec_node(buffer->target_node, 1, 0); - offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *))); + offp = (size_t *)(buffer->data + align_helper(buffer->data_size)); if (failed_at) off_end = failed_at; else @@ -1477,7 +1479,7 @@ static void binder_transaction(struct binder_proc *proc, if (target_node) binder_inc_node(target_node, 1, 0, NULL); - offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); + offp = (size_t *)(t->buffer->data + align_helper(tr->data_size)); if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { binder_user_error("%d:%d got transaction with invalid data ptr\n", @@ -2396,8 +2398,7 @@ static int binder_thread_read(struct binder_proc *proc, tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset; tr.data.ptr.offsets = tr.data.ptr.buffer + - ALIGN(t->buffer->data_size, - sizeof(void *)); + align_helper(t->buffer->data_size); if (binder_copy_to_user(cmd, &tr, &ptr, sizeof(struct binder_transaction_data))) return -EFAULT; From 98e77a8deabe744d3754f28f54e435d72407b8a9 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:37 +0000 Subject: [PATCH 059/147] staging: android: binder: Add deref_helper() macro This patch adds a deref_helper() macro that will be used to dereference the binder offsets on 64bit systems where the offset is either a 32bit or a 64bit value, depending on the userpace used (32bit /64bit) This patch is a temporary patch that will be extended with 32bit compat handling. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 8a4e252ece9e..38d47f1fee37 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -142,6 +142,7 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, } while (0) #define align_helper(ptr) ALIGN(ptr, sizeof(void *)) +#define deref_helper(ptr) (*(typeof(size_t *))ptr) enum binder_stat_types { BINDER_STAT_PROC, @@ -1231,7 +1232,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, size_t *failed_at) { - size_t *offp, *off_end; + void *offp, *off_end; int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1247,16 +1248,16 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, off_end = failed_at; else off_end = (void *)offp + buffer->offsets_size; - for (; offp < off_end; offp++) { + for (; offp < off_end; offp += sizeof(size_t)) { struct flat_binder_object *fp; - if (*offp > buffer->data_size - sizeof(*fp) || + if (deref_helper(offp) > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(u32))) { + !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { pr_err("transaction release %d bad offset %zd, size %zd\n", - debug_id, *offp, buffer->data_size); + debug_id, deref_helper(offp), buffer->data_size); continue; } - fp = (struct flat_binder_object *)(buffer->data + *offp); + fp = (struct flat_binder_object *)(buffer->data + deref_helper(offp)); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { @@ -1306,7 +1307,7 @@ static void binder_transaction(struct binder_proc *proc, { struct binder_transaction *t; struct binder_work *tcomplete; - size_t *offp, *off_end; + void *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; @@ -1500,17 +1501,17 @@ static void binder_transaction(struct binder_proc *proc, goto err_bad_offset; } off_end = (void *)offp + tr->offsets_size; - for (; offp < off_end; offp++) { + for (; offp < off_end; offp += sizeof(size_t)) { struct flat_binder_object *fp; - if (*offp > t->buffer->data_size - sizeof(*fp) || + if (deref_helper(offp) > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(u32))) { + !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { binder_user_error("%d:%d got transaction with invalid offset, %zd\n", - proc->pid, thread->pid, *offp); + proc->pid, thread->pid, deref_helper(offp)); return_error = BR_FAILED_REPLY; goto err_bad_offset; } - fp = (struct flat_binder_object *)(t->buffer->data + *offp); + fp = (struct flat_binder_object *)(t->buffer->data + deref_helper(offp)); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { From 63efce4893bc25a6db91bb363f0fa30a2af8d149 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:38 +0000 Subject: [PATCH 060/147] staging: android: binder: Add size_helper() macro This patch adds size_helper() macro that will be used for indexing into different buffers on 64bit systems where the size of particular structures will differ depending on the userspace used (32bit /64bit). This patch is a temporary patch that will be extended with 32bit compat handling. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 38d47f1fee37..6dd58a228361 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -143,6 +143,7 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, #define align_helper(ptr) ALIGN(ptr, sizeof(void *)) #define deref_helper(ptr) (*(typeof(size_t *))ptr) +#define size_helper(x) sizeof(x) enum binder_stat_types { BINDER_STAT_PROC, @@ -1248,10 +1249,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, off_end = failed_at; else off_end = (void *)offp + buffer->offsets_size; - for (; offp < off_end; offp += sizeof(size_t)) { + for (; offp < off_end; offp += size_helper(size_t)) { struct flat_binder_object *fp; - if (deref_helper(offp) > buffer->data_size - sizeof(*fp) || - buffer->data_size < sizeof(*fp) || + if (deref_helper(offp) > buffer->data_size - size_helper(*fp) || + buffer->data_size < size_helper(*fp) || !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { pr_err("transaction release %d bad offset %zd, size %zd\n", debug_id, deref_helper(offp), buffer->data_size); @@ -1494,17 +1495,17 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } - if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { + if (!IS_ALIGNED(tr->offsets_size, size_helper(size_t))) { binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n", proc->pid, thread->pid, tr->offsets_size); return_error = BR_FAILED_REPLY; goto err_bad_offset; } off_end = (void *)offp + tr->offsets_size; - for (; offp < off_end; offp += sizeof(size_t)) { + for (; offp < off_end; offp += size_helper(size_t)) { struct flat_binder_object *fp; - if (deref_helper(offp) > t->buffer->data_size - sizeof(*fp) || - t->buffer->data_size < sizeof(*fp) || + if (deref_helper(offp) > t->buffer->data_size - size_helper(*fp) || + t->buffer->data_size < size_helper(*fp) || !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { binder_user_error("%d:%d got transaction with invalid offset, %zd\n", proc->pid, thread->pid, deref_helper(offp)); @@ -2247,7 +2248,7 @@ static int binder_thread_read(struct binder_proc *proc, break; } - if (end - ptr < sizeof(tr) + 4) + if (end - ptr < size_helper(tr) + 4) break; switch (w->type) { From 46bd93ed20f4b4f1ae743f46a458b6d8eb10f2b0 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:39 +0000 Subject: [PATCH 061/147] staging: android: binder: Add copy_flat_binder_object() This patch adds copy_flat_binder_object macro() that will help dereference struct flat_binder_object on 64bit systems where the structure differs between 32bit and 64bit userspace. This patch is a temporary patch that will be extended with 32bit compat handling. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 6dd58a228361..16ce8f4e5ed2 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -145,6 +145,11 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, #define deref_helper(ptr) (*(typeof(size_t *))ptr) #define size_helper(x) sizeof(x) +static inline struct flat_binder_object *copy_flat_binder_object(void __user *ptr) +{ + return (struct flat_binder_object *)ptr; +} + enum binder_stat_types { BINDER_STAT_PROC, BINDER_STAT_THREAD, @@ -1258,7 +1263,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, deref_helper(offp), buffer->data_size); continue; } - fp = (struct flat_binder_object *)(buffer->data + deref_helper(offp)); + fp = copy_flat_binder_object(buffer->data + deref_helper(offp)); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { @@ -1512,7 +1517,7 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_bad_offset; } - fp = (struct flat_binder_object *)(t->buffer->data + deref_helper(offp)); + fp = copy_flat_binder_object(t->buffer->data + deref_helper(offp)); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { From 42aea61e29f2c76517be8867b0209fdd9ea2a660 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:40 +0000 Subject: [PATCH 062/147] staging: android: binder: Add binder compat handling to binder.h This patch adds all the needed compat structures to binder.h. All the structures defined in this patch mirror the structure and size of 32bit ones. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/uapi/binder.h | 109 ++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 008722a249bc..384658ac1bb4 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -21,6 +21,9 @@ #define _UAPI_LINUX_BINDER_H #include +#ifdef CONFIG_COMPAT +#include +#endif #define B_PACK_CHARS(c1, c2, c3, c4) \ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) @@ -331,5 +334,111 @@ enum binder_driver_command_protocol { */ }; +/* Support for 32bit userspace on a 64bit system */ +#ifdef CONFIG_COMPAT +struct compat_flat_binder_object { + /* 8 bytes for large_flat_header. */ + __u32 type; + __u32 flags; + + /* 8 bytes of data. */ + union { + compat_uptr_t binder; /* local object */ + __u32 handle; /* remote object */ + }; + + /* extra data associated with local object */ + compat_uptr_t cookie; +}; + +struct compat_binder_write_read { + compat_size_t write_size; /* bytes to write */ + compat_size_t write_consumed; /* bytes consumed by driver */ + compat_ulong_t write_buffer; + compat_size_t read_size; /* bytes to read */ + compat_size_t read_consumed; /* bytes consumed by driver */ + compat_ulong_t read_buffer; +}; + +#define COMPAT_BINDER_WRITE_READ _IOWR('b', 1, struct compat_binder_write_read) + +struct compat_binder_transaction_data { + /* The first two are only used for bcTRANSACTION and brTRANSACTION, + * identifying the target and contents of the transaction. + */ + union { + __u32 handle; /* target descriptor of command transaction */ + compat_uptr_t ptr; /* target descriptor of return transaction */ + } target; + compat_uptr_t cookie; /* target object cookie */ + __u32 code; /* transaction command */ + + /* General information about the transaction. */ + __u32 flags; + pid_t sender_pid; + uid_t sender_euid; + compat_size_t data_size; /* number of bytes of data */ + compat_size_t offsets_size; /* number of bytes of offsets */ + + /* If this transaction is inline, the data immediately + * follows here; otherwise, it ends with a pointer to + * the data buffer. + */ + union { + struct { + /* transaction data */ + compat_uptr_t buffer; + /* offsets from buffer to flat_binder_object structs */ + compat_uptr_t offsets; + } ptr; + __u8 buf[8]; + } data; +}; + +struct compat_binder_ptr_cookie { + compat_uptr_t ptr; + compat_uptr_t cookie; +}; + +/* legacy - not used anymore */ +struct compat_binder_pri_ptr_cookie { + __s32 priority; + compat_uptr_t ptr; + compat_uptr_t cookie; +}; + +enum compat_binder_driver_return_protocol { + COMPAT_BR_TRANSACTION = _IOR('r', 2, struct compat_binder_transaction_data), + COMPAT_BR_REPLY = _IOR('r', 3, struct compat_binder_transaction_data), + + COMPAT_BR_INCREFS = _IOR('r', 7, struct compat_binder_ptr_cookie), + COMPAT_BR_ACQUIRE = _IOR('r', 8, struct compat_binder_ptr_cookie), + COMPAT_BR_RELEASE = _IOR('r', 9, struct compat_binder_ptr_cookie), + COMPAT_BR_DECREFS = _IOR('r', 10, struct compat_binder_ptr_cookie), + + /* legacy - not used anymore */ + COMPAT_BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct compat_binder_pri_ptr_cookie), + + COMPAT_BR_DEAD_BINDER = _IOR('r', 15, compat_uptr_t), + COMPAT_BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, compat_uptr_t), +}; + +enum compat_binder_driver_command_protocol { + COMPAT_BC_TRANSACTION = _IOW('c', 0, struct compat_binder_transaction_data), + COMPAT_BC_REPLY = _IOW('c', 1, struct compat_binder_transaction_data), + + COMPAT_BC_FREE_BUFFER = _IOW('c', 3, compat_uptr_t), + + COMPAT_BC_INCREFS_DONE = _IOW('c', 8, struct compat_binder_ptr_cookie), + COMPAT_BC_ACQUIRE_DONE = _IOW('c', 9, struct compat_binder_ptr_cookie), + + COMPAT_BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct compat_binder_ptr_cookie), + COMPAT_BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct compat_binder_ptr_cookie), + + COMPAT_BC_DEAD_BINDER_DONE = _IOW('c', 16, compat_uptr_t), +}; +#endif /* CONFIG_COMPAT */ + + #endif /* _UAPI_LINUX_BINDER_H */ From 754af9a1d3f81e8e17dd47be81c673abc681fbe0 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 12 Jun 2013 16:28:04 +0100 Subject: [PATCH 063/147] arm64: mm: permit use of tagged pointers at EL0 TCR.TBI0 can be used to cause hardware address translation to ignore the top byte of userspace virtual addresses. Whilst not especially useful in standard C programs, this can be used by JITs to `tag' pointers with various pieces of metadata. This patch enables this bit for AArch64 Linux, and adds a new file to Documentation/arm64/ which describes some potential caveats when using tagged virtual addresses. Change-Id: I4c025d026144c69a2259b6562e46176f95b4e110 Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- Documentation/arm64/tagged-pointers.txt | 34 +++++++++++++++++++++++++ arch/arm64/include/asm/pgtable-hwdef.h | 1 + arch/arm64/kernel/entry.S | 1 + arch/arm64/mm/proc.S | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 Documentation/arm64/tagged-pointers.txt diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt new file mode 100644 index 000000000000..264e9841563a --- /dev/null +++ b/Documentation/arm64/tagged-pointers.txt @@ -0,0 +1,34 @@ + Tagged virtual addresses in AArch64 Linux + ========================================= + +Author: Will Deacon +Date : 12 June 2013 + +This document briefly describes the provision of tagged virtual +addresses in the AArch64 translation system and their potential uses +in AArch64 Linux. + +The kernel configures the translation tables so that translations made +via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of +the virtual address ignored by the translation hardware. This frees up +this byte for application use, with the following caveats: + + (1) The kernel requires that all user addresses passed to EL1 + are tagged with tag 0x00. This means that any syscall + parameters containing user virtual addresses *must* have + their top byte cleared before trapping to the kernel. + + (2) Tags are not guaranteed to be preserved when delivering + signals. This means that signal handlers in applications + making use of tags cannot rely on the tag information for + user virtual addresses being maintained for fields inside + siginfo_t. One exception to this rule is for signals raised + in response to debug exceptions, where the tag information + will be preserved. + + (3) Special care should be taken when using tagged pointers, + since it is likely that C compilers will not hazard two + addresses differing only in the upper bits. + +The architecture prevents the use of a tagged PC, so the upper byte will +be set to a sign-extension of bit 55 on exception return. diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index 75fd13d289b9..7eeed1ae2c5f 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -92,5 +92,6 @@ #define TCR_TG1_64K (UL(1) << 30) #define TCR_IPS_40BIT (UL(2) << 32) #define TCR_ASID16 (UL(1) << 36) +#define TCR_TBI0 (UL(1) << 37) #endif diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 1d1314280a03..1146e6f40a6b 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -423,6 +423,7 @@ el0_da: * Data abort handling */ mrs x0, far_el1 + bic x0, x0, #(0xff << 56) disable_step x1 isb enable_dbg diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index a82ae8868077..9428de8a8f37 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -151,7 +151,7 @@ ENTRY(__cpu_setup) * both user and kernel. */ ldr x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \ - TCR_ASID16 | (1 << 31) + TCR_ASID16 | TCR_TBI0 | (1 << 31) #ifdef CONFIG_ARM64_64K_PAGES orr x10, x10, TCR_TG0_64K orr x10, x10, TCR_TG1_64K From 7a18e70688223a37ba4c8cf5edd313e8d1bb680d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 17 Sep 2013 11:46:23 +0100 Subject: [PATCH 064/147] arm64: documentation: tighten up tagged pointer documentation Commit d50240a5f6ce ("arm64: mm: permit use of tagged pointers at EL0") added support for tagged pointers in userspace, but the corresponding update to Documentation/ contained some imprecise statements. This patch fixes up some minor ambiguities in the text, hopefully making it more clear about exactly what the kernel expects from user virtual addresses. Change-Id: I7df342e01d5253ccacb3847449940892768d7e07 Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- Documentation/arm64/tagged-pointers.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt index 264e9841563a..d9995f1f51b3 100644 --- a/Documentation/arm64/tagged-pointers.txt +++ b/Documentation/arm64/tagged-pointers.txt @@ -18,17 +18,17 @@ this byte for application use, with the following caveats: parameters containing user virtual addresses *must* have their top byte cleared before trapping to the kernel. - (2) Tags are not guaranteed to be preserved when delivering - signals. This means that signal handlers in applications - making use of tags cannot rely on the tag information for - user virtual addresses being maintained for fields inside - siginfo_t. One exception to this rule is for signals raised - in response to debug exceptions, where the tag information + (2) Non-zero tags are not preserved when delivering signals. + This means that signal handlers in applications making use + of tags cannot rely on the tag information for user virtual + addresses being maintained for fields inside siginfo_t. + One exception to this rule is for signals raised in response + to watchpoint debug exceptions, where the tag information will be preserved. (3) Special care should be taken when using tagged pointers, since it is likely that C compilers will not hazard two - addresses differing only in the upper bits. + virtual addresses differing only in the upper byte. The architecture prevents the use of a tagged PC, so the upper byte will be set to a sign-extension of bit 55 on exception return. From c10c64d40bf14ce5964300991744d17296d57481 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Mon, 13 Jan 2014 15:24:24 -0800 Subject: [PATCH 065/147] video: adf: define constants for device-custom ioctls Device-custom ADF ioctls can use type ADF_IOCTL_TYPE and nr >= ADF_IOCTL_NR_CUSTOM Change-Id: Ia8270973df5100e996ca0e021ede60e54b9af72a Signed-off-by: Greg Hackmann --- include/uapi/video/adf.h | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/include/uapi/video/adf.h b/include/uapi/video/adf.h index 38458f6428b5..b703bf9e9a66 100644 --- a/include/uapi/video/adf.h +++ b/include/uapi/video/adf.h @@ -295,17 +295,27 @@ struct adf_overlay_engine_data { }; #define ADF_MAX_SUPPORTED_FORMATS (4096 / sizeof(__u32)) -#define ADF_SET_EVENT _IOW('D', 0, struct adf_set_event) -#define ADF_BLANK _IOW('D', 1, __u8) -#define ADF_POST_CONFIG _IOW('D', 2, struct adf_post_config) -#define ADF_SET_MODE _IOW('D', 3, struct drm_mode_modeinfo) -#define ADF_GET_DEVICE_DATA _IOR('D', 4, struct adf_device_data) -#define ADF_GET_INTERFACE_DATA _IOR('D', 5, struct adf_interface_data) +#define ADF_IOCTL_TYPE 'D' +#define ADF_IOCTL_NR_CUSTOM 128 + +#define ADF_SET_EVENT _IOW(ADF_IOCTL_TYPE, 0, struct adf_set_event) +#define ADF_BLANK _IOW(ADF_IOCTL_TYPE, 1, __u8) +#define ADF_POST_CONFIG _IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config) +#define ADF_SET_MODE _IOW(ADF_IOCTL_TYPE, 3, \ + struct drm_mode_modeinfo) +#define ADF_GET_DEVICE_DATA _IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data) +#define ADF_GET_INTERFACE_DATA _IOR(ADF_IOCTL_TYPE, 5, \ + struct adf_interface_data) #define ADF_GET_OVERLAY_ENGINE_DATA \ - _IOR('D', 6, struct adf_overlay_engine_data) -#define ADF_SIMPLE_POST_CONFIG _IOW('D', 7, struct adf_simple_post_config) -#define ADF_SIMPLE_BUFFER_ALLOC _IOW('D', 8, struct adf_simple_buffer_alloc) -#define ADF_ATTACH _IOW('D', 9, struct adf_attachment_config) -#define ADF_DETACH _IOW('D', 10, struct adf_attachment_config) + _IOR(ADF_IOCTL_TYPE, 6, \ + struct adf_overlay_engine_data) +#define ADF_SIMPLE_POST_CONFIG _IOW(ADF_IOCTL_TYPE, 7, \ + struct adf_simple_post_config) +#define ADF_SIMPLE_BUFFER_ALLOC _IOW(ADF_IOCTL_TYPE, 8, \ + struct adf_simple_buffer_alloc) +#define ADF_ATTACH _IOW(ADF_IOCTL_TYPE, 9, \ + struct adf_attachment_config) +#define ADF_DETACH _IOW(ADF_IOCTL_TYPE, 10, \ + struct adf_attachment_config) #endif /* _UAPI_VIDEO_ADF_H_ */ From 0ac276ebfca1d405153f4a3476aa1f7f66bbbec8 Mon Sep 17 00:00:00 2001 From: Minsung Kim Date: Sun, 19 Jan 2014 14:32:42 +0900 Subject: [PATCH 066/147] cpufreq: interactive: fix NULL pointer dereference at sysfs ops sysfs ops for target_loads and above_hispeed_delay can be called before initializing tunables at CPUFREQ_GOV_POLICY_INIT. Create sysfs entries after initialization. Change-Id: I50356198d7629731c0d32a3066d61fe8354e0001 Signed-off-by: Minsung Kim --- drivers/cpufreq/cpufreq_interactive.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index 9f63bd1e4fee..8297ac69863b 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -1178,13 +1178,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, return -ENOMEM; } - rc = sysfs_create_group(get_governor_parent_kobj(policy), - get_sysfs_attr()); - if (rc) { - kfree(tunables); - return rc; - } - tunables->usage_count = 1; tunables->above_hispeed_delay = default_above_hispeed_delay; tunables->nabove_hispeed_delay = @@ -1200,16 +1193,26 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, spin_lock_init(&tunables->target_loads_lock); spin_lock_init(&tunables->above_hispeed_delay_lock); + policy->governor_data = tunables; + if (!have_governor_per_policy()) + common_tunables = tunables; + + rc = sysfs_create_group(get_governor_parent_kobj(policy), + get_sysfs_attr()); + if (rc) { + kfree(tunables); + policy->governor_data = NULL; + if (!have_governor_per_policy()) + common_tunables = NULL; + return rc; + } + if (!policy->governor->initialized) { idle_notifier_register(&cpufreq_interactive_idle_nb); cpufreq_register_notifier(&cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); } - policy->governor_data = tunables; - if (!have_governor_per_policy()) - common_tunables = tunables; - break; case CPUFREQ_GOV_POLICY_EXIT: From 46650262c2342eab6ef01b382741df2d89688ab3 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 4 Dec 2013 18:09:41 +0000 Subject: [PATCH 067/147] staging: android: binder: Add binder compat layer This patch adds support for 32bit userspace running on 64bit kernels. All the changes done in this patch have been tested on 32bit and 64bit systems. Signed-off-by: Serban Constantinescu Signed-off-by: John Stultz --- drivers/staging/android/binder.c | 355 ++++++++++++++++++++++++++++++- 1 file changed, 353 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 16ce8f4e5ed2..65dd819d41aa 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "binder.h" #include "binder_trace.h" @@ -141,6 +142,77 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, binder_stop_on_user_error = 2; \ } while (0) +#ifdef CONFIG_COMPAT +static inline void writeback_flat_binder_object(struct flat_binder_object *fp, + void __user *ptr) +{ + struct compat_flat_binder_object *tmp_fp; + + tmp_fp = (struct compat_flat_binder_object *) ptr; + tmp_fp->type = fp->type; + tmp_fp->flags = fp->flags; + tmp_fp->binder = ptr_to_compat(fp->binder); + tmp_fp->cookie = ptr_to_compat(fp->cookie); +} + +static inline struct flat_binder_object *copy_flat_binder_object(void __user *ptr) +{ + struct flat_binder_object *fp; + struct compat_flat_binder_object *tmp_fp; + + if (!is_compat_task()) + return (struct flat_binder_object *) ptr; + + fp = kzalloc(sizeof(*fp), GFP_KERNEL); + if (fp == NULL) + return NULL; + + tmp_fp = (struct compat_flat_binder_object *) ptr; + /* copy compat struct */ + fp->type = tmp_fp->type; + fp->flags = tmp_fp->flags; + fp->binder = compat_ptr(tmp_fp->binder); + fp->cookie = compat_ptr(tmp_fp->cookie); + + return fp; +} + +static inline uint32_t compat_change_size(uint32_t cmd, size_t size) +{ + uint32_t compat_cmd; + + compat_cmd = cmd & ~IOCSIZE_MASK; + compat_cmd = compat_cmd | ((size << _IOC_SIZESHIFT) & IOCSIZE_MASK); + return compat_cmd; +} + +#define align_helper(x) ( \ + is_compat_task() ? \ + ALIGN(x, sizeof(compat_uptr_t)) : \ + ALIGN(x, sizeof(void *)) \ + ) + +#define deref_helper(x) ( \ + is_compat_task() ? \ + (size_t) *(compat_size_t *)x : \ + *(size_t *)x \ + ) + +#define size_helper(x) ({ \ + size_t __size; \ + if (!is_compat_task()) \ + __size = sizeof(x); \ + else if (sizeof(x) == sizeof(struct flat_binder_object)) \ + __size = sizeof(struct compat_flat_binder_object); \ + else if (sizeof(x) == sizeof(struct binder_transaction_data)) \ + __size = sizeof(struct compat_binder_transaction_data); \ + else if (sizeof(x) == sizeof(size_t)) \ + __size = sizeof(compat_size_t); \ + else \ + BUG(); \ + __size; \ + }) +#else #define align_helper(ptr) ALIGN(ptr, sizeof(void *)) #define deref_helper(ptr) (*(typeof(size_t *))ptr) #define size_helper(x) sizeof(x) @@ -149,6 +221,7 @@ static inline struct flat_binder_object *copy_flat_binder_object(void __user *pt { return (struct flat_binder_object *)ptr; } +#endif enum binder_stat_types { BINDER_STAT_PROC, @@ -1255,7 +1328,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, else off_end = (void *)offp + buffer->offsets_size; for (; offp < off_end; offp += size_helper(size_t)) { - struct flat_binder_object *fp; + struct flat_binder_object *fp = NULL; if (deref_helper(offp) > buffer->data_size - size_helper(*fp) || buffer->data_size < size_helper(*fp) || !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { @@ -1304,6 +1377,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, fp->type); break; } + if (is_compat_task()) + kfree(fp); } } @@ -1322,6 +1397,7 @@ static void binder_transaction(struct binder_proc *proc, struct binder_transaction *in_reply_to = NULL; struct binder_transaction_log_entry *e; uint32_t return_error; + struct flat_binder_object *fp = NULL; e = binder_transaction_log_add(&binder_transaction_log); e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY); @@ -1508,7 +1584,6 @@ static void binder_transaction(struct binder_proc *proc, } off_end = (void *)offp + tr->offsets_size; for (; offp < off_end; offp += size_helper(size_t)) { - struct flat_binder_object *fp; if (deref_helper(offp) > t->buffer->data_size - size_helper(*fp) || t->buffer->data_size < size_helper(*fp) || !IS_ALIGNED(deref_helper(offp), sizeof(u32))) { @@ -1657,6 +1732,12 @@ static void binder_transaction(struct binder_proc *proc, return_error = BR_FAILED_REPLY; goto err_bad_object_type; } +#ifdef CONFIG_COMPAT + if (is_compat_task()) { + writeback_flat_binder_object(fp, t->buffer->data + deref_helper(offp)); + kfree(fp); + } +#endif } if (reply) { BUG_ON(t->buffer->async_transaction != 0); @@ -1692,6 +1773,8 @@ static void binder_transaction(struct binder_proc *proc, err_bad_object_type: err_bad_offset: err_copy_data_failed: + if (is_compat_task()) + kfree(fp); trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); t->buffer->transaction = NULL; @@ -1938,6 +2021,95 @@ static void bc_dead_binder_done(struct binder_proc *proc, return; } +#ifdef CONFIG_COMPAT +static int compat_binder_thread_write(struct binder_proc *proc, + struct binder_thread *thread, uint32_t cmd, + void __user **ptr) +{ + BUG_ON(!is_compat_task()); + switch (cmd) { + case COMPAT_BC_INCREFS_DONE: + case COMPAT_BC_ACQUIRE_DONE: { + compat_uptr_t node_ptr; + compat_uptr_t cookie; + + if (get_user(node_ptr, (compat_uptr_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(compat_uptr_t); + if (get_user(cookie, (compat_uptr_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(compat_uptr_t); + bc_increfs_done(proc, thread, cmd == COMPAT_BC_ACQUIRE_DONE, + compat_ptr(node_ptr), compat_ptr(cookie)); + break; + } + + case COMPAT_BC_FREE_BUFFER: { + compat_uptr_t data_ptr; + + if (get_user(data_ptr, (compat_uptr_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(compat_uptr_t); + bc_free_buffer(proc, thread, compat_ptr(data_ptr)); + break; + } + + case COMPAT_BC_TRANSACTION: + case COMPAT_BC_REPLY: { + struct binder_transaction_data tr; + struct compat_binder_transaction_data tmp_tr; + + if (copy_from_user(&tmp_tr, *ptr, sizeof(tmp_tr))) + return -EFAULT; + *ptr += sizeof(tmp_tr); + + memset(&tr, 0, sizeof(tr)); + /* copy from compat struct */ + tr.target.ptr = compat_ptr(tmp_tr.target.ptr); + tr.cookie = compat_ptr(tmp_tr.cookie); + tr.code = tmp_tr.code; + tr.flags = tmp_tr.flags; + tr.sender_pid = tmp_tr.sender_pid; + tr.sender_euid = tmp_tr.sender_euid; + tr.data_size = (size_t) tmp_tr.data_size; + tr.offsets_size = (size_t) tmp_tr.offsets_size; + tr.data.ptr.buffer = compat_ptr(tmp_tr.data.ptr.buffer); + tr.data.ptr.offsets = compat_ptr(tmp_tr.data.ptr.offsets); + + binder_transaction(proc, thread, &tr, cmd == COMPAT_BC_REPLY); + break; + } + case COMPAT_BC_REQUEST_DEATH_NOTIFICATION: + case COMPAT_BC_CLEAR_DEATH_NOTIFICATION: { + uint32_t target; + compat_uptr_t cookie; + + if (get_user(target, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (get_user(cookie, (compat_uptr_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(compat_uptr_t); + bc_clear_death_notif(proc, thread, cmd == COMPAT_BC_REQUEST_DEATH_NOTIFICATION, + target, compat_ptr(cookie)); + break; + } + case COMPAT_BC_DEAD_BINDER_DONE: { + compat_uptr_t cookie; + + if (get_user(cookie, (compat_uptr_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(compat_uptr_t); + bc_dead_binder_done(proc, thread, compat_ptr(cookie)); + break; + } + default: + return -EINVAL; + } + return 0; +} +#endif + static int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, void __user *buffer, size_t size, size_t *consumed) @@ -2112,6 +2284,10 @@ static int binder_thread_write(struct binder_proc *proc, break; } default: +#ifdef CONFIG_COMPAT + if (is_compat_task() && (!compat_binder_thread_write(proc, thread, cmd, &ptr))) + break; +#endif pr_err("%d:%d unknown command %d\n", proc->pid, thread->pid, cmd); return -EINVAL; @@ -2145,6 +2321,103 @@ static int binder_has_thread_work(struct binder_thread *thread) (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } +#ifdef CONFIG_COMPAT +static int binder_copy_to_user(uint32_t cmd, void *parcel, + void __user **ptr, size_t size) +{ + if (!is_compat_task()) { + if (put_user(cmd, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (copy_to_user(*ptr, parcel, size)) + return -EFAULT; + *ptr += size; + return 0; + } + switch (cmd) { + case BR_INCREFS: + case BR_ACQUIRE: + case BR_RELEASE: + case BR_DECREFS: { + struct binder_ptr_cookie *fp; + struct compat_binder_ptr_cookie tmp; + + cmd = compat_change_size(cmd, sizeof(tmp)); + BUG_ON((cmd != COMPAT_BR_INCREFS) && + (cmd != COMPAT_BR_ACQUIRE) && + (cmd != COMPAT_BR_RELEASE) && + (cmd != COMPAT_BR_DECREFS)); + + fp = (struct binder_ptr_cookie *) parcel; + tmp.ptr = ptr_to_compat(fp->ptr); + tmp.cookie = ptr_to_compat(fp->cookie); + if (put_user(cmd, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (copy_to_user(*ptr, &tmp, sizeof(tmp))) + return -EFAULT; + *ptr += sizeof(tmp); + + break; + } + case BR_DEAD_BINDER: + case BR_CLEAR_DEATH_NOTIFICATION_DONE: { + compat_uptr_t tmp; + + cmd = compat_change_size(cmd, sizeof(tmp)); + BUG_ON((cmd != COMPAT_BR_DEAD_BINDER) && + (cmd != COMPAT_BR_CLEAR_DEATH_NOTIFICATION_DONE)); + + tmp = ptr_to_compat((void *)*(uintptr_t *) parcel); + if (put_user(cmd, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (copy_to_user(*ptr, &tmp, sizeof(tmp))) + return -EFAULT; + *ptr += sizeof(tmp); + + break; + } + case BR_REPLY: + case BR_TRANSACTION: { + struct binder_transaction_data *fp; + struct compat_binder_transaction_data tmp; + + memset(&tmp, 0, sizeof(tmp)); + cmd = compat_change_size(cmd, sizeof(tmp)); + BUG_ON((cmd != COMPAT_BR_REPLY) && + (cmd != COMPAT_BR_TRANSACTION)); + + fp = (struct binder_transaction_data *) parcel; + /* copy to compat struct */ + tmp.target.ptr = ptr_to_compat(fp->target.ptr); + tmp.cookie = ptr_to_compat(fp->cookie); + tmp.code = fp->code; + tmp.flags = fp->flags; + tmp.sender_pid = fp->sender_pid; + tmp.sender_euid = fp->sender_euid; + tmp.data_size = (compat_size_t) fp->data_size; + tmp.offsets_size = (compat_size_t) fp->offsets_size; + tmp.data.ptr.buffer = ptr_to_compat((void *)fp->data.ptr.buffer); + tmp.data.ptr.offsets = ptr_to_compat((void *)fp->data.ptr.offsets); + + if (put_user(cmd, (uint32_t __user *)*ptr)) + return -EFAULT; + *ptr += sizeof(uint32_t); + if (copy_to_user(*ptr, &tmp, sizeof(tmp))) + return -EFAULT; + *ptr += sizeof(tmp); + + break; + } + default: + pr_err("unexpected user copy, cmd %d, ptr %p\n", + cmd, (void *)*(uintptr_t *)ptr); + return -EFAULT; + } + return 0; +} +#else static int binder_copy_to_user(uint32_t cmd, void *parcel, void __user **ptr, size_t size) { @@ -2156,6 +2429,7 @@ static int binder_copy_to_user(uint32_t cmd, void *parcel, *ptr += size; return 0; } +#endif static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, @@ -2750,6 +3024,80 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return ret; } +/* TODO: add tracepoint */ +#ifdef CONFIG_COMPAT +static long compat_binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct binder_thread *thread; + struct compat_binder_write_read bwr; + struct binder_proc *proc = filp->private_data; + void __user *ubuf = compat_ptr(arg); + + /* pr_info("compat_binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg); */ + + if (cmd != COMPAT_BINDER_WRITE_READ) + return binder_ioctl(filp, cmd, arg); + + BUG_ON(!is_compat_task()); + binder_lock(__func__); + thread = binder_get_thread(proc); + if (thread == NULL) { + ret = -ENOMEM; + goto err; + } + + /* COMPAT_BINDER_WRITE_READ */ + if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { + ret = -EFAULT; + goto err; + } + binder_debug(BINDER_DEBUG_READ_WRITE, + "compat: %d:%d write %d at %016x, read %d at %016x\n", + proc->pid, thread->pid, bwr.write_size, + bwr.write_buffer, bwr.read_size, bwr.read_buffer); + + if (bwr.write_size > 0) { + size_t tmp_write_consumed = (size_t)bwr.write_consumed; + ret = binder_thread_write(proc, thread, compat_ptr(bwr.write_buffer), (size_t)bwr.write_size, &tmp_write_consumed); + bwr.write_consumed = (compat_size_t)tmp_write_consumed; + if (ret < 0) { + bwr.read_consumed = 0; + if (copy_to_user(ubuf, &bwr, sizeof(bwr))) + ret = -EFAULT; + goto err; + } + } + + if (bwr.read_size > 0) { + size_t tmp_read_consumed = (size_t)bwr.read_consumed; + ret = binder_thread_read(proc, thread, compat_ptr(bwr.read_buffer), (size_t)bwr.read_size, &tmp_read_consumed, filp->f_flags & O_NONBLOCK); + bwr.read_consumed = (compat_size_t)tmp_read_consumed; + if (!list_empty(&proc->todo)) + wake_up_interruptible(&proc->wait); + if (ret < 0) { + if (copy_to_user(ubuf, &bwr, sizeof(bwr))) + ret = -EFAULT; + goto err; + } + } + binder_debug(BINDER_DEBUG_READ_WRITE, + "compat: %d:%d wrote %d of %d, read return %d of %d\n", + proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, + bwr.read_consumed, bwr.read_size); + if (copy_to_user(ubuf, &bwr, sizeof(bwr))) + ret = -EFAULT; + +err: + if (thread) + thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; + binder_unlock(__func__); + if (ret && ret != -ERESTARTSYS) + pr_info("%d:%d compat ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); + return ret; +} +#endif + static void binder_vma_open(struct vm_area_struct *vma) { struct binder_proc *proc = vma->vm_private_data; @@ -3567,6 +3915,9 @@ static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_binder_ioctl, +#endif .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, From f024263397cfaca5e2e97a27d9db424a42432eaf Mon Sep 17 00:00:00 2001 From: Ashish Sharma Date: Wed, 15 Jan 2014 16:47:16 -0800 Subject: [PATCH 068/147] android: configs: Add CONFIG_NETFILTER_XT_TARGET_IDLETIMER Signed-off-by: Ashish Sharma (cherry picked from commit 5621df1091c7e103bca6cdd1dbecf4333efad4e7) Change-Id: I3104266fa648fc024fee45f1ce9800142898baf7 --- android/configs/android-base.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 1fb9bb5b1ac6..6b67601b7f1a 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -83,6 +83,7 @@ CONFIG_NETFILTER_XT_MATCH_TIME=y CONFIG_NETFILTER_XT_MATCH_U32=y CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_TARGET_NFLOG=y CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y From da8a3700249608e24c3910549a5045cf1908a86d Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Tue, 28 Jan 2014 10:23:19 -0800 Subject: [PATCH 069/147] android: configs: update 3.10 options Change-Id: Ifbda55e570a22ace98d7d74b057ba21a597e0826 --- android/configs/android-base.cfg | 1 - android/configs/android-recommended.cfg | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg index 6b67601b7f1a..00c99e1f3b1f 100644 --- a/android/configs/android-base.cfg +++ b/android/configs/android-base.cfg @@ -17,7 +17,6 @@ CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_SCHED=y CONFIG_DM_CRYPT=y CONFIG_EMBEDDED=y -CONFIG_EXPERIMENTAL=y CONFIG_FB=y CONFIG_HIGH_RES_TIMERS=y CONFIG_INET6_AH=y diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg index 9caa089c5d19..aceee62a3e0b 100644 --- a/android/configs/android-recommended.cfg +++ b/android/configs/android-recommended.cfg @@ -5,7 +5,6 @@ # CONFIG_NF_CONNTRACK_SIP is not set # CONFIG_PM_WAKELOCKS_GC is not set # CONFIG_VT is not set -CONFIG_ANDROID_RAM_CONSOLE=y CONFIG_ANDROID_TIMED_GPIO=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_BLK_DEV_LOOP=y @@ -95,6 +94,9 @@ CONFIG_PM_DEBUG=y CONFIG_PM_RUNTIME=y CONFIG_PM_WAKELOCKS_LIMIT=0 CONFIG_POWER_SUPPLY=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y CONFIG_SCHEDSTATS=y CONFIG_SMARTJOYPLUS_FF=y CONFIG_SND=y From 233fd81496ca2cb483f3987b5753b71d7071531a Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Tue, 28 Jan 2014 15:39:48 -0800 Subject: [PATCH 070/147] ion: Fix ION_IOC_FREE compat ioctl The compat ioctl for ION_IOC_FREE currently passes allocation data instead of the free data. Correct this. Change-Id: I5108a1937104b8368426f7695b4a2df416036a87 Signed-off-by: Laura Abbott --- drivers/staging/android/ion/compat_ion.c | 25 ++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index e9a8132cd56f..fb0ebddbba2b 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -35,9 +35,14 @@ struct compat_ion_custom_data { compat_ulong_t arg; }; +struct compat_ion_handle_data { + compat_int_t handle; +}; + #define COMPAT_ION_IOC_ALLOC _IOWR(ION_IOC_MAGIC, 0, \ struct compat_ion_allocation_data) -#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data) +#define COMPAT_ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, \ + struct compat_ion_handle_data) #define COMPAT_ION_IOC_CUSTOM _IOWR(ION_IOC_MAGIC, 6, \ struct compat_ion_custom_data) @@ -64,6 +69,18 @@ static int compat_get_ion_allocation_data( return err; } +static int compat_get_ion_handle_data( + struct compat_ion_handle_data __user *data32, + struct ion_handle_data __user *data) +{ + compat_int_t i; + + err = get_user(i, &data32->handle); + err |= put_user(i, &data->handle); + + return err; +} + static int compat_put_ion_allocation_data( struct compat_ion_allocation_data __user *data32, struct ion_allocation_data __user *data) @@ -132,8 +149,8 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } case COMPAT_ION_IOC_FREE: { - struct compat_ion_allocation_data __user *data32; - struct ion_allocation_data __user *data; + struct compat_ion_handle_data __user *data32; + struct ion_handle_data __user *data; int err; data32 = compat_ptr(arg); @@ -141,7 +158,7 @@ long compat_ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (data == NULL) return -EFAULT; - err = compat_get_ion_allocation_data(data32, data); + err = compat_get_ion_handle_data(data32, data); if (err) return err; From d4e564429cb89a90b9d5482af884b0b6a85aa284 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 29 Jan 2014 13:00:51 -0800 Subject: [PATCH 071/147] staging: ion: Build fix for compat_ion.c compat_get_ion_handle_data is missing a declaration for the return value. This patch simply adds it, so things build. Change-Id: I1a72a3c56975dc614322a63852f2a6554f2be107 Signed-off-by: John Stultz --- drivers/staging/android/ion/compat_ion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c index fb0ebddbba2b..a5e8c408fd78 100644 --- a/drivers/staging/android/ion/compat_ion.c +++ b/drivers/staging/android/ion/compat_ion.c @@ -74,6 +74,7 @@ static int compat_get_ion_handle_data( struct ion_handle_data __user *data) { compat_int_t i; + int err; err = get_user(i, &data32->handle); err |= put_user(i, &data->handle); From fd762f67b3508e44804d7d7d91532292cb3b113b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 22 May 2013 20:17:31 +0000 Subject: [PATCH 072/147] net: ipv6: Add IPv6 support to the ping socket. [net-next commit 6d0bfe22611602f36617bc7aa2ffa1bbb2f54c67] This adds the ability to send ICMPv6 echo requests without a raw socket. The equivalent ability for ICMPv4 was added in 2011. Instead of having separate code paths for IPv4 and IPv6, make most of the code in net/ipv4/ping.c dual-stack and only add a few IPv6-specific bits (like the protocol definition) to a new net/ipv6/ping.c. Hopefully this will reduce divergence and/or duplication of bugs in the future. Caveats: - Setting options via ancillary data (e.g., using IPV6_PKTINFO to specify the outgoing interface) is not yet supported. - There are no separate security settings for IPv4 and IPv6; everything is controlled by /proc/net/ipv4/ping_group_range. - The proc interface does not yet display IPv6 ping sockets properly. Tested with a patched copy of ping6 and using raw socket calls. Compiles and works with all of CONFIG_IPV6={n,m,y}. Bug: 12800827 Change-Id: I718cd9931823873ab44df22e8a66e12d6a0a6eb1 Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- include/net/ipv6.h | 6 + include/net/ping.h | 49 +++- include/net/transp_v6.h | 3 + net/ipv4/icmp.c | 5 +- net/ipv4/ping.c | 559 ++++++++++++++++++++++++++++------------ net/ipv6/Makefile | 2 +- net/ipv6/af_inet6.c | 12 + net/ipv6/icmp.c | 19 +- net/ipv6/ping.c | 216 ++++++++++++++++ 9 files changed, 699 insertions(+), 172 deletions(-) create mode 100644 net/ipv6/ping.c diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 0810aa57c780..ab47582f6c0b 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -260,6 +260,12 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len); + +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6); + extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); diff --git a/include/net/ping.h b/include/net/ping.h index 682b5ae9af51..9242fa090d3d 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -13,6 +13,7 @@ #ifndef _PING_H #define _PING_H +#include #include /* PING_HTABLE_SIZE must be power of 2 */ @@ -28,6 +29,18 @@ */ #define GID_T_MAX (((gid_t)~0U) >> 1) +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +struct pingv6_ops { + int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); + int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); + void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict); +}; + struct ping_table { struct hlist_nulls_head hash[PING_HTABLE_SIZE]; rwlock_t lock; @@ -39,10 +52,39 @@ struct ping_iter_state { }; extern struct proto ping_prot; +extern struct ping_table ping_table; +#if IS_ENABLED(CONFIG_IPV6) +extern struct pingv6_ops pingv6_ops; +#endif +struct pingfakehdr { + struct icmphdr icmph; + struct iovec *iov; + sa_family_t family; + __wsum wcheck; +}; -extern void ping_rcv(struct sk_buff *); -extern void ping_err(struct sk_buff *, u32 info); +int ping_get_port(struct sock *sk, unsigned short ident); +void ping_hash(struct sock *sk); +void ping_unhash(struct sock *sk); + +int ping_init_sock(struct sock *sk); +void ping_close(struct sock *sk, long timeout); +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len); +void ping_err(struct sk_buff *skb, int offset, u32 info); +int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, + struct sk_buff *); + +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len); +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len); +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); +void ping_rcv(struct sk_buff *skb); #ifdef CONFIG_PROC_FS extern int __init ping_proc_init(void); @@ -50,6 +92,7 @@ extern void ping_proc_exit(void); #endif void __init ping_init(void); - +int __init pingv6_init(void); +void pingv6_exit(void); #endif /* _PING_H */ diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 938b7fd11204..eb40e71ff2ee 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; @@ -21,6 +22,8 @@ extern int ipv6_frag_init(void); extern void ipv6_frag_exit(void); /* transport protocols */ +extern int pingv6_init(void); +extern void pingv6_exit(void); extern int rawv6_init(void); extern void rawv6_exit(void); extern int udpv6_init(void); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 76e10b47e053..562efd91f457 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -939,7 +939,8 @@ int icmp_rcv(struct sk_buff *skb) void icmp_err(struct sk_buff *skb, u32 info) { struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int offset = iph->ihl<<2; + struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset); int type = icmp_hdr(skb)->type; int code = icmp_hdr(skb)->code; struct net *net = dev_net(skb->dev); @@ -949,7 +950,7 @@ void icmp_err(struct sk_buff *skb, u32 info) * triggered by ICMP_ECHOREPLY which sent from kernel. */ if (icmph->type != ICMP_ECHOREPLY) { - ping_err(skb, info); + ping_err(skb, offset, info); return; } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 7d93d62cd5fd..71f6ad02fa67 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,8 +45,18 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#include +#include +#endif -static struct ping_table ping_table; + +struct ping_table ping_table; +struct pingv6_ops pingv6_ops; +EXPORT_SYMBOL_GPL(pingv6_ops); static u16 ping_port_rover; @@ -58,6 +67,7 @@ static inline int ping_hashfn(struct net *net, unsigned int num, unsigned int ma pr_debug("hash(%d) = %d\n", num, res); return res; } +EXPORT_SYMBOL_GPL(ping_hash); static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, struct net *net, unsigned int num) @@ -65,7 +75,7 @@ static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; } -static int ping_v4_get_port(struct sock *sk, unsigned short ident) +int ping_get_port(struct sock *sk, unsigned short ident) { struct hlist_nulls_node *node; struct hlist_nulls_head *hlist; @@ -103,6 +113,10 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) ping_portaddr_for_each_entry(sk2, node, hlist) { isk2 = inet_sk(sk2); + /* BUG? Why is this reuse and not reuseaddr? ping.c + * doesn't turn off SO_REUSEADDR, and it doesn't expect + * that other ping processes can steal its packets. + */ if ((isk2->inet_num == ident) && (sk2 != sk) && (!sk2->sk_reuse || !sk->sk_reuse)) @@ -125,17 +139,18 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) write_unlock_bh(&ping_table.lock); return 1; } +EXPORT_SYMBOL_GPL(ping_get_port); -static void ping_v4_hash(struct sock *sk) +void ping_hash(struct sock *sk) { - pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); + pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); BUG(); /* "Please do not press this button again." */ } -static void ping_v4_unhash(struct sock *sk) +void ping_unhash(struct sock *sk) { struct inet_sock *isk = inet_sk(sk); - pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); @@ -146,31 +161,61 @@ static void ping_v4_unhash(struct sock *sk) write_unlock_bh(&ping_table.lock); } } +EXPORT_SYMBOL_GPL(ping_unhash); -static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr, - u16 ident, int dif) +static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) { struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); struct sock *sk = NULL; struct inet_sock *isk; struct hlist_nulls_node *hnode; + int dif = skb->dev->ifindex; + + if (skb->protocol == htons(ETH_P_IP)) { + pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", + (int)ident, &ip_hdr(skb)->daddr, dif); +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n", + (int)ident, &ipv6_hdr(skb)->daddr, dif); +#endif + } - pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", - (int)ident, &daddr, dif); read_lock_bh(&ping_table.lock); ping_portaddr_for_each_entry(sk, hnode, hslot) { isk = inet_sk(sk); - pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk, - (int)isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); - pr_debug("iterate\n"); if (isk->inet_num != ident) continue; - if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) - continue; + + if (skb->protocol == htons(ETH_P_IP) && + sk->sk_family == AF_INET) { + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, + (int) isk->inet_num, &isk->inet_rcv_saddr, + sk->sk_bound_dev_if); + + if (isk->inet_rcv_saddr && + isk->inet_rcv_saddr != ip_hdr(skb)->daddr) + continue; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6) && + sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, + (int) isk->inet_num, + &inet6_sk(sk)->rcv_saddr, + sk->sk_bound_dev_if); + + if (!ipv6_addr_any(&np->rcv_saddr) && + !ipv6_addr_equal(&np->rcv_saddr, + &ipv6_hdr(skb)->daddr)) + continue; +#endif + } + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) continue; @@ -200,7 +245,7 @@ static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, } -static int ping_init_sock(struct sock *sk) +int ping_init_sock(struct sock *sk) { struct net *net = sock_net(sk); kgid_t group = current_egid(); @@ -225,8 +270,9 @@ static int ping_init_sock(struct sock *sk) return -EACCES; } +EXPORT_SYMBOL_GPL(ping_init_sock); -static void ping_close(struct sock *sk, long timeout) +void ping_close(struct sock *sk, long timeout) { pr_debug("ping_close(sk=%p,sk->num=%u)\n", inet_sk(sk), inet_sk(sk)->inet_num); @@ -234,36 +280,122 @@ static void ping_close(struct sock *sk, long timeout) sk_common_release(sk); } +EXPORT_SYMBOL_GPL(ping_close); +/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */ +int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + struct sockaddr *uaddr, int addr_len) { + struct net *net = sock_net(sk); + if (sk->sk_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; + int chk_addr_ret; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + + chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr); + + if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) + chk_addr_ret = RTN_LOCAL; + + if ((sysctl_ip_nonlocal_bind == 0 && + isk->freebind == 0 && isk->transparent == 0 && + chk_addr_ret != RTN_LOCAL) || + chk_addr_ret == RTN_MULTICAST || + chk_addr_ret == RTN_BROADCAST) + return -EADDRNOTAVAIL; + +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; + int addr_type, scoped, has_addr; + struct net_device *dev = NULL; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); + + addr_type = ipv6_addr_type(&addr->sin6_addr); + scoped = __ipv6_addr_needs_scope_id(addr_type); + if ((addr_type != IPV6_ADDR_ANY && + !(addr_type & IPV6_ADDR_UNICAST)) || + (scoped && !addr->sin6_scope_id)) + return -EINVAL; + + rcu_read_lock(); + if (addr->sin6_scope_id) { + dev = dev_get_by_index_rcu(net, addr->sin6_scope_id); + if (!dev) { + rcu_read_unlock(); + return -ENODEV; + } + } + has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev, + scoped); + rcu_read_unlock(); + + if (!(isk->freebind || isk->transparent || has_addr || + addr_type == IPV6_ADDR_ANY)) + return -EADDRNOTAVAIL; + + if (scoped) + sk->sk_bound_dev_if = addr->sin6_scope_id; +#endif + } else { + return -EAFNOSUPPORT; + } + return 0; +} + +void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) +{ + if (saddr->sa_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *addr = (struct sockaddr_in *) saddr; + isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (saddr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr; + struct ipv6_pinfo *np = inet6_sk(sk); + np->rcv_saddr = np->saddr = addr->sin6_addr; +#endif + } +} + +void ping_clear_saddr(struct sock *sk, int dif) +{ + sk->sk_bound_dev_if = dif; + if (sk->sk_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + isk->inet_rcv_saddr = isk->inet_saddr = 0; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); + memset(&np->saddr, 0, sizeof(np->saddr)); +#endif + } +} /* * We need our own bind because there are no privileged id's == local ports. * Moreover, we don't allow binding to multi- and broadcast addresses. */ -static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct inet_sock *isk = inet_sk(sk); unsigned short snum; - int chk_addr_ret; int err; + int dif = sk->sk_bound_dev_if; - if (addr_len < sizeof(struct sockaddr_in)) - return -EINVAL; - - pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", - sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); - - chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); - if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) - chk_addr_ret = RTN_LOCAL; - - if ((sysctl_ip_nonlocal_bind == 0 && - isk->freebind == 0 && isk->transparent == 0 && - chk_addr_ret != RTN_LOCAL) || - chk_addr_ret == RTN_MULTICAST || - chk_addr_ret == RTN_BROADCAST) - return -EADDRNOTAVAIL; + err = ping_check_bind_addr(sk, isk, uaddr, addr_len); + if (err) + return err; lock_sock(sk); @@ -272,42 +404,50 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) goto out; err = -EADDRINUSE; - isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; - snum = ntohs(addr->sin_port); - if (ping_v4_get_port(sk, snum) != 0) { - isk->inet_saddr = isk->inet_rcv_saddr = 0; + ping_set_saddr(sk, uaddr); + snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port); + if (ping_get_port(sk, snum) != 0) { + ping_clear_saddr(sk, dif); goto out; } - pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n", + pr_debug("after bind(): num = %d, dif = %d\n", (int)isk->inet_num, - &isk->inet_rcv_saddr, (int)sk->sk_bound_dev_if); err = 0; - if (isk->inet_rcv_saddr) + if ((sk->sk_family == AF_INET && isk->inet_rcv_saddr) || + (sk->sk_family == AF_INET6 && + !ipv6_addr_any(&inet6_sk(sk)->rcv_saddr))) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; isk->inet_sport = htons(isk->inet_num); isk->inet_daddr = 0; isk->inet_dport = 0; + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) + memset(&inet6_sk(sk)->daddr, 0, sizeof(inet6_sk(sk)->daddr)); +#endif + sk_dst_reset(sk); out: release_sock(sk); pr_debug("ping_v4_bind -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_bind); /* * Is this a supported type of ICMP message? */ -static inline int ping_supported(int type, int code) +static inline int ping_supported(int family, int type, int code) { - if (type == ICMP_ECHO && code == 0) - return 1; - return 0; + return (family == AF_INET && type == ICMP_ECHO && code == 0) || + (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0); } /* @@ -315,30 +455,42 @@ static inline int ping_supported(int type, int code) * sort of error condition. */ -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); - -void ping_err(struct sk_buff *skb, u32 info) +void ping_err(struct sk_buff *skb, int offset, u32 info) { - struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int family; + struct icmphdr *icmph; struct inet_sock *inet_sock; - int type = icmp_hdr(skb)->type; - int code = icmp_hdr(skb)->code; + int type; + int code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; int err; + if (skb->protocol == htons(ETH_P_IP)) { + family = AF_INET; + type = icmp_hdr(skb)->type; + code = icmp_hdr(skb)->code; + icmph = (struct icmphdr *)(skb->data + offset); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + family = AF_INET6; + type = icmp6_hdr(skb)->icmp6_type; + code = icmp6_hdr(skb)->icmp6_code; + icmph = (struct icmphdr *) (skb->data + offset); + } else { + BUG(); + } + /* We assume the packet has already been checked by icmp_unreach */ - if (!ping_supported(icmph->type, icmph->code)) + if (!ping_supported(family, icmph->type, icmph->code)) return; - pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, - code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n", + skb->protocol, type, code, ntohs(icmph->un.echo.id), + ntohs(icmph->un.echo.sequence)); - sk = ping_v4_lookup(net, iph->daddr, iph->saddr, - ntohs(icmph->un.echo.id), skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk == NULL) { pr_debug("no socket, dropping\n"); return; /* No socket for error */ @@ -349,72 +501,83 @@ void ping_err(struct sk_buff *skb, u32 info) harderr = 0; inet_sock = inet_sk(sk); - switch (type) { - default: - case ICMP_TIME_EXCEEDED: - err = EHOSTUNREACH; - break; - case ICMP_SOURCE_QUENCH: - /* This is not a real error but ping wants to see it. - * Report it with some fake errno. */ - err = EREMOTEIO; - break; - case ICMP_PARAMETERPROB: - err = EPROTO; - harderr = 1; - break; - case ICMP_DEST_UNREACH: - if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - ipv4_sk_update_pmtu(skb, sk, info); - if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { - err = EMSGSIZE; - harderr = 1; - break; + if (skb->protocol == htons(ETH_P_IP)) { + switch (type) { + default: + case ICMP_TIME_EXCEEDED: + err = EHOSTUNREACH; + break; + case ICMP_SOURCE_QUENCH: + /* This is not a real error but ping wants to see it. + * Report it with some fake errno. + */ + err = EREMOTEIO; + break; + case ICMP_PARAMETERPROB: + err = EPROTO; + harderr = 1; + break; + case ICMP_DEST_UNREACH: + if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ + ipv4_sk_update_pmtu(skb, sk, info); + if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { + err = EMSGSIZE; + harderr = 1; + break; + } + goto out; } - goto out; + err = EHOSTUNREACH; + if (code <= NR_ICMP_UNREACH) { + harderr = icmp_err_convert[code].fatal; + err = icmp_err_convert[code].errno; + } + break; + case ICMP_REDIRECT: + /* See ICMP_SOURCE_QUENCH */ + ipv4_sk_redirect(skb, sk); + err = EREMOTEIO; + break; } - err = EHOSTUNREACH; - if (code <= NR_ICMP_UNREACH) { - harderr = icmp_err_convert[code].fatal; - err = icmp_err_convert[code].errno; - } - break; - case ICMP_REDIRECT: - /* See ICMP_SOURCE_QUENCH */ - ipv4_sk_redirect(skb, sk); - err = EREMOTEIO; - break; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + harderr = pingv6_ops.icmpv6_err_convert(type, code, &err); +#endif } /* * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!inet_sock->recverr) { + if ((family == AF_INET && !inet_sock->recverr) || + (family == AF_INET6 && !inet6_sk(sk)->recverr)) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; } else { - ip_icmp_error(sk, skb, err, 0 /* no remote port */, - info, (u8 *)icmph); + if (family == AF_INET) { + ip_icmp_error(sk, skb, err, 0 /* no remote port */, + info, (u8 *)icmph); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + pingv6_ops.ipv6_icmp_error(sk, skb, err, 0, + info, (u8 *)icmph); +#endif + } } sk->sk_err = err; sk->sk_error_report(sk); out: sock_put(sk); } +EXPORT_SYMBOL_GPL(ping_err); /* - * Copy and checksum an ICMP Echo packet from user space into a buffer. + * Copy and checksum an ICMP Echo packet from user space into a buffer + * starting from the payload. */ -struct pingfakehdr { - struct icmphdr icmph; - struct iovec *iov; - __wsum wcheck; -}; - -static int ping_getfrag(void *from, char *to, - int offset, int fraglen, int odd, struct sk_buff *skb) +int ping_getfrag(void *from, char *to, + int offset, int fraglen, int odd, struct sk_buff *skb) { struct pingfakehdr *pfh = (struct pingfakehdr *)from; @@ -425,20 +588,33 @@ static int ping_getfrag(void *from, char *to, pfh->iov, 0, fraglen - sizeof(struct icmphdr), &pfh->wcheck)) return -EFAULT; - - return 0; + } else if (offset < sizeof(struct icmphdr)) { + BUG(); + } else { + if (csum_partial_copy_fromiovecend + (to, pfh->iov, offset - sizeof(struct icmphdr), + fraglen, &pfh->wcheck)) + return -EFAULT; } - if (offset < sizeof(struct icmphdr)) - BUG(); - if (csum_partial_copy_fromiovecend - (to, pfh->iov, offset - sizeof(struct icmphdr), - fraglen, &pfh->wcheck)) - return -EFAULT; + +#if IS_ENABLED(CONFIG_IPV6) + /* For IPv6, checksum each skb as we go along, as expected by + * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in + * wcheck, it will be finalized in ping_v4_push_pending_frames. + */ + if (pfh->family == AF_INET6) { + skb->csum = pfh->wcheck; + skb->ip_summed = CHECKSUM_NONE; + pfh->wcheck = 0; + } +#endif + return 0; } +EXPORT_SYMBOL_GPL(ping_getfrag); -static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, - struct flowi4 *fl4) +static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, + struct flowi4 *fl4) { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); @@ -450,24 +626,9 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, return ip_push_pending_frames(sk, fl4); } -static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) -{ - struct net *net = sock_net(sk); - struct flowi4 fl4; - struct inet_sock *inet = inet_sk(sk); - struct ipcm_cookie ipc; - struct icmphdr user_icmph; - struct pingfakehdr pfh; - struct rtable *rt = NULL; - struct ip_options_data opt_copy; - int free = 0; - __be32 saddr, daddr, faddr; - u8 tos; - int err; - - pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); - +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len) { + u8 type, code; if (len > 0xFFFF) return -EMSGSIZE; @@ -482,15 +643,53 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* * Fetch the ICMP header provided by the userland. - * iovec is modified! + * iovec is modified! The ICMP header is consumed. */ - - if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, - sizeof(struct icmphdr))) + if (memcpy_fromiovec(user_icmph, msg->msg_iov, icmph_len)) return -EFAULT; - if (!ping_supported(user_icmph.type, user_icmph.code)) + + if (family == AF_INET) { + type = ((struct icmphdr *) user_icmph)->type; + code = ((struct icmphdr *) user_icmph)->code; +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + type = ((struct icmp6hdr *) user_icmph)->icmp6_type; + code = ((struct icmp6hdr *) user_icmph)->icmp6_code; +#endif + } else { + BUG(); + } + + if (!ping_supported(family, type, code)) return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(ping_common_sendmsg); + +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct net *net = sock_net(sk); + struct flowi4 fl4; + struct inet_sock *inet = inet_sk(sk); + struct ipcm_cookie ipc; + struct icmphdr user_icmph; + struct pingfakehdr pfh; + struct rtable *rt = NULL; + struct ip_options_data opt_copy; + int free = 0; + __be32 saddr, daddr, faddr; + u8 tos; + int err; + + pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + /* * Get and verify the address. */ @@ -595,13 +794,14 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; pfh.iov = msg->msg_iov; pfh.wcheck = 0; + pfh.family = AF_INET; err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else - err = ping_push_pending_frames(sk, &pfh, &fl4); + err = ping_v4_push_pending_frames(sk, &pfh, &fl4); release_sock(sk); out: @@ -622,11 +822,13 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } -static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); - struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + int family = sk->sk_family; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; struct sk_buff *skb; int copied, err; @@ -636,11 +838,22 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); + if (addr_len) { + if (family == AF_INET) + *addr_len = sizeof(*sin); + else if (family == AF_INET6 && addr_len) + *addr_len = sizeof(*sin6); + } - if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { + return ip_recv_error(sk, msg, len); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + return pingv6_ops.ipv6_recv_error(sk, msg, len); +#endif + } + } skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -659,15 +872,40 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sock_recv_timestamp(msg, sk, skb); - /* Copy the address. */ - if (sin) { + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { + sin = (struct sockaddr_in *) msg->msg_name; sin->sin_family = AF_INET; sin->sin_port = 0 /* skb->h.uh->source */; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); + +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); + sin6 = (struct sockaddr_in6 *) msg->msg_name; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; + + if (np->sndflow) + sin6->sin6_flowinfo = ip6_flowinfo(ip6); + + if (__ipv6_addr_needs_scope_id( + ipv6_addr_type(&sin6->sin6_addr))) + sin6->sin6_scope_id = IP6CB(skb)->iif; + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); +#endif + } else { + BUG(); } - if (isk->cmsg_flags) - ip_cmsg_recv(msg, skb); + err = copied; done: @@ -676,8 +914,9 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pr_debug("ping_recvmsg -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_recvmsg); -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", inet_sk(sk), inet_sk(sk)->inet_num, skb); @@ -688,6 +927,7 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } return 0; } +EXPORT_SYMBOL_GPL(ping_queue_rcv_skb); /* @@ -698,10 +938,7 @@ void ping_rcv(struct sk_buff *skb) { struct sock *sk; struct net *net = dev_net(skb->dev); - struct iphdr *iph = ip_hdr(skb); struct icmphdr *icmph = icmp_hdr(skb); - __be32 saddr = iph->saddr; - __be32 daddr = iph->daddr; /* We assume the packet has already been checked by icmp_rcv */ @@ -711,8 +948,7 @@ void ping_rcv(struct sk_buff *skb) /* Push ICMP header back */ skb_push(skb, skb->data - (u8 *)icmph); - sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), - skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk != NULL) { pr_debug("rcv on socket %p\n", sk); ping_queue_rcv_skb(sk, skb_get(skb)); @@ -723,6 +959,7 @@ void ping_rcv(struct sk_buff *skb) /* We're called from icmp_rcv(). kfree_skb() is done there. */ } +EXPORT_SYMBOL_GPL(ping_rcv); struct proto ping_prot = { .name = "PING", @@ -733,14 +970,14 @@ struct proto ping_prot = { .disconnect = udp_disconnect, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, - .sendmsg = ping_sendmsg, + .sendmsg = ping_v4_sendmsg, .recvmsg = ping_recvmsg, .bind = ping_bind, .backlog_rcv = ping_queue_rcv_skb, .release_cb = ip4_datagram_release_cb, - .hash = ping_v4_hash, - .unhash = ping_v4_unhash, - .get_port = ping_v4_get_port, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, .obj_size = sizeof(struct inet_sock), }; EXPORT_SYMBOL(ping_prot); diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 9af088d2cdaa..470a9c008e9b 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ - raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o ipv6-offload := ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index ebf231016b1f..a4cfde67fcb7 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -873,6 +874,9 @@ static int __init inet6_init(void) if (err) goto out_unregister_udplite_proto; + err = proto_register(&pingv6_prot, 1); + if (err) + goto out_unregister_ping_proto; /* We MUST register RAW sockets before we create the ICMP6, * IGMP6, or NDISC control sockets. @@ -963,6 +967,10 @@ static int __init inet6_init(void) if (err) goto ipv6_packet_fail; + err = pingv6_init(); + if (err) + goto pingv6_fail; + #ifdef CONFIG_SYSCTL err = ipv6_sysctl_register(); if (err) @@ -975,6 +983,8 @@ static int __init inet6_init(void) sysctl_fail: ipv6_packet_cleanup(); #endif +pingv6_fail: + pingv6_exit(); ipv6_packet_fail: tcpv6_exit(); tcpv6_fail: @@ -1018,6 +1028,8 @@ static int __init inet6_init(void) rtnl_unregister_all(PF_INET6); out_sock_register_fail: rawv6_exit(); +out_unregister_ping_proto: + proto_unregister(&pingv6_prot); out_unregister_raw_proto: proto_unregister(&rawv6_prot); out_unregister_udplite_proto: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index b4ff0a42b8c7..1d2902e61786 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -57,6 +57,7 @@ #include #include +#include #include #include #include @@ -84,12 +85,18 @@ static inline struct sock *icmpv6_sk(struct net *net) static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) { + /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ + struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); struct net *net = dev_net(skb->dev); if (type == ICMPV6_PKT_TOOBIG) ip6_update_pmtu(skb, net, info, 0, 0); else if (type == NDISC_REDIRECT) ip6_redirect(skb, net, 0, 0); + + if (!(type & ICMPV6_INFOMSG_MASK)) + if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) + ping_err(skb, offset, info); } static int icmpv6_rcv(struct sk_buff *skb); @@ -224,7 +231,8 @@ static bool opt_unrec(struct sk_buff *skb, __u32 offset) return (*op & 0xC0) == 0x80; } -static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len) { struct sk_buff *skb; struct icmp6hdr *icmp6h; @@ -307,8 +315,8 @@ static void mip6_addr_swap(struct sk_buff *skb) static inline void mip6_addr_swap(struct sk_buff *skb) {} #endif -static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, - struct sock *sk, struct flowi6 *fl6) +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6) { struct dst_entry *dst, *dst2; struct flowi6 fl2; @@ -697,7 +705,8 @@ static int icmpv6_rcv(struct sk_buff *skb) skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", + LIMIT_NETDEBUG(KERN_DEBUG + "ICMPv6 checksum failed [%pI6c > %pI6c]\n", saddr, daddr); goto csum_error; } @@ -718,7 +727,7 @@ static int icmpv6_rcv(struct sk_buff *skb) break; case ICMPV6_ECHO_REPLY: - /* we couldn't care less */ + ping_rcv(skb); break; case ICMPV6_PKT_TOOBIG: diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c new file mode 100644 index 000000000000..a6462d657c15 --- /dev/null +++ b/net/ipv6/ping.c @@ -0,0 +1,216 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * "Ping" sockets + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Based on ipv4/ping.c code. + * + * Authors: Lorenzo Colitti (IPv6 support) + * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6), + * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct proto pingv6_prot = { + .name = "PINGv6", + .owner = THIS_MODULE, + .init = ping_init_sock, + .close = ping_close, + .connect = ip6_datagram_connect, + .disconnect = udp_disconnect, + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .sendmsg = ping_v6_sendmsg, + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, + .obj_size = sizeof(struct raw6_sock), +}; +EXPORT_SYMBOL_GPL(pingv6_prot); + +static struct inet_protosw pingv6_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_ICMPV6, + .prot = &pingv6_prot, + .ops = &inet6_dgram_ops, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, +}; + + +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +{ + return -EAFNOSUPPORT; +} +int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb) +{ + return -EAFNOSUPPORT; +} +int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) +{ + return -EAFNOSUPPORT; +} +void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload) {} +int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict) +{ + return 0; +} + +int __init pingv6_init(void) +{ + pingv6_ops.ipv6_recv_error = ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; + return inet6_register_protosw(&pingv6_protosw); +} + +/* This never gets called because it's not possible to unload the ipv6 module, + * but just in case. + */ +void pingv6_exit(void) +{ + pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; + pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; + inet6_unregister_protosw(&pingv6_protosw); +} + +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct icmp6hdr user_icmph; + int addr_type; + struct in6_addr *daddr; + int iif = 0; + struct flowi6 fl6; + int err; + int hlimit; + struct dst_entry *dst; + struct rt6_info *rt; + struct pingfakehdr pfh; + + pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + + if (msg->msg_name) { + struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; + if (msg->msg_namelen < sizeof(struct sockaddr_in6) || + u->sin6_family != AF_INET6) { + return -EINVAL; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { + return -EINVAL; + } + daddr = &(u->sin6_addr); + iif = u->sin6_scope_id; + } else { + if (sk->sk_state != TCP_ESTABLISHED) + return -EDESTADDRREQ; + daddr = &np->daddr; + } + + if (!iif) + iif = sk->sk_bound_dev_if; + + addr_type = ipv6_addr_type(daddr); + if (__ipv6_addr_needs_scope_id(addr_type) && !iif) + return -EINVAL; + if (addr_type & IPV6_ADDR_MAPPED) + return -EINVAL; + + /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ + + memset(&fl6, 0, sizeof(fl6)); + + fl6.flowi6_proto = IPPROTO_ICMPV6; + fl6.saddr = np->saddr; + fl6.daddr = *daddr; + fl6.fl6_icmp_type = user_icmph.icmp6_type; + fl6.fl6_icmp_code = user_icmph.icmp6_code; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 1); + if (IS_ERR(dst)) + return PTR_ERR(dst); + rt = (struct rt6_info *) dst; + + np = inet6_sk(sk); + if (!np) + return -EBADF; + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + pfh.icmph.type = user_icmph.icmp6_type; + pfh.icmph.code = user_icmph.icmp6_code; + pfh.icmph.checksum = 0; + pfh.icmph.un.echo.id = inet->inet_sport; + pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; + pfh.iov = msg->msg_iov; + pfh.wcheck = 0; + pfh.family = AF_INET6; + + if (ipv6_addr_is_multicast(&fl6.daddr)) + hlimit = np->mcast_hops; + else + hlimit = np->hop_limit; + if (hlimit < 0) + hlimit = ip6_dst_hoplimit(dst); + + err = ip6_append_data(sk, ping_getfrag, &pfh, len, + 0, hlimit, + np->tclass, NULL, &fl6, rt, + MSG_DONTWAIT, np->dontfrag); + + if (err) { + ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, + ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, + (struct icmp6hdr *) &pfh.icmph, + len); + } + + return err; +} From 51d00bd5efb17e555a5c1f50a597b3eda5fea2f9 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 2 Jun 2013 22:43:52 +0000 Subject: [PATCH 073/147] ping: always initialize ->sin6_scope_id and ->sin6_flowinfo [net-next commit c26d6b46da3ee86fa8a864347331e5513ca84c2b] If we don't need scope id, we should initialize it to zero. Same for ->sin6_flowinfo. Bug: 12800827 Change-Id: Ic19792cee3f5dc30237562cf48e6bdf49817c96e Cc: Lorenzo Colitti Cc: David S. Miller Signed-off-by: Cong Wang Acked-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv4/ping.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 71f6ad02fa67..0f419a2208ff 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -892,12 +892,12 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sin6->sin6_port = 0; sin6->sin6_addr = ip6->saddr; + sin6->sin6_flowinfo = 0; if (np->sndflow) sin6->sin6_flowinfo = ip6_flowinfo(ip6); - if (__ipv6_addr_needs_scope_id( - ipv6_addr_type(&sin6->sin6_addr))) - sin6->sin6_scope_id = IP6CB(skb)->iif; + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); if (inet6_sk(sk)->rxopt.all) pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); From 2ac994153e3126cc9a011926b63fcd215a2a71c8 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Jul 2013 00:12:40 +0900 Subject: [PATCH 074/147] net: ipv6: fix wrong ping_v6_sendmsg return value [net-next commit fbfe80c890a1dc521d0b629b870e32fcffff0da5] ping_v6_sendmsg currently returns 0 on success. It should return the number of bytes written instead. Bug: 12800827 Change-Id: I7ed17dc61afbb68a84908e67e44db976ec812bad Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/ping.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index a6462d657c15..1f4886857b44 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -212,5 +212,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, len); } - return err; + if (err) + return err; + + return len; } From b918c72ce27090051ac9681bfd162abcec0abceb Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Jul 2013 00:52:49 +0900 Subject: [PATCH 075/147] net: ipv6: add missing lock in ping_v6_sendmsg [net-next commit a1bdc45580fc19e968b32ad27cd7e476a4aa58f6] Bug: 12800827 Change-Id: I93d897e5043dc89bc99f111c89ef4f8b1fa1885d Signed-off-by: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/ping.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 1f4886857b44..858788da5a2f 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -197,6 +197,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (hlimit < 0) hlimit = ip6_dst_hoplimit(dst); + lock_sock(sk); err = ip6_append_data(sk, ping_getfrag, &pfh, len, 0, hlimit, np->tclass, NULL, &fl6, rt, @@ -211,6 +212,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, (struct icmp6hdr *) &pfh.icmph, len); } + release_sock(sk); if (err) return err; From 5a0312add72620b4bd67ccb7cde887ef2b95cd6d Mon Sep 17 00:00:00 2001 From: Hannes Frederic Sowa Date: Mon, 18 Nov 2013 07:07:45 +0100 Subject: [PATCH 076/147] ping: prevent NULL pointer dereference on write to msg_name A plain read() on a socket does set msg->msg_name to NULL. So check for NULL pointer first. [Backport of net-next cf970c002d270c36202bd5b9c2804d3097a52da0] Bug: 12780426 Change-Id: I3df76aca2fa56478b9a33c404f7b1f0940475ef7 Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Lorenzo Colitti --- net/ipv4/ping.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 0f419a2208ff..edd6e74cad35 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -875,10 +875,12 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* Copy the address and add cmsg data. */ if (family == AF_INET) { sin = (struct sockaddr_in *) msg->msg_name; - sin->sin_family = AF_INET; - sin->sin_port = 0 /* skb->h.uh->source */; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + if (sin) { + sin->sin_family = AF_INET; + sin->sin_port = 0 /* skb->h.uh->source */; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + } if (isk->cmsg_flags) ip_cmsg_recv(msg, skb); @@ -888,16 +890,18 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6hdr *ip6 = ipv6_hdr(skb); sin6 = (struct sockaddr_in6 *) msg->msg_name; - sin6->sin6_family = AF_INET6; - sin6->sin6_port = 0; - sin6->sin6_addr = ip6->saddr; - sin6->sin6_flowinfo = 0; - if (np->sndflow) - sin6->sin6_flowinfo = ip6_flowinfo(ip6); - - sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, - IP6CB(skb)->iif); + if (sin6) { + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; + sin6->sin6_flowinfo = 0; + if (np->sndflow) + sin6->sin6_flowinfo = ip6_flowinfo(ip6); + sin6->sin6_scope_id = + ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); + } if (inet6_sk(sk)->rxopt.all) pingv6_ops.ip6_datagram_recv_ctl(sk, msg, skb); From 6e23832c042e05fcc25f9d26e7e3f7959cce7c54 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 31 Jan 2014 11:22:18 -0800 Subject: [PATCH 077/147] Fix aarch64 build issue with ION In trying to build ION for aarch64, I came across the following build error: In file included from /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/page.h:39:0, from drivers/staging/android/ion/ion_system_heap.c:17: /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/pgtable-3level-types.h:19:1: error: unknown type name u64 typedef u64 pteval_t; ^ /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/pgtable-3level-types.h:20:1: error: unknown type name u64 typedef u64 pmdval_t; ^ ... The problem is asm/page.h doesn't include anything that defines u64, so add an asm/types.h include to the pgtable-3level-types.h to match upstream and avoid the issue. Change-Id: I23f6d2e909cb4de1f9b4f21eb20f9200367faddd Signed-off-by: John Stultz --- arch/arm64/include/asm/pgtable-3level-types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/pgtable-3level-types.h b/arch/arm64/include/asm/pgtable-3level-types.h index 4489615f14a9..4e94424938a4 100644 --- a/arch/arm64/include/asm/pgtable-3level-types.h +++ b/arch/arm64/include/asm/pgtable-3level-types.h @@ -16,6 +16,8 @@ #ifndef __ASM_PGTABLE_3LEVEL_TYPES_H #define __ASM_PGTABLE_3LEVEL_TYPES_H +#include + typedef u64 pteval_t; typedef u64 pmdval_t; typedef u64 pgdval_t; From 5675c04044d70363f6ada070aea41a5434ed6741 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Fri, 31 Jan 2014 11:22:18 -0800 Subject: [PATCH 078/147] Fix aarch64 build issue with ION In trying to build ION for aarch64, I came across the following build error: In file included from /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/page.h:39:0, from drivers/staging/android/ion/ion_system_heap.c:17: /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/pgtable-3level-types.h:19:1: error: unknown type name u64 typedef u64 pteval_t; ^ /home/jstultz/projects/linux/linaro.android/arch/arm64/include/asm/pgtable-3level-types.h:20:1: error: unknown type name u64 typedef u64 pmdval_t; ^ ... The problem is asm/page.h doesn't include anything that defines u64, so add an asm/types.h include to the pgtable-3level-types.h to match upstream and avoid the issue. Change-Id: I3f098bf666761ac6b316389a46d37cc449c342d6 Signed-off-by: John Stultz --- arch/arm64/include/asm/pgtable-3level-types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/pgtable-3level-types.h b/arch/arm64/include/asm/pgtable-3level-types.h index 4489615f14a9..4e94424938a4 100644 --- a/arch/arm64/include/asm/pgtable-3level-types.h +++ b/arch/arm64/include/asm/pgtable-3level-types.h @@ -16,6 +16,8 @@ #ifndef __ASM_PGTABLE_3LEVEL_TYPES_H #define __ASM_PGTABLE_3LEVEL_TYPES_H +#include + typedef u64 pteval_t; typedef u64 pmdval_t; typedef u64 pgdval_t; From 7b03678ec56f64297df40c873fdfaf87d5a3a1f8 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:43 +0100 Subject: [PATCH 079/147] staging: android: binder: modify struct binder_write_read to use size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change mirrors the userspace operation where struct binder_write_read members that specify the buffer size and consumed size are size_t elements. The patch also fixes the binder_thread_write() and binder_thread_read() functions prototypes to conform with the definition of binder_write_read. The changes do not affect existing 32bit ABI. Change-Id: I987246d507b9c5e4627c62a1da971d11869ac5a0 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 10 +++++----- drivers/staging/android/uapi/binder.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index f8d5b03f5444..59e714cd8e1b 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1719,7 +1719,7 @@ static void binder_transaction(struct binder_proc *proc, } int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, signed long *consumed) + void __user *buffer, size_t size, size_t *consumed) { uint32_t cmd; void __user *ptr = buffer + *consumed; @@ -2099,8 +2099,8 @@ static int binder_has_thread_work(struct binder_thread *thread) static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, - signed long *consumed, int non_block) + void __user *buffer, size_t size, + size_t *consumed, int non_block) { void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2597,7 +2597,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %ld at %08lx, read %ld at %08lx\n", + "%d:%d write %zd at %08lx, read %zd at %08lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); @@ -2623,7 +2623,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d wrote %ld of %ld, read return %ld of %ld\n", + "%d:%d wrote %zd of %zd, read return %zd of %zd\n", proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index b6cb483592ca..9e19f64e25aa 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -67,11 +67,11 @@ struct flat_binder_object { */ struct binder_write_read { - signed long write_size; /* bytes to write */ - signed long write_consumed; /* bytes consumed by driver */ + size_t write_size; /* bytes to write */ + size_t write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; - signed long read_size; /* bytes to read */ - signed long read_consumed; /* bytes consumed by driver */ + size_t read_size; /* bytes to read */ + size_t read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; }; From a0bd9ce4b5492666ffdbfe1cb71b236900a4a64e Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:44 +0100 Subject: [PATCH 080/147] staging: android: binder: fix BINDER_SET_MAX_THREADS declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change will fix the BINDER_SET_MAX_THREADS ioctl to use __u32 instead of size_t for setting the max threads. Thus using the same handler for 32 and 64bit kernels. This value is stored internally in struct binder_proc and set to 15 on open_binder() in the libbinder API(thus no need for a 64bit size_t on 64bit platforms). The change does not affect existing 32bit ABI. Change-Id: Ibdfe10a70d475a91c247dc36e9cfd74a259d50e4 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 9e19f64e25aa..db9abe37ac94 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -86,7 +86,7 @@ struct binder_version { #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) -#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t) +#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) From 032f0c2707ac7f21114eda0889bacda10156a2da Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:45 +0100 Subject: [PATCH 081/147] staging: android: binder: fix BC_FREE_BUFFER ioctl declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BinderDriverCommands mirror the ioctl usage. Thus the size of the structure passed through the interface should be used to generate the ioctl No. The change reflects the type being passed from the user space-a pointer to a binder_buffer. This change should not affect the existing 32bit user space since BC_FREE_BUFFER is computed as: #define _IOW(type,nr,size) \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) and for a 32bit compiler BC_FREE_BUFFER will have the same computed value. This change will also ease our work in differentiating BC_FREE_BUFFER from COMPAT_BC_FREE_BUFFER. The change does not affect existing 32bit ABI. Change-Id: I2e0ae87bc4e913225a8eb2912913f7e3617cb575 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index db9abe37ac94..3de85afb5b69 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -265,7 +265,7 @@ enum binder_driver_command_protocol { * Else you have acquired a primary reference on the object. */ - BC_FREE_BUFFER = _IOW('c', 3, int), + BC_FREE_BUFFER = _IOW('c', 3, void *), /* * void *: ptr to transaction data received on a read */ From 74a9e70a3f31c2175541d935658bfedbe386d2a0 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:46 +0100 Subject: [PATCH 082/147] staging: android: binder: fix alignment issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Android userspace aligns the data written to the binder buffers to 4bytes. Thus for 32bit platforms or 64bit platforms running an 32bit Android userspace we can have a buffer looking like this: platform buffer(binder_cmd pointer) size 32/32 32b 32b 8B 64/32 32b 64b 12B 64/64 32b 64b 12B Thus the kernel needs to check that the buffer size is aligned to 4bytes not to (void *) that will be 8bytes on 64bit machines. The change does not affect existing 32bit ABI. Change-Id: I7535f07301519623ea6334f525d312d687407ed4 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 59e714cd8e1b..6e8b0e742405 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1249,7 +1249,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { pr_err("transaction release %d bad offset %zd, size %zd\n", debug_id, *offp, buffer->data_size); continue; @@ -1502,7 +1502,7 @@ static void binder_transaction(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { binder_user_error("%d:%d got transaction with invalid offset, %zd\n", proc->pid, thread->pid, *offp); return_error = BR_FAILED_REPLY; From c9371023516e4831edbe804d50492f2cca924ff1 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:47 +0100 Subject: [PATCH 083/147] staging: android: binder: replace types with portable ones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this driver is meant to be used on different types of processors and a portable driver should specify the size a variable expects to be this patch changes the types used throughout the binder interface. We use "userspace" types since this header will be exported and used by the Android filesystem. The patch does not change in any way the functionality of the binder driver. Change-Id: Ib26daab8bc44b92d4a09badc8ecb64d37ee8773b Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/binder.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 3de85afb5b69..e1f547bb485f 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -123,10 +123,10 @@ struct binder_transaction_data { void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ - unsigned int code; /* transaction command */ + __u32 code; /* transaction command */ /* General information about the transaction. */ - unsigned int flags; + __u32 flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ @@ -143,7 +143,7 @@ struct binder_transaction_data { /* offsets from buffer to flat_binder_object structs */ const void __user *offsets; } ptr; - uint8_t buf[8]; + __u8 buf[8]; } data; }; @@ -153,18 +153,18 @@ struct binder_ptr_cookie { }; struct binder_pri_desc { - int priority; - int desc; + __s32 priority; + __s32 desc; }; struct binder_pri_ptr_cookie { - int priority; + __s32 priority; void *ptr; void *cookie; }; enum binder_driver_return_protocol { - BR_ERROR = _IOR('r', 0, int), + BR_ERROR = _IOR('r', 0, __s32), /* * int: error code */ @@ -178,7 +178,7 @@ enum binder_driver_return_protocol { * binder_transaction_data: the received command. */ - BR_ACQUIRE_RESULT = _IOR('r', 4, int), + BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), /* * not currently supported * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. @@ -258,7 +258,7 @@ enum binder_driver_command_protocol { * binder_transaction_data: the sent command. */ - BC_ACQUIRE_RESULT = _IOW('c', 2, int), + BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), /* * not currently supported * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. @@ -270,10 +270,10 @@ enum binder_driver_command_protocol { * void *: ptr to transaction data received on a read */ - BC_INCREFS = _IOW('c', 4, int), - BC_ACQUIRE = _IOW('c', 5, int), - BC_RELEASE = _IOW('c', 6, int), - BC_DECREFS = _IOW('c', 7, int), + BC_INCREFS = _IOW('c', 4, __u32), + BC_ACQUIRE = _IOW('c', 5, __u32), + BC_RELEASE = _IOW('c', 6, __u32), + BC_DECREFS = _IOW('c', 7, __u32), /* * int: descriptor */ From 20bc01a685bb82d44478e58b6b2d3799062d3e42 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:48 +0100 Subject: [PATCH 084/147] staging: android: binder: fix binder interface for 64bit compat layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes in this patch will fix the binder interface for use on 64bit machines and stand as the base of the 64bit compat support. The changes apply to the structures that are passed between the kernel and userspace. Most of the changes applied mirror the change to struct binder_version where there is no need for a 64bit wide protocol_version(on 64bit machines). The change inlines with the existing 32bit userspace(the structure has the same size) and simplifies the compat layer such that the same handler can service the BINDER_VERSION ioctl. Other changes make use of kernel types as well as user-exportable ones and fix format specifier issues. The changes do not affect existing 32bit ABI. Change-Id: Icccc8d47c302930cc61cddc5749b4cc74dc84117 Signed-off-by: Serban Constantinescu Acked-by: Arve Hjønnevåg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 20 ++++++++++---------- drivers/staging/android/uapi/binder.h | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 6e8b0e742405..b9a7d9347784 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1273,7 +1273,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - pr_err("transaction release %d bad handle %ld\n", + pr_err("transaction release %d bad handle %d\n", debug_id, fp->handle); break; } @@ -1285,13 +1285,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_FD: binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld\n", fp->handle); + " fd %d\n", fp->handle); if (failed_at) task_close_fd(proc, fp->handle); break; default: - pr_err("transaction release %d bad object type %lx\n", + pr_err("transaction release %d bad object type %x\n", debug_id, fp->type); break; } @@ -1557,7 +1557,7 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - binder_user_error("%d:%d got transaction with invalid handle, %ld\n", + binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; @@ -1604,13 +1604,13 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { - binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if (!target_node->accept_fds) { - binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; @@ -1618,7 +1618,7 @@ static void binder_transaction(struct binder_proc *proc, file = fget(fp->handle); if (file == NULL) { - binder_user_error("%d:%d got transaction with invalid fd, %ld\n", + binder_user_error("%d:%d got transaction with invalid fd, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fget_failed; @@ -1637,13 +1637,13 @@ static void binder_transaction(struct binder_proc *proc, task_fd_install(target_proc, target_fd, file); trace_binder_transaction_fd(t, fp->handle, target_fd); binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld -> %d\n", fp->handle, target_fd); + " fd %d -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; default: - binder_user_error("%d:%d got transaction with invalid object type, %lx\n", + binder_user_error("%d:%d got transaction with invalid object type, %x\n", proc->pid, thread->pid, fp->type); return_error = BR_FAILED_REPLY; goto err_bad_object_type; @@ -2597,7 +2597,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %zd at %08lx, read %zd at %08lx\n", + "%d:%d write %zd at %016lx, read %zd at %016lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index e1f547bb485f..e76cfa876daa 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -48,13 +48,13 @@ enum { */ struct flat_binder_object { /* 8 bytes for large_flat_header. */ - unsigned long type; - unsigned long flags; + __u32 type; + __u32 flags; /* 8 bytes of data. */ union { void __user *binder; /* local object */ - signed long handle; /* remote object */ + __u32 handle; /* remote object */ }; /* extra data associated with local object */ @@ -78,7 +78,7 @@ struct binder_write_read { /* Use with BINDER_VERSION, driver fills in fields. */ struct binder_version { /* driver protocol version -- increment with incompatible change */ - signed long protocol_version; + __s32 protocol_version; }; /* This is the current protocol version. */ @@ -119,7 +119,7 @@ struct binder_transaction_data { * identifying the target and contents of the transaction. */ union { - size_t handle; /* target descriptor of command transaction */ + __u32 handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ @@ -154,7 +154,7 @@ struct binder_ptr_cookie { struct binder_pri_desc { __s32 priority; - __s32 desc; + __u32 desc; }; struct binder_pri_ptr_cookie { From b96e1ae1d7d6f275e985ebdd0f426f16dd371451 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Wed, 15 Jan 2014 11:28:36 +0000 Subject: [PATCH 085/147] staging: android: binder: fix ABI for 64bit Android This patch fixes the ABI for 64bit Android userspace. BC_REQUEST_DEATH_NOTIFICATION and BC_CLEAR_DEATH_NOTIFICATION claim to be using struct binder_ptr_cookie, but they are using a 32bit handle and a pointer. On 32bit systems the payload size is the same as the size of struct binder_ptr_cookie, however for 64bit systems this will differ. This patch adds struct binder_handle_cookie that fixes this issue for 64bit Android. Since there are no 64bit users of this interface that we know of this change should not affect any existing systems. Change-Id: I8909cbc50aad48ccf371270bad6f69ff242a8c22 Signed-off-by: Serban Constantinescu --- drivers/staging/android/uapi/binder.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index e76cfa876daa..008722a249bc 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -152,6 +152,11 @@ struct binder_ptr_cookie { void *cookie; }; +struct binder_handle_cookie { + __u32 handle; + void *cookie; +} __attribute__((packed)); + struct binder_pri_desc { __s32 priority; __u32 desc; @@ -308,15 +313,15 @@ enum binder_driver_command_protocol { * of looping threads it has available. */ - BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie), + BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), /* - * void *: ptr to binder + * int: handle * void *: cookie */ - BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie), + BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), /* - * void *: ptr to binder + * int: handle * void *: cookie */ From 2d595dc92ae19b49e4c1ebb1f8e3b461a2d06592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Mon, 27 Jan 2014 19:18:47 -0800 Subject: [PATCH 086/147] Staging: android: binder: Support concurrent 32 bit and 64 bit processes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add binder_size_t and binder_uintptr_t that is used instead of size_t and void __user * in the user-space interface. Use 64 bit pointers on all systems unless CONFIG_ANDROID_BINDER_IPC_32BIT is set (which enables the old protocol on 32 bit systems). Change BINDER_CURRENT_PROTOCOL_VERSION to 8 if CONFIG_ANDROID_BINDER_IPC_32BIT is not set. Add compat ioctl. Change-Id: Ifbbde0209da0050011bcab34c547a4c30d6e8c49 Signed-off-by: Arve Hjønnevåg --- drivers/staging/android/Kconfig | 7 + drivers/staging/android/binder.c | 253 +++++++++++++------------ drivers/staging/android/binder.h | 4 + drivers/staging/android/binder_trace.h | 14 +- drivers/staging/android/uapi/binder.h | 60 +++--- 5 files changed, 191 insertions(+), 147 deletions(-) diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 6da535db2538..a14e0b428c28 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -19,6 +19,13 @@ config ANDROID_BINDER_IPC Android process, using Binder to identify, invoke and pass arguments between said processes. +config ANDROID_BINDER_IPC_32BIT + bool "Use old 32-bit binder api" + depends on !64BIT + ---help--- + Enable to support an old 32-bit Android user-space. Breaks the new + Android user-space. + config ASHMEM bool "Enable the Anonymous Shared Memory Subsystem" default n diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index b9a7d9347784..a1931c026230 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -229,8 +229,8 @@ struct binder_node { int internal_strong_refs; int local_weak_refs; int local_strong_refs; - void __user *ptr; - void __user *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; unsigned has_strong_ref:1; unsigned pending_strong_ref:1; unsigned has_weak_ref:1; @@ -243,7 +243,7 @@ struct binder_node { struct binder_ref_death { struct binder_work work; - void __user *cookie; + binder_uintptr_t cookie; }; struct binder_ref { @@ -516,14 +516,14 @@ static void binder_insert_allocated_buffer(struct binder_proc *proc, } static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc, - void __user *user_ptr) + uintptr_t user_ptr) { struct rb_node *n = proc->allocated_buffers.rb_node; struct binder_buffer *buffer; struct binder_buffer *kern_ptr; - kern_ptr = user_ptr - proc->user_buffer_offset - - offsetof(struct binder_buffer, data); + kern_ptr = (struct binder_buffer *)(user_ptr - proc->user_buffer_offset + - offsetof(struct binder_buffer, data)); while (n) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -857,7 +857,7 @@ static void binder_free_buf(struct binder_proc *proc, } static struct binder_node *binder_get_node(struct binder_proc *proc, - void __user *ptr) + binder_uintptr_t ptr) { struct rb_node *n = proc->nodes.rb_node; struct binder_node *node; @@ -876,8 +876,8 @@ static struct binder_node *binder_get_node(struct binder_proc *proc, } static struct binder_node *binder_new_node(struct binder_proc *proc, - void __user *ptr, - void __user *cookie) + binder_uintptr_t ptr, + binder_uintptr_t cookie) { struct rb_node **p = &proc->nodes.rb_node; struct rb_node *parent = NULL; @@ -909,9 +909,9 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p created\n", + "%d:%d node %d u%016llx c%016llx created\n", proc->pid, current->pid, node->debug_id, - node->ptr, node->cookie); + (u64)node->ptr, (u64)node->cookie); return node; } @@ -1227,9 +1227,9 @@ static void binder_send_failed_reply(struct binder_transaction *t, static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, - size_t *failed_at) + binder_size_t *failed_at) { - size_t *offp, *off_end; + binder_size_t *offp, *off_end; int debug_id = buffer->debug_id; binder_debug(BINDER_DEBUG_TRANSACTION, @@ -1240,7 +1240,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, if (buffer->target_node) binder_dec_node(buffer->target_node, 1, 0); - offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *))); + offp = (binder_size_t *)(buffer->data + + ALIGN(buffer->data_size, sizeof(void *))); if (failed_at) off_end = failed_at; else @@ -1250,8 +1251,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(u32))) { - pr_err("transaction release %d bad offset %zd, size %zd\n", - debug_id, *offp, buffer->data_size); + pr_err("transaction release %d bad offset %lld, size %zd\n", + debug_id, (u64)*offp, buffer->data_size); continue; } fp = (struct flat_binder_object *)(buffer->data + *offp); @@ -1260,13 +1261,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_BINDER: { struct binder_node *node = binder_get_node(proc, fp->binder); if (node == NULL) { - pr_err("transaction release %d bad node %p\n", - debug_id, fp->binder); + pr_err("transaction release %d bad node %016llx\n", + debug_id, (u64)fp->binder); break; } binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p\n", - node->debug_id, node->ptr); + " node %d u%016llx\n", + node->debug_id, (u64)node->ptr); binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0); } break; case BINDER_TYPE_HANDLE: @@ -1304,7 +1305,7 @@ static void binder_transaction(struct binder_proc *proc, { struct binder_transaction *t; struct binder_work *tcomplete; - size_t *offp, *off_end; + binder_size_t *offp, *off_end; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; @@ -1437,18 +1438,20 @@ static void binder_transaction(struct binder_proc *proc, if (reply) binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d BC_REPLY %d -> %d:%d, data %p-%p size %zd-%zd\n", + "%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_thread->pid, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); + (u64)tr->data.ptr.buffer, + (u64)tr->data.ptr.offsets, + (u64)tr->data_size, (u64)tr->offsets_size); else binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d BC_TRANSACTION %d -> %d - node %d, data %p-%p size %zd-%zd\n", + "%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld\n", proc->pid, thread->pid, t->debug_id, target_proc->pid, target_node->debug_id, - tr->data.ptr.buffer, tr->data.ptr.offsets, - tr->data_size, tr->offsets_size); + (u64)tr->data.ptr.buffer, + (u64)tr->data.ptr.offsets, + (u64)tr->data_size, (u64)tr->offsets_size); if (!reply && !(tr->flags & TF_ONE_WAY)) t->from = thread; @@ -1477,23 +1480,26 @@ static void binder_transaction(struct binder_proc *proc, if (target_node) binder_inc_node(target_node, 1, 0, NULL); - offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *))); + offp = (binder_size_t *)(t->buffer->data + + ALIGN(tr->data_size, sizeof(void *))); - if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) { + if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t) + tr->data.ptr.buffer, tr->data_size)) { binder_user_error("%d:%d got transaction with invalid data ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } - if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) { + if (copy_from_user(offp, (const void __user *)(uintptr_t) + tr->data.ptr.offsets, tr->offsets_size)) { binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; goto err_copy_data_failed; } - if (!IS_ALIGNED(tr->offsets_size, sizeof(size_t))) { - binder_user_error("%d:%d got transaction with invalid offsets size, %zd\n", - proc->pid, thread->pid, tr->offsets_size); + if (!IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))) { + binder_user_error("%d:%d got transaction with invalid offsets size, %lld\n", + proc->pid, thread->pid, (u64)tr->offsets_size); return_error = BR_FAILED_REPLY; goto err_bad_offset; } @@ -1503,8 +1509,8 @@ static void binder_transaction(struct binder_proc *proc, if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(u32))) { - binder_user_error("%d:%d got transaction with invalid offset, %zd\n", - proc->pid, thread->pid, *offp); + binder_user_error("%d:%d got transaction with invalid offset, %lld\n", + proc->pid, thread->pid, (u64)*offp); return_error = BR_FAILED_REPLY; goto err_bad_offset; } @@ -1524,10 +1530,10 @@ static void binder_transaction(struct binder_proc *proc, node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS); } if (fp->cookie != node->cookie) { - binder_user_error("%d:%d sending u%p node %d, cookie mismatch %p != %p\n", + binder_user_error("%d:%d sending u%016llx node %d, cookie mismatch %016llx != %016llx\n", proc->pid, thread->pid, - fp->binder, node->debug_id, - fp->cookie, node->cookie); + (u64)fp->binder, node->debug_id, + (u64)fp->cookie, (u64)node->cookie); goto err_binder_get_ref_for_node_failed; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { @@ -1549,9 +1555,9 @@ static void binder_transaction(struct binder_proc *proc, trace_binder_transaction_node_to_ref(t, node, ref); binder_debug(BINDER_DEBUG_TRANSACTION, - " node %d u%p -> ref %d desc %d\n", - node->debug_id, node->ptr, ref->debug_id, - ref->desc); + " node %d u%016llx -> ref %d desc %d\n", + node->debug_id, (u64)node->ptr, + ref->debug_id, ref->desc); } break; case BINDER_TYPE_HANDLE: case BINDER_TYPE_WEAK_HANDLE: { @@ -1577,9 +1583,9 @@ static void binder_transaction(struct binder_proc *proc, binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL); trace_binder_transaction_ref_to_node(t, ref); binder_debug(BINDER_DEBUG_TRANSACTION, - " ref %d desc %d -> node %d u%p\n", + " ref %d desc %d -> node %d u%016llx\n", ref->debug_id, ref->desc, ref->node->debug_id, - ref->node->ptr); + (u64)ref->node->ptr); } else { struct binder_ref *new_ref; new_ref = binder_get_ref_for_node(target_proc, ref->node); @@ -1700,9 +1706,9 @@ static void binder_transaction(struct binder_proc *proc, err_invalid_target_handle: err_no_context_mgr_node: binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, - "%d:%d transaction failed %d, size %zd-%zd\n", + "%d:%d transaction failed %d, size %lld-%lld\n", proc->pid, thread->pid, return_error, - tr->data_size, tr->offsets_size); + (u64)tr->data_size, (u64)tr->offsets_size); { struct binder_transaction_log_entry *fe; @@ -1719,9 +1725,11 @@ static void binder_transaction(struct binder_proc *proc, } int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, size_t size, size_t *consumed) + binder_uintptr_t binder_buffer, size_t size, + binder_size_t *consumed) { uint32_t cmd; + void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -1790,33 +1798,33 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } case BC_INCREFS_DONE: case BC_ACQUIRE_DONE: { - void __user *node_ptr; - void *cookie; + binder_uintptr_t node_ptr; + binder_uintptr_t cookie; struct binder_node *node; - if (get_user(node_ptr, (void * __user *)ptr)) + if (get_user(node_ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - if (get_user(cookie, (void * __user *)ptr)) + ptr += sizeof(binder_uintptr_t); + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(binder_uintptr_t); node = binder_get_node(proc, node_ptr); if (node == NULL) { - binder_user_error("%d:%d %s u%p no match\n", + binder_user_error("%d:%d %s u%016llx no match\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node_ptr); + (u64)node_ptr); break; } if (cookie != node->cookie) { - binder_user_error("%d:%d %s u%p node %d cookie mismatch %p != %p\n", + binder_user_error("%d:%d %s u%016llx node %d cookie mismatch %016llx != %016llx\n", proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", - node_ptr, node->debug_id, - cookie, node->cookie); + (u64)node_ptr, node->debug_id, + (u64)cookie, (u64)node->cookie); break; } if (cmd == BC_ACQUIRE_DONE) { @@ -1852,27 +1860,27 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, return -EINVAL; case BC_FREE_BUFFER: { - void __user *data_ptr; + binder_uintptr_t data_ptr; struct binder_buffer *buffer; - if (get_user(data_ptr, (void * __user *)ptr)) + if (get_user(data_ptr, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(binder_uintptr_t); buffer = binder_buffer_lookup(proc, data_ptr); if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p no match\n", - proc->pid, thread->pid, data_ptr); + binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, (u64)data_ptr); break; } if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%p matched unreturned buffer\n", - proc->pid, thread->pid, data_ptr); + binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", + proc->pid, thread->pid, (u64)data_ptr); break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, - "%d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n", - proc->pid, thread->pid, data_ptr, buffer->debug_id, + "%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n", + proc->pid, thread->pid, (u64)data_ptr, buffer->debug_id, buffer->transaction ? "active" : "finished"); if (buffer->transaction) { @@ -1942,16 +1950,16 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, case BC_REQUEST_DEATH_NOTIFICATION: case BC_CLEAR_DEATH_NOTIFICATION: { uint32_t target; - void __user *cookie; + binder_uintptr_t cookie; struct binder_ref *ref; struct binder_ref_death *death; if (get_user(target, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); - if (get_user(cookie, (void __user * __user *)ptr)) + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(binder_uintptr_t); ref = binder_get_ref(proc, target); if (ref == NULL) { binder_user_error("%d:%d %s invalid ref %d\n", @@ -1964,12 +1972,12 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "%d:%d %s %p ref %d desc %d s %d w %d for node %d\n", + "%d:%d %s %016llx ref %d desc %d s %d w %d for node %d\n", proc->pid, thread->pid, cmd == BC_REQUEST_DEATH_NOTIFICATION ? "BC_REQUEST_DEATH_NOTIFICATION" : "BC_CLEAR_DEATH_NOTIFICATION", - cookie, ref->debug_id, ref->desc, + (u64)cookie, ref->debug_id, ref->desc, ref->strong, ref->weak, ref->node->debug_id); if (cmd == BC_REQUEST_DEATH_NOTIFICATION) { @@ -2007,9 +2015,9 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } death = ref->death; if (death->cookie != cookie) { - binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %p != %p\n", + binder_user_error("%d:%d BC_CLEAR_DEATH_NOTIFICATION death notification cookie mismatch %016llx != %016llx\n", proc->pid, thread->pid, - death->cookie, cookie); + (u64)death->cookie, (u64)cookie); break; } ref->death = NULL; @@ -2029,9 +2037,9 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } break; case BC_DEAD_BINDER_DONE: { struct binder_work *w; - void __user *cookie; + binder_uintptr_t cookie; struct binder_ref_death *death = NULL; - if (get_user(cookie, (void __user * __user *)ptr)) + if (get_user(cookie, (binder_uintptr_t __user *)ptr)) return -EFAULT; ptr += sizeof(void *); @@ -2043,11 +2051,11 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, } } binder_debug(BINDER_DEBUG_DEAD_BINDER, - "%d:%d BC_DEAD_BINDER_DONE %p found %p\n", - proc->pid, thread->pid, cookie, death); + "%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", + proc->pid, thread->pid, (u64)cookie, death); if (death == NULL) { - binder_user_error("%d:%d BC_DEAD_BINDER_DONE %p not found\n", - proc->pid, thread->pid, cookie); + binder_user_error("%d:%d BC_DEAD_BINDER_DONE %016llx not found\n", + proc->pid, thread->pid, (u64)cookie); break; } @@ -2099,9 +2107,10 @@ static int binder_has_thread_work(struct binder_thread *thread) static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, size_t size, - size_t *consumed, int non_block) + binder_uintptr_t binder_buffer, size_t size, + binder_size_t *consumed, int non_block) { + void __user *buffer = (void __user *)(uintptr_t)binder_buffer; void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2246,32 +2255,36 @@ static int binder_thread_read(struct binder_proc *proc, if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); - if (put_user(node->ptr, (void * __user *)ptr)) + if (put_user(node->ptr, + (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); - if (put_user(node->cookie, (void * __user *)ptr)) + ptr += sizeof(binder_uintptr_t); + if (put_user(node->cookie, + (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(binder_uintptr_t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_USER_REFS, - "%d:%d %s %d u%p c%p\n", - proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie); + "%d:%d %s %d u%016llx c%016llx\n", + proc->pid, thread->pid, cmd_name, + node->debug_id, + (u64)node->ptr, (u64)node->cookie); } else { list_del_init(&w->entry); if (!weak && !strong) { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p deleted\n", + "%d:%d node %d u%016llx c%016llx deleted\n", proc->pid, thread->pid, node->debug_id, - node->ptr, node->cookie); + (u64)node->ptr, (u64)node->cookie); rb_erase(&node->rb_node, &proc->nodes); kfree(node); binder_stats_deleted(BINDER_STAT_NODE); } else { binder_debug(BINDER_DEBUG_INTERNAL_REFS, - "%d:%d node %d u%p c%p state unchanged\n", - proc->pid, thread->pid, node->debug_id, node->ptr, - node->cookie); + "%d:%d node %d u%016llx c%016llx state unchanged\n", + proc->pid, thread->pid, node->debug_id, + (u64)node->ptr, (u64)node->cookie); } } } break; @@ -2289,17 +2302,18 @@ static int binder_thread_read(struct binder_proc *proc, if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; ptr += sizeof(uint32_t); - if (put_user(death->cookie, (void * __user *)ptr)) + if (put_user(death->cookie, + (binder_uintptr_t __user *)ptr)) return -EFAULT; - ptr += sizeof(void *); + ptr += sizeof(binder_uintptr_t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION, - "%d:%d %s %p\n", + "%d:%d %s %016llx\n", proc->pid, thread->pid, cmd == BR_DEAD_BINDER ? "BR_DEAD_BINDER" : "BR_CLEAR_DEATH_NOTIFICATION_DONE", - death->cookie); + (u64)death->cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { list_del(&w->entry); @@ -2329,8 +2343,8 @@ static int binder_thread_read(struct binder_proc *proc, binder_set_nice(target_node->min_priority); cmd = BR_TRANSACTION; } else { - tr.target.ptr = NULL; - tr.cookie = NULL; + tr.target.ptr = 0; + tr.cookie = 0; cmd = BR_REPLY; } tr.code = t->code; @@ -2347,8 +2361,9 @@ static int binder_thread_read(struct binder_proc *proc, tr.data_size = t->buffer->data_size; tr.offsets_size = t->buffer->offsets_size; - tr.data.ptr.buffer = (void *)t->buffer->data + - proc->user_buffer_offset; + tr.data.ptr.buffer = (binder_uintptr_t)( + (uintptr_t)t->buffer->data + + proc->user_buffer_offset); tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *)); @@ -2363,14 +2378,14 @@ static int binder_thread_read(struct binder_proc *proc, trace_binder_transaction_received(t); binder_stat_br(proc, thread, cmd); binder_debug(BINDER_DEBUG_TRANSACTION, - "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %p-%p\n", + "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n", proc->pid, thread->pid, (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY", t->debug_id, t->from ? t->from->proc->pid : 0, t->from ? t->from->pid : 0, cmd, t->buffer->data_size, t->buffer->offsets_size, - tr.data.ptr.buffer, tr.data.ptr.offsets); + (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets); list_del(&t->work.entry); t->buffer->allow_user_free = 1; @@ -2440,8 +2455,8 @@ static void binder_release_work(struct list_head *list) death = container_of(w, struct binder_ref_death, work); binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, - "undelivered death notification, %p\n", - death->cookie); + "undelivered death notification, %016llx\n", + (u64)death->cookie); kfree(death); binder_stats_deleted(BINDER_STAT_DEATH); } break; @@ -2597,12 +2612,13 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %zd at %016lx, read %zd at %016lx\n", - proc->pid, thread->pid, bwr.write_size, - bwr.write_buffer, bwr.read_size, bwr.read_buffer); + "%d:%d write %lld at %016llx, read %lld at %016llx\n", + proc->pid, thread->pid, + (u64)bwr.write_size, (u64)bwr.write_buffer, + (u64)bwr.read_size, (u64)bwr.read_buffer); if (bwr.write_size > 0) { - ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); + ret = binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size, &bwr.write_consumed); trace_binder_write_done(ret); if (ret < 0) { bwr.read_consumed = 0; @@ -2612,7 +2628,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } if (bwr.read_size > 0) { - ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); + ret = binder_thread_read(proc, thread, bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); trace_binder_read_done(ret); if (!list_empty(&proc->todo)) wake_up_interruptible(&proc->wait); @@ -2623,9 +2639,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d wrote %zd of %zd, read return %zd of %zd\n", - proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, - bwr.read_consumed, bwr.read_size); + "%d:%d wrote %lld of %lld, read return %lld of %lld\n", + proc->pid, thread->pid, + (u64)bwr.write_consumed, (u64)bwr.write_size, + (u64)bwr.read_consumed, (u64)bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { ret = -EFAULT; goto err; @@ -2657,7 +2674,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } else binder_context_mgr_uid = current->cred->euid; - binder_context_mgr_node = binder_new_node(proc, NULL, NULL); + binder_context_mgr_node = binder_new_node(proc, 0, 0); if (binder_context_mgr_node == NULL) { ret = -ENOMEM; goto err; @@ -3153,8 +3170,9 @@ static void print_binder_work(struct seq_file *m, const char *prefix, break; case BINDER_WORK_NODE: node = container_of(w, struct binder_node, work); - seq_printf(m, "%snode work %d: u%p c%p\n", - prefix, node->debug_id, node->ptr, node->cookie); + seq_printf(m, "%snode work %d: u%016llx c%016llx\n", + prefix, node->debug_id, + (u64)node->ptr, (u64)node->cookie); break; case BINDER_WORK_DEAD_BINDER: seq_printf(m, "%shas dead binder\n", prefix); @@ -3214,8 +3232,8 @@ static void print_binder_node(struct seq_file *m, struct binder_node *node) hlist_for_each_entry(ref, &node->refs, node_entry) count++; - seq_printf(m, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d", - node->debug_id, node->ptr, node->cookie, + seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d", + node->debug_id, (u64)node->ptr, (u64)node->cookie, node->has_strong_ref, node->has_weak_ref, node->local_strong_refs, node->local_weak_refs, node->internal_strong_refs, count); @@ -3517,6 +3535,7 @@ static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, + .compat_ioctl = binder_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index d4101a671718..eb0834656dfe 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -20,6 +20,10 @@ #ifndef _LINUX_BINDER_H #define _LINUX_BINDER_H +#ifdef CONFIG_ANDROID_BINDER_IPC_32BIT +#define BINDER_IPC_32BIT 1 +#endif + #include "uapi/binder.h" #endif /* _LINUX_BINDER_H */ diff --git a/drivers/staging/android/binder_trace.h b/drivers/staging/android/binder_trace.h index 82a567c2af67..7f20f3dc8369 100644 --- a/drivers/staging/android/binder_trace.h +++ b/drivers/staging/android/binder_trace.h @@ -152,7 +152,7 @@ TRACE_EVENT(binder_transaction_node_to_ref, TP_STRUCT__entry( __field(int, debug_id) __field(int, node_debug_id) - __field(void __user *, node_ptr) + __field(binder_uintptr_t, node_ptr) __field(int, ref_debug_id) __field(uint32_t, ref_desc) ), @@ -163,8 +163,9 @@ TRACE_EVENT(binder_transaction_node_to_ref, __entry->ref_debug_id = ref->debug_id; __entry->ref_desc = ref->desc; ), - TP_printk("transaction=%d node=%d src_ptr=0x%p ==> dest_ref=%d dest_desc=%d", - __entry->debug_id, __entry->node_debug_id, __entry->node_ptr, + TP_printk("transaction=%d node=%d src_ptr=0x%016llx ==> dest_ref=%d dest_desc=%d", + __entry->debug_id, __entry->node_debug_id, + (u64)__entry->node_ptr, __entry->ref_debug_id, __entry->ref_desc) ); @@ -177,7 +178,7 @@ TRACE_EVENT(binder_transaction_ref_to_node, __field(int, ref_debug_id) __field(uint32_t, ref_desc) __field(int, node_debug_id) - __field(void __user *, node_ptr) + __field(binder_uintptr_t, node_ptr) ), TP_fast_assign( __entry->debug_id = t->debug_id; @@ -186,9 +187,10 @@ TRACE_EVENT(binder_transaction_ref_to_node, __entry->node_debug_id = ref->node->debug_id; __entry->node_ptr = ref->node->ptr; ), - TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%p", + TP_printk("transaction=%d node=%d src_ref=%d src_desc=%d ==> dest_ptr=0x%016llx", __entry->debug_id, __entry->node_debug_id, - __entry->ref_debug_id, __entry->ref_desc, __entry->node_ptr) + __entry->ref_debug_id, __entry->ref_desc, + (u64)__entry->node_ptr) ); TRACE_EVENT(binder_transaction_ref_to_ref, diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h index 008722a249bc..4098c502fc36 100644 --- a/drivers/staging/android/uapi/binder.h +++ b/drivers/staging/android/uapi/binder.h @@ -39,6 +39,14 @@ enum { FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, }; +#ifdef BINDER_IPC_32BIT +typedef __u32 binder_size_t; +typedef __u32 binder_uintptr_t; +#else +typedef __u64 binder_size_t; +typedef __u64 binder_uintptr_t; +#endif + /* * This is the flattened representation of a Binder object for transfer * between processes. The 'offsets' supplied as part of a binder transaction @@ -53,12 +61,12 @@ struct flat_binder_object { /* 8 bytes of data. */ union { - void __user *binder; /* local object */ - __u32 handle; /* remote object */ + binder_uintptr_t binder; /* local object */ + __u32 handle; /* remote object */ }; /* extra data associated with local object */ - void __user *cookie; + binder_uintptr_t cookie; }; /* @@ -67,12 +75,12 @@ struct flat_binder_object { */ struct binder_write_read { - size_t write_size; /* bytes to write */ - size_t write_consumed; /* bytes consumed by driver */ - unsigned long write_buffer; - size_t read_size; /* bytes to read */ - size_t read_consumed; /* bytes consumed by driver */ - unsigned long read_buffer; + binder_size_t write_size; /* bytes to write */ + binder_size_t write_consumed; /* bytes consumed by driver */ + binder_uintptr_t write_buffer; + binder_size_t read_size; /* bytes to read */ + binder_size_t read_consumed; /* bytes consumed by driver */ + binder_uintptr_t read_buffer; }; /* Use with BINDER_VERSION, driver fills in fields. */ @@ -82,7 +90,11 @@ struct binder_version { }; /* This is the current protocol version. */ +#ifdef BINDER_IPC_32BIT #define BINDER_CURRENT_PROTOCOL_VERSION 7 +#else +#define BINDER_CURRENT_PROTOCOL_VERSION 8 +#endif #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) @@ -120,17 +132,17 @@ struct binder_transaction_data { */ union { __u32 handle; /* target descriptor of command transaction */ - void *ptr; /* target descriptor of return transaction */ + binder_uintptr_t ptr; /* target descriptor of return transaction */ } target; - void *cookie; /* target object cookie */ + binder_uintptr_t cookie; /* target object cookie */ __u32 code; /* transaction command */ /* General information about the transaction. */ __u32 flags; pid_t sender_pid; uid_t sender_euid; - size_t data_size; /* number of bytes of data */ - size_t offsets_size; /* number of bytes of offsets */ + binder_size_t data_size; /* number of bytes of data */ + binder_size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to @@ -139,22 +151,22 @@ struct binder_transaction_data { union { struct { /* transaction data */ - const void __user *buffer; + binder_uintptr_t buffer; /* offsets from buffer to flat_binder_object structs */ - const void __user *offsets; + binder_uintptr_t offsets; } ptr; __u8 buf[8]; } data; }; struct binder_ptr_cookie { - void *ptr; - void *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; }; struct binder_handle_cookie { __u32 handle; - void *cookie; + binder_uintptr_t cookie; } __attribute__((packed)); struct binder_pri_desc { @@ -164,8 +176,8 @@ struct binder_pri_desc { struct binder_pri_ptr_cookie { __s32 priority; - void *ptr; - void *cookie; + binder_uintptr_t ptr; + binder_uintptr_t cookie; }; enum binder_driver_return_protocol { @@ -240,11 +252,11 @@ enum binder_driver_return_protocol { * stop threadpool thread */ - BR_DEAD_BINDER = _IOR('r', 15, void *), + BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), /* * void *: cookie */ - BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *), + BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), /* * void *: cookie */ @@ -270,7 +282,7 @@ enum binder_driver_command_protocol { * Else you have acquired a primary reference on the object. */ - BC_FREE_BUFFER = _IOW('c', 3, void *), + BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), /* * void *: ptr to transaction data received on a read */ @@ -325,7 +337,7 @@ enum binder_driver_command_protocol { * void *: cookie */ - BC_DEAD_BINDER_DONE = _IOW('c', 16, void *), + BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), /* * void *: cookie */ From 5da20bcd490fe65d51f0b04fb0f88f09babf8fdf Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 9 Jan 2014 21:46:34 -0500 Subject: [PATCH 087/147] SELinux: Fix possible NULL pointer dereference in selinux_inode_permission() commit 3dc91d4338d698ce77832985f9cb183d8eeaf6be upstream. While running stress tests on adding and deleting ftrace instances I hit this bug: BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 IP: selinux_inode_permission+0x85/0x160 PGD 63681067 PUD 7ddbe067 PMD 0 Oops: 0000 [#1] PREEMPT CPU: 0 PID: 5634 Comm: ftrace-test-mki Not tainted 3.13.0-rc4-test-00033-gd2a6dde-dirty #20 Hardware name: /DG965MQ, BIOS MQ96510J.86A.0372.2006.0605.1717 06/05/2006 task: ffff880078375800 ti: ffff88007ddb0000 task.ti: ffff88007ddb0000 RIP: 0010:[] [] selinux_inode_permission+0x85/0x160 RSP: 0018:ffff88007ddb1c48 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000800000 RCX: ffff88006dd43840 RDX: 0000000000000001 RSI: 0000000000000081 RDI: ffff88006ee46000 RBP: ffff88007ddb1c88 R08: 0000000000000000 R09: ffff88007ddb1c54 R10: 6e6576652f6f6f66 R11: 0000000000000003 R12: 0000000000000000 R13: 0000000000000081 R14: ffff88006ee46000 R15: 0000000000000000 FS: 00007f217b5b6700(0000) GS:ffffffff81e21000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033^M CR2: 0000000000000020 CR3: 000000006a0fe000 CR4: 00000000000007f0 Call Trace: security_inode_permission+0x1c/0x30 __inode_permission+0x41/0xa0 inode_permission+0x18/0x50 link_path_walk+0x66/0x920 path_openat+0xa6/0x6c0 do_filp_open+0x43/0xa0 do_sys_open+0x146/0x240 SyS_open+0x1e/0x20 system_call_fastpath+0x16/0x1b Code: 84 a1 00 00 00 81 e3 00 20 00 00 89 d8 83 c8 02 40 f6 c6 04 0f 45 d8 40 f6 c6 08 74 71 80 cf 02 49 8b 46 38 4c 8d 4d cc 45 31 c0 <0f> b7 50 20 8b 70 1c 48 8b 41 70 89 d9 8b 78 04 e8 36 cf ff ff RIP selinux_inode_permission+0x85/0x160 CR2: 0000000000000020 Investigating, I found that the inode->i_security was NULL, and the dereference of it caused the oops. in selinux_inode_permission(): isec = inode->i_security; rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); Note, the crash came from stressing the deletion and reading of debugfs files. I was not able to recreate this via normal files. But I'm not sure they are safe. It may just be that the race window is much harder to hit. What seems to have happened (and what I have traced), is the file is being opened at the same time the file or directory is being deleted. As the dentry and inode locks are not held during the path walk, nor is the inodes ref counts being incremented, there is nothing saving these structures from being discarded except for an rcu_read_lock(). The rcu_read_lock() protects against freeing of the inode, but it does not protect freeing of the inode_security_struct. Now if the freeing of the i_security happens with a call_rcu(), and the i_security field of the inode is not changed (it gets freed as the inode gets freed) then there will be no issue here. (Linus Torvalds suggested not setting the field to NULL such that we do not need to check if it is NULL in the permission check). Note, this is a hack, but it fixes the problem at hand. A real fix is to restructure the destroy_inode() to call all the destructor handlers from the RCU callback. But that is a major job to do, and requires a lot of work. For now, we just band-aid this bug with this fix (it works), and work on a more maintainable solution in the future. Link: http://lkml.kernel.org/r/20140109101932.0508dec7@gandalf.local.home Link: http://lkml.kernel.org/r/20140109182756.17abaaa8@gandalf.local.home Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- security/selinux/hooks.c | 20 ++++++++++++++++++-- security/selinux/include/objsec.h | 5 ++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 61ee72d35fd5..11918d7ddb6e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -218,6 +218,14 @@ static int inode_alloc_security(struct inode *inode) return 0; } +static void inode_free_rcu(struct rcu_head *head) +{ + struct inode_security_struct *isec; + + isec = container_of(head, struct inode_security_struct, rcu); + kmem_cache_free(sel_inode_cache, isec); +} + static void inode_free_security(struct inode *inode) { struct inode_security_struct *isec = inode->i_security; @@ -228,8 +236,16 @@ static void inode_free_security(struct inode *inode) list_del_init(&isec->list); spin_unlock(&sbsec->isec_lock); - inode->i_security = NULL; - kmem_cache_free(sel_inode_cache, isec); + /* + * The inode may still be referenced in a path walk and + * a call to selinux_inode_permission() can be made + * after inode_free_security() is called. Ideally, the VFS + * wouldn't do this, but fixing that is a much harder + * job. For now, simply free the i_security via RCU, and + * leave the current inode->i_security pointer intact. + * The inode will be freed after the RCU grace period too. + */ + call_rcu(&isec->rcu, inode_free_rcu); } static int file_alloc_security(struct file *file) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index aa47bcabb5f6..6fd9dd256a62 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -38,7 +38,10 @@ struct task_security_struct { struct inode_security_struct { struct inode *inode; /* back pointer to inode object */ - struct list_head list; /* list of inode_security_struct */ + union { + struct list_head list; /* list of inode_security_struct */ + struct rcu_head rcu; /* for freeing the inode_security_struct */ + }; u32 task_sid; /* SID of creating task */ u32 sid; /* SID of this object */ u16 sclass; /* security class of this object */ From 537057b66d4ef6fe1cc27939442a6e9a8d8104b9 Mon Sep 17 00:00:00 2001 From: Ashish Sharma Date: Wed, 5 Feb 2014 01:50:50 +0000 Subject: [PATCH 088/147] netfilter: xt_IDLETIMER: Revert to retain the kernel API format. Reverted Change-Id: Iaeca5dd2d7878c0733923ae03309a2a7b86979ca Change-Id: I0e0a4f60ec14330d8d8d1c5a508fa058d9919e07 Signed-off-by: Ashish Sharma (cherry picked from commit e0a4e5b0e808d718dd9af500c5754118fc3935db) --- net/netfilter/xt_IDLETIMER.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c index f4ba86348660..df91e26f55f2 100644 --- a/net/netfilter/xt_IDLETIMER.c +++ b/net/netfilter/xt_IDLETIMER.c @@ -68,15 +68,15 @@ static DEFINE_MUTEX(list_mutex); static struct kobject *idletimer_tg_kobj; -static void notify_netlink_uevent(const char *label, struct idletimer_tg *timer) +static void notify_netlink_uevent(const char *iface, struct idletimer_tg *timer) { - char label_msg[NLMSG_MAX_SIZE]; + char iface_msg[NLMSG_MAX_SIZE]; char state_msg[NLMSG_MAX_SIZE]; - char *envp[] = { label_msg, state_msg, NULL }; + char *envp[] = { iface_msg, state_msg, NULL }; int res; - res = snprintf(label_msg, NLMSG_MAX_SIZE, "LABEL=%s", - label); + res = snprintf(iface_msg, NLMSG_MAX_SIZE, "INTERFACE=%s", + iface); if (NLMSG_MAX_SIZE <= res) { pr_err("message too long (%d)", res); return; @@ -87,7 +87,7 @@ static void notify_netlink_uevent(const char *label, struct idletimer_tg *timer) pr_err("message too long (%d)", res); return; } - pr_debug("putting nlmsg: <%s> <%s>\n", label_msg, state_msg); + pr_debug("putting nlmsg: <%s> <%s>\n", iface_msg, state_msg); kobject_uevent_env(idletimer_tg_kobj, KOBJ_CHANGE, envp); return; From 8179b7b7fe7e0ee85f670d109de6d7e3be46b2a9 Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Wed, 5 Feb 2014 12:29:34 -0800 Subject: [PATCH 089/147] ARM: tegra: flounder: stick to 32bit binder for now. Signed-off-by: JP Abgrall --- drivers/staging/android/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index a14e0b428c28..a802bc0bf4a4 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -21,6 +21,7 @@ config ANDROID_BINDER_IPC config ANDROID_BINDER_IPC_32BIT bool "Use old 32-bit binder api" + default y depends on !64BIT ---help--- Enable to support an old 32-bit Android user-space. Breaks the new From 43fcab022e7eef42e0bbcc7b955e8de2ef1469a4 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 30 Jan 2014 11:26:59 -0500 Subject: [PATCH 090/147] SELinux: Fix kernel BUG on empty security contexts. Setting an empty security context (length=0) on a file will lead to incorrectly dereferencing the type and other fields of the security context structure, yielding a kernel BUG. As a zero-length security context is never valid, just reject all such security contexts whether coming from userspace via setxattr or coming from the filesystem upon a getxattr request by SELinux. Setting a security context value (empty or otherwise) unknown to SELinux in the first place is only possible for a root process (CAP_MAC_ADMIN), and, if running SELinux in enforcing mode, only if the corresponding SELinux mac_admin permission is also granted to the domain by policy. In Fedora policies, this is only allowed for specific domains such as livecd for setting down security contexts that are not defined in the build host policy. [On Android, this can only be set by root/CAP_MAC_ADMIN processes, and if running SELinux in enforcing mode, only if mac_admin permission is granted in policy. In Android 4.4, this would only be allowed for root/CAP_MAC_ADMIN processes that are also in unconfined domains. In current AOSP master, mac_admin is not allowed for any domains except the recovery console which has a legitimate need for it. The other potential vector is mounting a maliciously crafted filesystem for which SELinux fetches xattrs (e.g. an ext4 filesystem on a SDcard). However, the end result is only a local denial-of-service (DOS) due to kernel BUG. This fix is queued for 3.14.] Reproducer: su setenforce 0 touch foo setfattr -n security.selinux foo Caveat: Relabeling or removing foo after doing the above may not be possible without booting with SELinux disabled. Any subsequent access to foo after doing the above will also trigger the BUG. BUG output from Matthew Thode: [ 473.893141] ------------[ cut here ]------------ [ 473.962110] kernel BUG at security/selinux/ss/services.c:654! [ 473.995314] invalid opcode: 0000 [#6] SMP [ 474.027196] Modules linked in: [ 474.058118] CPU: 0 PID: 8138 Comm: ls Tainted: G D I 3.13.0-grsec #1 [ 474.116637] Hardware name: Supermicro X8ST3/X8ST3, BIOS 2.0 07/29/10 [ 474.149768] task: ffff8805f50cd010 ti: ffff8805f50cd488 task.ti: ffff8805f50cd488 [ 474.183707] RIP: 0010:[] [] context_struct_compute_av+0xce/0x308 [ 474.219954] RSP: 0018:ffff8805c0ac3c38 EFLAGS: 00010246 [ 474.252253] RAX: 0000000000000000 RBX: ffff8805c0ac3d94 RCX: 0000000000000100 [ 474.287018] RDX: ffff8805e8aac000 RSI: 00000000ffffffff RDI: ffff8805e8aaa000 [ 474.321199] RBP: ffff8805c0ac3cb8 R08: 0000000000000010 R09: 0000000000000006 [ 474.357446] R10: 0000000000000000 R11: ffff8805c567a000 R12: 0000000000000006 [ 474.419191] R13: ffff8805c2b74e88 R14: 00000000000001da R15: 0000000000000000 [ 474.453816] FS: 00007f2e75220800(0000) GS:ffff88061fc00000(0000) knlGS:0000000000000000 [ 474.489254] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 474.522215] CR2: 00007f2e74716090 CR3: 00000005c085e000 CR4: 00000000000207f0 [ 474.556058] Stack: [ 474.584325] ffff8805c0ac3c98 ffffffff811b549b ffff8805c0ac3c98 ffff8805f1190a40 [ 474.618913] ffff8805a6202f08 ffff8805c2b74e88 00068800d0464990 ffff8805e8aac860 [ 474.653955] ffff8805c0ac3cb8 000700068113833a ffff880606c75060 ffff8805c0ac3d94 [ 474.690461] Call Trace: [ 474.723779] [] ? lookup_fast+0x1cd/0x22a [ 474.778049] [] security_compute_av+0xf4/0x20b [ 474.811398] [] avc_compute_av+0x2a/0x179 [ 474.843813] [] avc_has_perm+0x45/0xf4 [ 474.875694] [] inode_has_perm+0x2a/0x31 [ 474.907370] [] selinux_inode_getattr+0x3c/0x3e [ 474.938726] [] security_inode_getattr+0x1b/0x22 [ 474.970036] [] vfs_getattr+0x19/0x2d [ 475.000618] [] vfs_fstatat+0x54/0x91 [ 475.030402] [] vfs_lstat+0x19/0x1b [ 475.061097] [] SyS_newlstat+0x15/0x30 [ 475.094595] [] ? __audit_syscall_entry+0xa1/0xc3 [ 475.148405] [] system_call_fastpath+0x16/0x1b [ 475.179201] Code: 00 48 85 c0 48 89 45 b8 75 02 0f 0b 48 8b 45 a0 48 8b 3d 45 d0 b6 00 8b 40 08 89 c6 ff ce e8 d1 b0 06 00 48 85 c0 49 89 c7 75 02 <0f> 0b 48 8b 45 b8 4c 8b 28 eb 1e 49 8d 7d 08 be 80 01 00 00 e8 [ 475.255884] RIP [] context_struct_compute_av+0xce/0x308 [ 475.296120] RSP [ 475.328734] ---[ end trace f076482e9d754adc ]--- [sds: commit message edited to note Android implications and to generate a unique Change-Id for gerrit] Change-Id: I4d5389f0cfa72b5f59dada45081fa47e03805413 Reported-by: Matthew Thode Signed-off-by: Stephen Smalley Cc: stable@vger.kernel.org Signed-off-by: Paul Moore --- security/selinux/ss/services.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b4feecc3fe01..18caa16de27b 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1231,6 +1231,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, struct context context; int rc = 0; + /* An empty security context is never valid. */ + if (!scontext_len) + return -EINVAL; + if (!ss_initialized) { int i; From 969ff3bbb38b6622800a1a4bd38404e3701193de Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Fri, 7 Feb 2014 18:40:10 -0800 Subject: [PATCH 091/147] tcp: add a sysctl to config the tcp_default_init_rwnd The default initial rwnd is hardcoded to 10. Now we allow it to be controlled via /proc/sys/net/ipv4/tcp_default_init_rwnd which limits the values from 3 to 100 This is somewhat needed because ipv6 routes are autoconfigured by the kernel. See "An Argument for Increasing TCP's Initial Congestion Window" in https://developers.google.com/speed/articles/tcp_initcwnd_paper.pdf Change-Id: I386b2a9d62de0ebe05c1ebe1b4bd91b314af5c54 Signed-off-by: JP Abgrall Conflicts: net/ipv4/sysctl_net_ipv4.c net/ipv4/tcp_input.c --- include/net/tcp.h | 1 + net/ipv4/sysctl_net_ipv4.c | 24 +++++++++++++++++++++++- net/ipv4/tcp_input.c | 5 +++-- net/ipv4/tcp_output.c | 7 +++---- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 1ed71a993d65..cfb55e14b25b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -287,6 +287,7 @@ extern int sysctl_tcp_thin_dupack; extern int sysctl_tcp_early_retrans; extern int sysctl_tcp_limit_output_bytes; extern int sysctl_tcp_challenge_ack_limit; +extern int sysctl_tcp_default_init_rwnd; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fa2f63fc453b..f9bb5d7488e0 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -135,6 +135,21 @@ static int ipv4_ping_group_range(ctl_table *table, int write, return ret; } +/* Validate changes from /proc interface. */ +static int proc_tcp_default_init_rwnd(ctl_table *ctl, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + int old_value = *(int *)ctl->data; + int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + int new_value = *(int *)ctl->data; + + if (write && ret == 0 && (new_value < 3 || new_value > 100)) + *(int *)ctl->data = old_value; + + return ret; +} + static int proc_tcp_congestion_control(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -732,7 +747,7 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { + { .procname = "tcp_thin_dupack", .data = &sysctl_tcp_thin_dupack, .maxlen = sizeof(int), @@ -748,6 +763,13 @@ static struct ctl_table ipv4_table[] = { .extra1 = &zero, .extra2 = &four, }, + { + .procname = "tcp_default_init_rwnd", + .data = &sysctl_tcp_default_init_rwnd, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_tcp_default_init_rwnd + }, { .procname = "udp_mem", .data = &sysctl_udp_mem, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9c6225780bd5..4189682d9ade 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -98,6 +98,7 @@ int sysctl_tcp_thin_dupack __read_mostly; int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; int sysctl_tcp_early_retrans __read_mostly = 3; +int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND; #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ @@ -351,14 +352,14 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb) static void tcp_fixup_rcvbuf(struct sock *sk) { u32 mss = tcp_sk(sk)->advmss; - u32 icwnd = TCP_DEFAULT_INIT_RCVWND; + u32 icwnd = sysctl_tcp_default_init_rwnd; int rcvmem; /* Limit to 10 segments if mss <= 1460, * or 14600/mss segments, with a minimum of two segments. */ if (mss > 1460) - icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); + icwnd = max_t(u32, (1460 * icwnd) / mss, 2); rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER); while (tcp_win_from_space(rcvmem) < mss) diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index ec335fabd5cc..084eac6a43b9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -231,14 +231,13 @@ void tcp_select_initial_window(int __space, __u32 mss, } /* Set initial window to a value enough for senders starting with - * initial congestion window of TCP_DEFAULT_INIT_RCVWND. Place + * initial congestion window of sysctl_tcp_default_init_rwnd. Place * a limit on the initial window when mss is larger than 1460. */ if (mss > (1 << *rcv_wscale)) { - int init_cwnd = TCP_DEFAULT_INIT_RCVWND; + int init_cwnd = sysctl_tcp_default_init_rwnd; if (mss > 1460) - init_cwnd = - max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); + init_cwnd = max_t(u32, (1460 * init_cwnd) / mss, 2); /* when initializing use the value from init_rcv_wnd * rather than the default from above */ From 9dac10e5b1f2a360e8b0fbbd785fd912dbd0b753 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 16 May 2013 05:09:56 +0000 Subject: [PATCH 092/147] cpufreq: Add EXPORT_SYMBOL_GPL for have_governor_per_policy This patch adds: EXPORT_SYMBOL_GPL(have_governor_per_policy), so that this routine can be used by modules too. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2d53f47d1747..2f254691ed1f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -132,6 +132,7 @@ bool have_governor_per_policy(void) { return cpufreq_driver->have_governor_per_policy; } +EXPORT_SYMBOL_GPL(have_governor_per_policy); static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { From 336eb742942e368ba93207eef48d6308a49220a4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 16 May 2013 05:09:57 +0000 Subject: [PATCH 093/147] cpufreq: governors: Move get_governor_parent_kobj() to cpufreq.c get_governor_parent_kobj() can be used by any governor, generic cpufreq governors or platform specific ones and so must be present in cpufreq.c instead of cpufreq_governor.c. This patch moves it to cpufreq.c. This also adds EXPORT_SYMBOL_GPL(get_governor_parent_kobj) so that modules can use this function too. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 9 +++++++++ drivers/cpufreq/cpufreq_governor.c | 8 -------- include/linux/cpufreq.h | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2f254691ed1f..3faf62bdbad0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -134,6 +134,15 @@ bool have_governor_per_policy(void) } EXPORT_SYMBOL_GPL(have_governor_per_policy); +struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) +{ + if (have_governor_per_policy()) + return &policy->kobj; + else + return cpufreq_global_kobject; +} +EXPORT_SYMBOL_GPL(get_governor_parent_kobj); + static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { struct cpufreq_policy *data; diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index dc9b72e25c1a..bf03b3001741 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -30,14 +30,6 @@ #include "cpufreq_governor.h" -static struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy) -{ - if (have_governor_per_policy()) - return &policy->kobj; - else - return cpufreq_global_kobject; -} - static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data) { if (have_governor_per_policy()) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index a6dc4013b0c7..400509e3a2c0 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -340,6 +340,7 @@ const char *cpufreq_get_current_driver(void); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); int cpufreq_update_policy(unsigned int cpu); bool have_governor_per_policy(void); +struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); #ifdef CONFIG_CPU_FREQ /* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */ From 0d7892920bf7061cca287e0d7b5a23e344d5adfb Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Thu, 27 Jun 2013 22:02:12 +0200 Subject: [PATCH 094/147] cpufreq: don't leave stale policy pointer in cdbs->cur_policy Clear ->cur_policy when stopping a governor, or the ->cur_policy pointer may be stale on systems with have_governor_per_policy when a new policy is allocated due to CPU hotplug offline/online. [rjw: Changelog] Suggested-by: Viresh Kumar Signed-off-by: Jacob Shin Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index bf03b3001741..1361bd432691 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -396,6 +396,7 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_data->mutex); mutex_destroy(&cpu_cdbs->timer_mutex); + cpu_cdbs->cur_policy = NULL; mutex_unlock(&dbs_data->mutex); From 6427820a87d082d8c35efedb0363bd3bf5469653 Mon Sep 17 00:00:00 2001 From: keunyoung Date: Wed, 29 Jan 2014 12:41:50 -0800 Subject: [PATCH 095/147] fix false disconnect due to a signal sent to the reading process - In the current implementation, when a signal is sent to the reading process, read is cancelled by calling usb_ep_dequeue, which lead into calling acc_complete_out with ECONNRESET, but the current logic treats it as disconnection, which makes the device inaccessible until cable is actually disconnected. - The fix calls disconnect only when ESHUTDOWN error is passed. - If data has already arrived while trying cancelling, the data is marked as available, and it will be read out on the next read. This is necessary as USB bulk is assumed to guarantee no data loss. Signed-off-by: keunyoung --- drivers/usb/gadget/f_accessory.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index 092964c2b506..f643146acb22 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -261,8 +261,10 @@ static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) { struct acc_dev *dev = _acc_dev; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_in set disconnected"); acc_set_disconnected(dev); + } req_put(dev, &dev->tx_idle, req); @@ -274,8 +276,10 @@ static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) struct acc_dev *dev = _acc_dev; dev->rx_done = 1; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_out set disconnected"); acc_set_disconnected(dev); + } wake_up(&dev->read_wq); } @@ -557,8 +561,10 @@ static ssize_t acc_read(struct file *fp, char __user *buf, pr_debug("acc_read(%d)\n", count); - if (dev->disconnected) + if (dev->disconnected) { + pr_debug("acc_read disconnected"); return -ENODEV; + } if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; @@ -571,6 +577,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + if (dev->rx_done) { + // last req cancelled. try to get it. + req = dev->rx_req[0]; + goto copy_data; + } + requeue_req: /* queue a request */ req = dev->rx_req[0]; @@ -588,9 +600,17 @@ static ssize_t acc_read(struct file *fp, char __user *buf, ret = wait_event_interruptible(dev->read_wq, dev->rx_done); if (ret < 0) { r = ret; - usb_ep_dequeue(dev->ep_out, req); + ret = usb_ep_dequeue(dev->ep_out, req); + if (ret != 0) { + // cancel failed. There can be a data already received. + // it will be retrieved in the next read. + pr_debug("acc_read: cancelling failed %d", ret); + } goto done; } + +copy_data: + dev->rx_done = 0; if (dev->online) { /* If we got a 0-len packet, throw it back and try again. */ if (req->actual == 0) @@ -619,8 +639,10 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, pr_debug("acc_write(%d)\n", count); - if (!dev->online || dev->disconnected) + if (!dev->online || dev->disconnected) { + pr_debug("acc_write disconnected or not online"); return -ENODEV; + } while (count > 0) { if (!dev->online) { From fd3a17735623a882bc6afd590e9c9bfb0e770f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Fri, 7 Feb 2014 17:46:21 -0800 Subject: [PATCH 096/147] Staging: android: binder: Fix death notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The change (008fa749e0fe5b2fffd20b7fe4891bb80d072c6a) that moved the node release code to a separate function broke death notifications in some cases. When it encountered a reference without a death notification request, it would skip looking at the remaining references, and therefore fail to send death notifications for them. Change-Id: I12083a50709ccc30ba11a5f4d9eeb5f0ff4471c6 Signed-off-by: Arve Hjønnevåg --- drivers/staging/android/binder.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index a1931c026230..6aec8509d7b0 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2941,7 +2941,7 @@ static int binder_node_release(struct binder_node *node, int refs) refs++; if (!ref->death) - goto out; + continue; death++; @@ -2954,7 +2954,6 @@ static int binder_node_release(struct binder_node *node, int refs) BUG(); } -out: binder_debug(BINDER_DEBUG_DEAD_BINDER, "node %d now dead, refs %d, death %d\n", node->debug_id, refs, death); From 4a475b3c6bef0d5f34e2a16ac77237b4be39f768 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Fri, 14 Feb 2014 15:39:52 -0800 Subject: [PATCH 097/147] video: adf: use ADF_IOCTL_TYPE in compat ioctl definitions Change-Id: I7451a282d9d972c9957568b366c164b67b4b47e8 Signed-off-by: Greg Hackmann --- drivers/video/adf/adf_fops32.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/adf/adf_fops32.h b/drivers/video/adf/adf_fops32.h index 18c673dc5e2e..53d43f010208 100644 --- a/drivers/video/adf/adf_fops32.h +++ b/drivers/video/adf/adf_fops32.h @@ -7,13 +7,13 @@ #include