summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-02-18 16:20:42 +0530
committerDeepak Nibade <dnibade@nvidia.com>2014-03-10 20:03:21 +0530
commit243d4c9490e60a84e3812cad8786f23da374adac (patch)
treedabe9e60a091b766e6f8b59b1479453999e39098
parent635837f825386fe490d57c471442c1dcf2d8bdc0 (diff)
parent43356cafc2d7d49408c8587039660bbcbc521f01 (diff)
Merge branch 'android-3.10' into dev-kernel-3.10
Bug 1456092 Change-Id: I87b6b883c382000fc0dfee7c8d8f36269f504e46 Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
-rw-r--r--Documentation/arm64/tagged-pointers.txt34
-rw-r--r--android/configs/android-base.cfg3
-rw-r--r--android/configs/android-recommended.cfg4
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h1
-rw-r--r--arch/arm64/kernel/entry.S1
-rw-r--r--arch/arm64/mach-tegra/BoardConfig.mk1
-rw-r--r--arch/arm64/mm/proc.S2
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c42
-rw-r--r--drivers/staging/android/Kconfig8
-rw-r--r--drivers/staging/android/binder.c374
-rw-r--r--drivers/staging/android/binder.h4
-rw-r--r--drivers/staging/android/binder_trace.h14
-rw-r--r--drivers/staging/android/ion/compat_ion.c26
-rw-r--r--drivers/staging/android/uapi/binder.h107
-rw-r--r--drivers/usb/gadget/f_accessory.c32
-rw-r--r--drivers/video/adf/adf_client.c7
-rw-r--r--drivers/video/adf/adf_fops32.c4
-rw-r--r--drivers/video/adf/adf_fops32.h8
-rw-r--r--include/net/ip.h2
-rw-r--r--include/net/ipv6.h4
-rw-r--r--include/net/ping.h3
-rw-r--r--include/net/tcp.h1
-rw-r--r--include/uapi/video/adf.h32
-rw-r--r--net/ipv4/icmp.c5
-rw-r--r--net/ipv4/ip_sockglue.c3
-rw-r--r--net/ipv4/ping.c46
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/sysctl_net_ipv4.c24
-rw-r--r--net/ipv4/tcp_input.c5
-rw-r--r--net/ipv4/tcp_output.c7
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/icmp.c9
-rw-r--r--net/netfilter/xt_IDLETIMER.c12
-rw-r--r--security/selinux/hooks.c20
-rw-r--r--security/selinux/include/objsec.h5
-rw-r--r--security/selinux/ss/services.c4
36 files changed, 518 insertions, 340 deletions
diff --git a/Documentation/arm64/tagged-pointers.txt b/Documentation/arm64/tagged-pointers.txt
new file mode 100644
index 000000000000..d9995f1f51b3
--- /dev/null
+++ b/Documentation/arm64/tagged-pointers.txt
@@ -0,0 +1,34 @@
+ Tagged virtual addresses in AArch64 Linux
+ =========================================
+
+Author: Will Deacon <will.deacon@arm.com>
+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) 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
+ 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.
diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg
index a9597658ef14..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
@@ -35,6 +34,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
@@ -82,6 +82,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
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
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 6ad781b21c08..93f96098ae41 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/mach-tegra/BoardConfig.mk b/arch/arm64/mach-tegra/BoardConfig.mk
new file mode 100644
index 000000000000..689e9db5c11d
--- /dev/null
+++ b/arch/arm64/mach-tegra/BoardConfig.mk
@@ -0,0 +1 @@
+TARGET_USES_64_BIT_BINDER := true
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index bf6044009699..50d25096f185 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -215,7 +215,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
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index d7adb0f421eb..b4c21feea256 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -741,7 +741,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;
}
@@ -781,7 +781,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;
}
@@ -1171,14 +1171,40 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
return 0;
}
- tunables = &global_tunables;
+ tunables = kzalloc(sizeof(*tunables), GFP_KERNEL);
+ if (!tunables) {
+ pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ tunables->usage_count = 1;
+ tunables->above_hispeed_delay = default_above_hispeed_delay;
+ tunables->nabove_hispeed_delay =
+ ARRAY_SIZE(default_above_hispeed_delay);
+ tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;
+ tunables->target_loads = default_target_loads;
+ tunables->ntarget_loads = ARRAY_SIZE(default_target_loads);
+ tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
+ tunables->timer_rate = DEFAULT_TIMER_RATE;
+ tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME;
+ tunables->timer_slack_val = DEFAULT_TIMER_SLACK;
+
+ 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)
+ if (rc) {
+ kfree(tunables);
+ policy->governor_data = NULL;
+ if (!have_governor_per_policy())
+ common_tunables = NULL;
return rc;
-
- tunables->usage_count = 1;
+ }
if (!policy->governor->initialized) {
idle_notifier_register(&cpufreq_interactive_idle_nb);
@@ -1186,10 +1212,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
CPUFREQ_TRANSITION_NOTIFIER);
}
- policy->governor_data = tunables;
- if (!have_governor_per_policy())
- common_tunables = tunables;
-
break;
case CPUFREQ_GOV_POLICY_EXIT:
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 14e2254ceba8..af80e05dd78f 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -19,6 +19,14 @@ 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"
+ default y
+ 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 5745254d94d8..6aec8509d7b0 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;
- userptr32_t ptr;
- userptr32_t 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;
- userptr32_t cookie;
+ binder_uintptr_t cookie;
};
struct binder_ref {
@@ -318,7 +318,7 @@ struct binder_proc {
int requested_threads;
int requested_threads_started;
int ready_threads;
- int default_priority;
+ long default_priority;
struct dentry *debugfs_entry;
};
@@ -360,8 +360,8 @@ struct binder_transaction {
struct binder_buffer *buffer;
unsigned int code;
unsigned int flags;
- int priority;
- int saved_priority;
+ long priority;
+ long saved_priority;
kuid_t sender_euid;
};
@@ -430,16 +430,16 @@ static inline void binder_unlock(const char *tag)
mutex_unlock(&binder_main_lock);
}
-static void binder_set_nice(int nice)
+static void binder_set_nice(long nice)
{
- int min_nice;
+ long min_nice;
if (can_nice(current, nice)) {
set_user_nice(current, nice);
return;
}
min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
binder_debug(BINDER_DEBUG_PRIORITY_CAP,
- "%d: nice value %d not allowed use %d instead\n",
+ "%d: nice value %ld not allowed use %ld instead\n",
current->pid, nice, min_nice);
set_user_nice(current, min_nice);
if (min_nice < 20)
@@ -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,
- userptr32_t 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 = (void *)(unsigned long)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);
@@ -660,8 +660,8 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
return NULL;
}
- size = ALIGN(data_size, sizeof(userptr32_t)) +
- ALIGN(offsets_size, sizeof(userptr32_t));
+ size = ALIGN(data_size, sizeof(void *)) +
+ ALIGN(offsets_size, sizeof(void *));
if (size < data_size || size < offsets_size) {
binder_user_error("%d: got transaction with invalid size %zd-%zd\n",
@@ -809,8 +809,8 @@ static void binder_free_buf(struct binder_proc *proc,
buffer_size = binder_buffer_size(proc, buffer);
- size = ALIGN(buffer->data_size, sizeof(userptr32_t)) +
- ALIGN(buffer->offsets_size, sizeof(userptr32_t));
+ size = ALIGN(buffer->data_size, sizeof(void *)) +
+ ALIGN(buffer->offsets_size, sizeof(void *));
binder_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: binder_free_buf %p size %zd buffer_size %zd\n",
@@ -857,7 +857,7 @@ static void binder_free_buf(struct binder_proc *proc,
}
static struct binder_node *binder_get_node(struct binder_proc *proc,
- userptr32_t 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,
- userptr32_t ptr,
- userptr32_t 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%x c%x 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,
- uint32_t *failed_at)
+ binder_size_t *failed_at)
{
- uint32_t *offp, *off_end;
+ binder_size_t *offp, *off_end;
int debug_id = buffer->debug_id;
binder_debug(BINDER_DEBUG_TRANSACTION,
@@ -1240,19 +1240,19 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
- offp = (uint32_t *)(buffer->data +
- ALIGN(buffer->data_size, sizeof(userptr32_t)));
+ offp = (binder_size_t *)(buffer->data +
+ ALIGN(buffer->data_size, sizeof(void *)));
if (failed_at)
off_end = failed_at;
else
- off_end = (uint32_t *)offp + (buffer->offsets_size/4);
+ off_end = (void *)offp + buffer->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
if (*offp > buffer->data_size - sizeof(*fp) ||
buffer->data_size < sizeof(*fp) ||
- !IS_ALIGNED(*offp, sizeof(userptr32_t))) {
- pr_err("transaction release %d bad offset %d, size %zd\n",
- debug_id, *offp, buffer->data_size);
+ !IS_ALIGNED(*offp, sizeof(u32))) {
+ 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);
@@ -1261,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 %x\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%x\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:
@@ -1305,7 +1305,7 @@ static void binder_transaction(struct binder_proc *proc,
{
struct binder_transaction *t;
struct binder_work *tcomplete;
- uint32_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;
@@ -1438,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 %x-%x size %d-%d\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 %x-%x size %d-%d\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;
@@ -1478,35 +1480,37 @@ static void binder_transaction(struct binder_proc *proc,
if (target_node)
binder_inc_node(target_node, 1, 0, NULL);
- offp = (uint32_t *)(t->buffer->data +
- ALIGN(tr->data_size, sizeof(userptr32_t)));
+ offp = (binder_size_t *)(t->buffer->data +
+ ALIGN(tr->data_size, sizeof(void *)));
- if (copy_from_user(t->buffer->data, (void *)(unsigned long)(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, (void *)(unsigned long)(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(u32))) {
- binder_user_error("%d:%d got transaction with invalid offsets size, %d\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;
}
- off_end = (uint32_t *)offp + (tr->offsets_size/4);
+ off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
if (*offp > t->buffer->data_size - sizeof(*fp) ||
t->buffer->data_size < sizeof(*fp) ||
- !IS_ALIGNED(*offp, sizeof(userptr32_t))) {
- binder_user_error("%d:%d got transaction with invalid offset, %d\n",
- proc->pid, thread->pid, *offp);
+ !IS_ALIGNED(*offp, sizeof(u32))) {
+ 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;
}
@@ -1526,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%x node %d, cookie mismatch %x != %x\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)) {
@@ -1551,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%x -> 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: {
@@ -1579,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%x\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);
@@ -1612,7 +1616,7 @@ static void binder_transaction(struct binder_proc *proc,
goto err_fd_not_allowed;
}
} else if (!target_node->accept_fds) {
- binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fd\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;
@@ -1702,9 +1706,9 @@ err_dead_binder:
err_invalid_target_handle:
err_no_context_mgr_node:
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
- "%d:%d transaction failed %d, size %d-%d\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;
@@ -1721,9 +1725,11 @@ err_no_context_mgr_node:
}
int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
- void __user *buffer, int size, int *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;
@@ -1737,16 +1743,11 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
proc->stats.bc[_IOC_NR(cmd)]++;
thread->stats.bc[_IOC_NR(cmd)]++;
}
- /*
- * since the transaction's IOCTL number are generated using
- * _IOC(dir,type,nr,size), a different userspace size will not
- * fall through
- */
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(BC_INCREFS):
- case _IOC_NR(BC_ACQUIRE):
- case _IOC_NR(BC_RELEASE):
- case _IOC_NR(BC_DECREFS): {
+ switch (cmd) {
+ case BC_INCREFS:
+ case BC_ACQUIRE:
+ case BC_RELEASE:
+ case BC_DECREFS: {
uint32_t target;
struct binder_ref *ref;
const char *debug_string;
@@ -1770,20 +1771,20 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
proc->pid, thread->pid, target);
break;
}
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(BC_INCREFS):
+ switch (cmd) {
+ case BC_INCREFS:
debug_string = "IncRefs";
binder_inc_ref(ref, 0, NULL);
break;
- case _IOC_NR(BC_ACQUIRE):
+ case BC_ACQUIRE:
debug_string = "Acquire";
binder_inc_ref(ref, 1, NULL);
break;
- case _IOC_NR(BC_RELEASE):
+ case BC_RELEASE:
debug_string = "Release";
binder_dec_ref(ref, 1);
break;
- case _IOC_NR(BC_DECREFS):
+ case BC_DECREFS:
default:
debug_string = "DecRefs";
binder_dec_ref(ref, 0);
@@ -1795,39 +1796,35 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
ref->desc, ref->strong, ref->weak, ref->node->debug_id);
break;
}
- case _IOC_NR(BC_INCREFS_DONE):
- case _IOC_NR(BC_ACQUIRE_DONE): {
- userptr32_t node_ptr;
- userptr32_t cookie;
+ case BC_INCREFS_DONE:
+ case BC_ACQUIRE_DONE: {
+ binder_uintptr_t node_ptr;
+ binder_uintptr_t cookie;
struct binder_node *node;
- if (_IOC_SIZE(cmd) != sizeof(struct binder_ptr_cookie)) {
- pr_err("binder: tranzaction structure size differs\n");
+ if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
return -EFAULT;
- }
- if (get_user(node_ptr, (userptr32_t __user *)ptr))
- return -EFAULT;
- ptr += sizeof(userptr32_t);
- if (get_user(cookie, (userptr32_t __user *)ptr))
+ ptr += sizeof(binder_uintptr_t);
+ if (get_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+ ptr += sizeof(binder_uintptr_t);
node = binder_get_node(proc, node_ptr);
if (node == NULL) {
- binder_user_error("%d:%d %s u%x 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%x node %d cookie mismatch %x != %x\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) {
@@ -1855,35 +1852,35 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
node->debug_id, node->local_strong_refs, node->local_weak_refs);
break;
}
- case _IOC_NR(BC_ATTEMPT_ACQUIRE):
+ case BC_ATTEMPT_ACQUIRE:
pr_err("BC_ATTEMPT_ACQUIRE not supported\n");
return -EINVAL;
- case _IOC_NR(BC_ACQUIRE_RESULT):
+ case BC_ACQUIRE_RESULT:
pr_err("BC_ACQUIRE_RESULT not supported\n");
return -EINVAL;
- case _IOC_NR(BC_FREE_BUFFER): {
- userptr32_t data_ptr;
+ case BC_FREE_BUFFER: {
+ binder_uintptr_t data_ptr;
struct binder_buffer *buffer;
- if (get_user(data_ptr, (userptr32_t __user *)ptr))
+ if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+ ptr += sizeof(binder_uintptr_t);
buffer = binder_buffer_lookup(proc, data_ptr);
if (buffer == NULL) {
- binder_user_error("%d:%d BC_FREE_BUFFER u%x 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%x 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%x 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) {
@@ -1903,14 +1900,10 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
break;
}
- case _IOC_NR(BC_TRANSACTION):
- case _IOC_NR(BC_REPLY): {
+ case BC_TRANSACTION:
+ case BC_REPLY: {
struct binder_transaction_data tr;
- if (_IOC_SIZE(cmd) != sizeof(tr)) {
- pr_err("binder: tranzaction structure size differs\n");
- return -EFAULT;
- }
if (copy_from_user(&tr, ptr, sizeof(tr)))
return -EFAULT;
ptr += sizeof(tr);
@@ -1918,7 +1911,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
break;
}
- case _IOC_NR(BC_REGISTER_LOOPER):
+ case BC_REGISTER_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_REGISTER_LOOPER\n",
proc->pid, thread->pid);
@@ -1936,7 +1929,7 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
}
thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
break;
- case _IOC_NR(BC_ENTER_LOOPER):
+ case BC_ENTER_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_ENTER_LOOPER\n",
proc->pid, thread->pid);
@@ -1947,26 +1940,26 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
}
thread->looper |= BINDER_LOOPER_STATE_ENTERED;
break;
- case _IOC_NR(BC_EXIT_LOOPER):
+ case BC_EXIT_LOOPER:
binder_debug(BINDER_DEBUG_THREADS,
"%d:%d BC_EXIT_LOOPER\n",
proc->pid, thread->pid);
thread->looper |= BINDER_LOOPER_STATE_EXITED;
break;
- case _IOC_NR(BC_REQUEST_DEATH_NOTIFICATION):
- case _IOC_NR(BC_CLEAR_DEATH_NOTIFICATION): {
+ case BC_REQUEST_DEATH_NOTIFICATION:
+ case BC_CLEAR_DEATH_NOTIFICATION: {
uint32_t target;
- userptr32_t 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, (userptr32_t __user *)ptr))
+ if (get_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+ ptr += sizeof(binder_uintptr_t);
ref = binder_get_ref(proc, target);
if (ref == NULL) {
binder_user_error("%d:%d %s invalid ref %d\n",
@@ -1979,12 +1972,12 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
}
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
- "%d:%d %s %x 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) {
@@ -2022,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 %x != %x\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;
@@ -2042,13 +2035,14 @@ int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
}
}
} break;
- case _IOC_NR(BC_DEAD_BINDER_DONE): {
+ case BC_DEAD_BINDER_DONE: {
struct binder_work *w;
- userptr32_t cookie;
+ binder_uintptr_t cookie;
struct binder_ref_death *death = NULL;
- if (get_user(cookie, (userptr32_t __user *)ptr))
+ if (get_user(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+
+ 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) {
@@ -2057,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 %x 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 %x 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;
}
@@ -2113,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, int size,
- int *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;
@@ -2260,32 +2255,36 @@ retry:
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
- if (put_user((unsigned long)node->ptr, (userptr32_t __user *)ptr))
+ if (put_user(node->ptr,
+ (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
- if (put_user((unsigned long)node->cookie, (userptr32_t __user *)ptr))
+ ptr += sizeof(binder_uintptr_t);
+ if (put_user(node->cookie,
+ (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+ ptr += sizeof(binder_uintptr_t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_USER_REFS,
- "%d:%d %s %d u%x c%x\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%x c%x 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%x c%x 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;
@@ -2303,17 +2302,18 @@ retry:
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
ptr += sizeof(uint32_t);
- if (put_user((unsigned long)death->cookie, (userptr32_t __user *)ptr))
+ if (put_user(death->cookie,
+ (binder_uintptr_t __user *)ptr))
return -EFAULT;
- ptr += sizeof(userptr32_t);
+ ptr += sizeof(binder_uintptr_t);
binder_stat_br(proc, thread, cmd);
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
- "binder: %d:%d %s %x\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);
@@ -2359,14 +2359,14 @@ retry:
tr.sender_pid = 0;
}
- tr.data_size = (userptr32_t)t->buffer->data_size;
- tr.offsets_size = (userptr32_t)t->buffer->offsets_size;
- tr.data.ptr.buffer = (unsigned long)((void *)t->buffer->data +
+ tr.data_size = t->buffer->data_size;
+ tr.offsets_size = t->buffer->offsets_size;
+ tr.data.ptr.buffer = (binder_uintptr_t)(
+ (uintptr_t)t->buffer->data +
proc->user_buffer_offset);
-
- tr.data.ptr.offsets = (userptr32_t)(tr.data.ptr.buffer +
+ tr.data.ptr.offsets = tr.data.ptr.buffer +
ALIGN(t->buffer->data_size,
- sizeof(userptr32_t)));
+ sizeof(void *));
if (put_user(cmd, (uint32_t __user *)ptr))
return -EFAULT;
@@ -2378,14 +2378,14 @@ retry:
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 %x-%x\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;
@@ -2455,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, %x\n",
- death->cookie);
+ "undelivered death notification, %016llx\n",
+ (u64)death->cookie);
kfree(death);
binder_stats_deleted(BINDER_STAT_DEATH);
} break;
@@ -2600,16 +2600,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
goto err;
}
- /*
- * since the transaction's IOCTL number are generated using
- * _IOC(dir,type,nr,size), a different userspace size will not
- * fall through
- */
- switch (_IOC_NR(cmd)) {
- case _IOC_NR(BINDER_WRITE_READ): {
+ switch (cmd) {
+ case BINDER_WRITE_READ: {
struct binder_write_read bwr;
if (size != sizeof(struct binder_write_read)) {
- pr_err("binder: BINDER_WRITE_READ transaction size differs\n");
ret = -EINVAL;
goto err;
}
@@ -2618,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 %d at %08x, read %d at %08x\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 *)(unsigned long)(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;
@@ -2633,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 *)(unsigned long)(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);
@@ -2644,22 +2639,23 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
}
binder_debug(BINDER_DEBUG_READ_WRITE,
- "%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);
+ "%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;
}
break;
}
- case _IOC_NR(BINDER_SET_MAX_THREADS):
+ case BINDER_SET_MAX_THREADS:
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
ret = -EINVAL;
goto err;
}
break;
- case _IOC_NR(BINDER_SET_CONTEXT_MGR):
+ case BINDER_SET_CONTEXT_MGR:
if (binder_context_mgr_node != NULL) {
pr_err("BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
@@ -2688,15 +2684,14 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
break;
- case _IOC_NR(BINDER_THREAD_EXIT):
+ case BINDER_THREAD_EXIT:
binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
proc->pid, thread->pid);
binder_free_thread(proc, thread);
thread = NULL;
break;
- case _IOC_NR(BINDER_VERSION):
+ case BINDER_VERSION:
if (size != sizeof(struct binder_version)) {
- pr_err("binder: BINDER_VERSION size differs\n");
ret = -EINVAL;
goto err;
}
@@ -2706,7 +2701,6 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
break;
default:
- pr_err("binder: IOCTL No. not found\n");
ret = -EINVAL;
goto err;
}
@@ -2947,7 +2941,7 @@ static int binder_node_release(struct binder_node *node, int refs)
refs++;
if (!ref->death)
- goto out;
+ continue;
death++;
@@ -2960,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);
@@ -3131,7 +3124,7 @@ static void print_binder_transaction(struct seq_file *m, const char *prefix,
struct binder_transaction *t)
{
seq_printf(m,
- "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %d r%d",
+ "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
prefix, t->debug_id, t,
t->from ? t->from->proc->pid : 0,
t->from ? t->from->pid : 0,
@@ -3176,8 +3169,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%x c%x\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);
@@ -3237,8 +3231,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%x c%x 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);
@@ -3540,7 +3534,7 @@ static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
- .compat_ioctl = binder_ioctl, /* handler for 32-bit compat layer */
+ .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/ion/compat_ion.c b/drivers/staging/android/ion/compat_ion.c
index af6cd370b30f..ee3a7380e53b 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,19 @@ 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;
+ int err;
+
+ 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 +150,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 +159,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;
diff --git a/drivers/staging/android/uapi/binder.h b/drivers/staging/android/uapi/binder.h
index 12198b74e47a..4098c502fc36 100644
--- a/drivers/staging/android/uapi/binder.h
+++ b/drivers/staging/android/uapi/binder.h
@@ -26,8 +26,6 @@
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85
-typedef __u32 userptr32_t;
-
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
@@ -41,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
@@ -50,17 +56,17 @@ enum {
*/
struct flat_binder_object {
/* 8 bytes for large_flat_header. */
- uint32_t type;
- uint32_t flags;
+ __u32 type;
+ __u32 flags;
/* 8 bytes of data. */
union {
- userptr32_t binder; /* local object */
- int32_t handle; /* remote object */
+ binder_uintptr_t binder; /* local object */
+ __u32 handle; /* remote object */
};
/* extra data associated with local object */
- userptr32_t cookie;
+ binder_uintptr_t cookie;
};
/*
@@ -69,22 +75,26 @@ struct flat_binder_object {
*/
struct binder_write_read {
- int32_t write_size; /* bytes to write */
- int32_t write_consumed; /* bytes consumed by driver */
- uint32_t write_buffer;
- int32_t read_size; /* bytes to read */
- int32_t read_consumed; /* bytes consumed by driver */
- uint32_t 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. */
struct binder_version {
/* driver protocol version -- increment with incompatible change */
- int32_t protocol_version;
+ __s32 protocol_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)
@@ -121,18 +131,18 @@ struct binder_transaction_data {
* identifying the target and contents of the transaction.
*/
union {
- uint32_t handle; /* target descriptor of command transaction */
- userptr32_t ptr; /* target descriptor of return transaction */
+ __u32 handle; /* target descriptor of command transaction */
+ binder_uintptr_t ptr; /* target descriptor of return transaction */
} target;
- userptr32_t cookie; /* target object cookie */
- unsigned int code; /* transaction command */
+ binder_uintptr_t cookie; /* target object cookie */
+ __u32 code; /* transaction command */
/* General information about the transaction. */
- unsigned int flags;
+ __u32 flags;
pid_t sender_pid;
uid_t sender_euid;
- uint32_t data_size; /* number of bytes of data */
- uint32_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
@@ -141,32 +151,37 @@ struct binder_transaction_data {
union {
struct {
/* transaction data */
- userptr32_t buffer;
+ binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
- userptr32_t offsets;
+ binder_uintptr_t offsets;
} ptr;
- uint8_t buf[8];
+ __u8 buf[8];
} data;
};
struct binder_ptr_cookie {
- userptr32_t tr;
- userptr32_t cookie;
+ binder_uintptr_t ptr;
+ binder_uintptr_t cookie;
};
+struct binder_handle_cookie {
+ __u32 handle;
+ binder_uintptr_t cookie;
+} __attribute__((packed));
+
struct binder_pri_desc {
- int priority;
- int desc;
+ __s32 priority;
+ __u32 desc;
};
struct binder_pri_ptr_cookie {
- int priority;
- userptr32_t ptr;
- userptr32_t cookie;
+ __s32 priority;
+ binder_uintptr_t ptr;
+ binder_uintptr_t cookie;
};
enum binder_driver_return_protocol {
- BR_ERROR = _IOR('r', 0, int),
+ BR_ERROR = _IOR('r', 0, __s32),
/*
* int: error code
*/
@@ -180,7 +195,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.
@@ -237,11 +252,11 @@ enum binder_driver_return_protocol {
* stop threadpool thread
*/
- BR_DEAD_BINDER = _IOR('r', 15, userptr32_t),
+ BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
/*
* void *: cookie
*/
- BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, userptr32_t),
+ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
/*
* void *: cookie
*/
@@ -260,22 +275,22 @@ 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.
* Else you have acquired a primary reference on the object.
*/
- BC_FREE_BUFFER = _IOW('c', 3, int),
+ BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
/*
* 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
*/
@@ -310,19 +325,19 @@ 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
*/
- BC_DEAD_BINDER_DONE = _IOW('c', 16, userptr32_t),
+ BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
/*
* void *: cookie
*/
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 @@ requeue_req:
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) {
diff --git a/drivers/video/adf/adf_client.c b/drivers/video/adf/adf_client.c
index bba873d34bbb..8061d8e6b9fb 100644
--- a/drivers/video/adf/adf_client.c
+++ b/drivers/video/adf/adf_client.c
@@ -283,7 +283,7 @@ static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf,
attachment = dma_buf_attach(buf->dma_bufs[i], dev->dev);
if (IS_ERR(attachment)) {
ret = PTR_ERR(attachment);
- dev_err(&dev->base.dev, "attaching plane %u failed: %d\n",
+ dev_err(&dev->base.dev, "attaching plane %zu failed: %d\n",
i, ret);
goto done;
}
@@ -292,12 +292,13 @@ static int adf_buffer_map(struct adf_device *dev, struct adf_buffer *buf,
sg_table = dma_buf_map_attachment(attachment, DMA_TO_DEVICE);
if (IS_ERR(sg_table)) {
ret = PTR_ERR(sg_table);
- dev_err(&dev->base.dev, "mapping plane %u failed: %d",
+ dev_err(&dev->base.dev, "mapping plane %zu failed: %d",
i, ret);
goto done;
} else if (!sg_table) {
ret = -ENOMEM;
- dev_err(&dev->base.dev, "mapping plane %u failed\n", i);
+ dev_err(&dev->base.dev, "mapping plane %zu failed\n",
+ i);
goto done;
}
mapping->sg_tables[i] = sg_table;
diff --git a/drivers/video/adf/adf_fops32.c b/drivers/video/adf/adf_fops32.c
index 60a47cf5a781..d299a8161491 100644
--- a/drivers/video/adf/adf_fops32.c
+++ b/drivers/video/adf/adf_fops32.c
@@ -81,7 +81,7 @@ long adf_compat_get_device_data(struct file *file,
&data->custom_data))
return -EFAULT;
- ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA32, (unsigned long)data);
+ ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data);
if (ret < 0)
return ret;
@@ -122,7 +122,7 @@ long adf_compat_get_interface_data(struct file *file,
&data->custom_data))
return -EFAULT;
- ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA32, (unsigned long)data);
+ ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data);
if (ret < 0)
return ret;
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 <video/adf.h>
#define ADF_POST_CONFIG32 \
- _IOW('D', 2, struct adf_post_config32)
+ _IOW(ADF_IOCTL_TYPE, 2, struct adf_post_config32)
#define ADF_GET_DEVICE_DATA32 \
- _IOR('D', 4, struct adf_device_data32)
+ _IOR(ADF_IOCTL_TYPE, 4, struct adf_device_data32)
#define ADF_GET_INTERFACE_DATA32 \
- _IOR('D', 5, struct adf_interface_data32)
+ _IOR(ADF_IOCTL_TYPE, 5, struct adf_interface_data32)
#define ADF_GET_OVERLAY_ENGINE_DATA32 \
- _IOR('D', 6, struct adf_overlay_engine_data32)
+ _IOR(ADF_IOCTL_TYPE, 6, struct adf_overlay_engine_data32)
struct adf_post_config32 {
compat_size_t n_interfaces;
diff --git a/include/net/ip.h b/include/net/ip.h
index 788f1d8a796f..edfa59174d9a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -454,7 +454,7 @@ extern int compat_ip_getsockopt(struct sock *sk, int level,
int optname, char __user *optval, int __user *optlen);
extern int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
-extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len);
+extern int ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
extern void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
__be16 port, u32 info, u8 *payload);
extern void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 dport,
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 97a5e5c04d7d..08a85885dbb9 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -261,10 +261,10 @@ 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 icmp6hdr *thdr, int len);
struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
- struct sock *sk, struct flowi6 *fl6);
+ struct sock *sk, struct flowi6 *fl6);
extern int ip6_ra_control(struct sock *sk, int sel);
diff --git a/include/net/ping.h b/include/net/ping.h
index 34d670048653..9242fa090d3d 100644
--- a/include/net/ping.h
+++ b/include/net/ping.h
@@ -33,7 +33,7 @@
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);
+ 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);
@@ -72,7 +72,6 @@ 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);
-void ping_v4_err(struct sk_buff *skb, u32 info);
int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd,
struct sk_buff *);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index a67601f2cb50..c10bd7a33492 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -288,6 +288,7 @@ extern int sysctl_tcp_early_retrans;
extern int sysctl_tcp_limit_output_bytes;
extern int sysctl_tcp_challenge_ack_limit;
extern int sysctl_tcp_min_tso_segs;
+extern int sysctl_tcp_default_init_rwnd;
extern atomic_long_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
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_ */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 62f663040d83..562efd91f457 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -939,7 +939,8 @@ error:
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_v4_err(skb, info);
+ ping_err(skb, offset, info);
return;
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 23e6ab0a2dc0..d9c4f113d709 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -368,7 +368,7 @@ void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 inf
/*
* Handle MSG_ERRQUEUE
*/
-int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
{
struct sock_exterr_skb *serr;
struct sk_buff *skb, *skb2;
@@ -405,7 +405,6 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
serr->addr_offset);
sin->sin_port = serr->port;
memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
- *addr_len = sizeof(*sin);
}
memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 0b26c09e5af7..5bf79864ca66 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -468,8 +468,6 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
int err;
if (skb->protocol == htons(ETH_P_IP)) {
- struct iphdr *iph = (struct iphdr *)skb->data;
- offset = iph->ihl << 2;
family = AF_INET;
type = icmp_hdr(skb)->type;
code = icmp_hdr(skb)->code;
@@ -511,7 +509,8 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
break;
case ICMP_SOURCE_QUENCH:
/* This is not a real error but ping wants to see it.
- * Report it with some fake errno. */
+ * Report it with some fake errno.
+ */
err = EREMOTEIO;
break;
case ICMP_PARAMETERPROB:
@@ -557,11 +556,11 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
} else {
if (family == AF_INET) {
ip_icmp_error(sk, skb, err, 0 /* no remote port */,
- info, (u8 *)icmph);
+ 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);
+ info, (u8 *)icmph);
#endif
}
}
@@ -572,18 +571,13 @@ out:
}
EXPORT_SYMBOL_GPL(ping_err);
-void ping_v4_err(struct sk_buff *skb, u32 info)
-{
- ping_err(skb, 0, info);
-}
-
/*
* Copy and checksum an ICMP Echo packet from user space into a buffer
* starting from the payload.
*/
int ping_getfrag(void *from, char *to,
- int offset, int fraglen, int odd, struct sk_buff *skb)
+ int offset, int fraglen, int odd, struct sk_buff *skb)
{
struct pingfakehdr *pfh = (struct pingfakehdr *)from;
@@ -853,7 +847,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if (flags & MSG_ERRQUEUE) {
if (family == AF_INET) {
- return ip_recv_error(sk, msg, len, addr_len);
+ 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);
@@ -881,16 +875,11 @@ 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;
-
- /* Copy the address. */
- if (msg->msg_name) {
- struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
-
+ 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));
- *addr_len = sizeof(*sin);
}
if (isk->cmsg_flags)
@@ -901,17 +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 =
- *(__be32 *)ip6 & IPV6_FLOWINFO_MASK;
-
- 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);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 402870fdfa0e..448e5a77fa88 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -693,7 +693,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
goto out;
if (flags & MSG_ERRQUEUE) {
- err = ip_recv_error(sk, msg, len, addr_len);
+ err = ip_recv_error(sk, msg, len);
goto out;
}
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 90b26beb84d4..4fca1aa4c505 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -138,6 +138,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)
{
@@ -737,7 +752,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),
@@ -763,6 +778,13 @@ static struct ctl_table ipv4_table[] = {
.extra2 = &gso_max_segs,
},
{
+ .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,
.maxlen = sizeof(sysctl_udp_mem),
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e15d330919af..aa5f3bfebabd 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 5560abfe6d30..3b113f84a277 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
*/
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5ed9a7a09f04..fe1a3404314d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1216,7 +1216,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
bool slow;
if (flags & MSG_ERRQUEUE)
- return ip_recv_error(sk, msg, len, addr_len);
+ return ip_recv_error(sk, msg, len);
try_again:
skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0),
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 50308a8070f8..6128f302f593 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -85,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);
@@ -699,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;
}
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;
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 */
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;