android: binder: Disable preemption while holding the global binder lock.
Change-Id: I90fe02cdedb8a5677b900a68528fb443b9204322 Signed-off-by: Riley Andrews <riandrews@google.com> Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-4.4 Git-commit: 5c9ce54ca3a66a57e4ebfe3ae71c5733b6bcc579 Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
This commit is contained in:
parent
cbe08a7835
commit
e4045d607a
1 changed files with 115 additions and 43 deletions
|
@ -427,6 +427,7 @@ static inline void binder_lock(const char *tag)
|
||||||
{
|
{
|
||||||
trace_binder_lock(tag);
|
trace_binder_lock(tag);
|
||||||
mutex_lock(&binder_main_lock);
|
mutex_lock(&binder_main_lock);
|
||||||
|
preempt_disable();
|
||||||
trace_binder_locked(tag);
|
trace_binder_locked(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,8 +435,62 @@ static inline void binder_unlock(const char *tag)
|
||||||
{
|
{
|
||||||
trace_binder_unlock(tag);
|
trace_binder_unlock(tag);
|
||||||
mutex_unlock(&binder_main_lock);
|
mutex_unlock(&binder_main_lock);
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void *kzalloc_preempt_disabled(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
ptr = kzalloc(size, GFP_NOWAIT);
|
||||||
|
if (ptr)
|
||||||
|
return ptr;
|
||||||
|
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
ptr = kzalloc(size, GFP_KERNEL);
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long copy_to_user_preempt_disabled(void __user *to, const void *from, long n)
|
||||||
|
{
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
ret = copy_to_user(to, from, n);
|
||||||
|
preempt_disable();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long copy_from_user_preempt_disabled(void *to, const void __user *from, long n)
|
||||||
|
{
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
ret = copy_from_user(to, from, n);
|
||||||
|
preempt_disable();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define get_user_preempt_disabled(x, ptr) \
|
||||||
|
({ \
|
||||||
|
int __ret; \
|
||||||
|
preempt_enable_no_resched(); \
|
||||||
|
__ret = get_user(x, ptr); \
|
||||||
|
preempt_disable(); \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define put_user_preempt_disabled(x, ptr) \
|
||||||
|
({ \
|
||||||
|
int __ret; \
|
||||||
|
preempt_enable_no_resched(); \
|
||||||
|
__ret = put_user(x, ptr); \
|
||||||
|
preempt_disable(); \
|
||||||
|
__ret; \
|
||||||
|
})
|
||||||
|
|
||||||
static void binder_set_nice(long nice)
|
static void binder_set_nice(long nice)
|
||||||
{
|
{
|
||||||
long min_nice;
|
long min_nice;
|
||||||
|
@ -568,6 +623,8 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||||
else
|
else
|
||||||
mm = get_task_mm(proc->tsk);
|
mm = get_task_mm(proc->tsk);
|
||||||
|
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
|
||||||
if (mm) {
|
if (mm) {
|
||||||
down_write(&mm->mmap_sem);
|
down_write(&mm->mmap_sem);
|
||||||
vma = proc->vma;
|
vma = proc->vma;
|
||||||
|
@ -622,6 +679,9 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||||
up_write(&mm->mmap_sem);
|
up_write(&mm->mmap_sem);
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
free_range:
|
free_range:
|
||||||
|
@ -644,6 +704,9 @@ err_no_vma:
|
||||||
up_write(&mm->mmap_sem);
|
up_write(&mm->mmap_sem);
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,7 +966,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
node = kzalloc_preempt_disabled(sizeof(*node));
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
binder_stats_created(BINDER_STAT_NODE);
|
binder_stats_created(BINDER_STAT_NODE);
|
||||||
|
@ -1040,7 +1103,7 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
|
||||||
else
|
else
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
|
new_ref = kzalloc_preempt_disabled(sizeof(*ref));
|
||||||
if (new_ref == NULL)
|
if (new_ref == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
binder_stats_created(BINDER_STAT_REF);
|
binder_stats_created(BINDER_STAT_REF);
|
||||||
|
@ -1438,14 +1501,14 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
e->to_proc = target_proc->pid;
|
e->to_proc = target_proc->pid;
|
||||||
|
|
||||||
/* TODO: reuse incoming transaction for reply */
|
/* TODO: reuse incoming transaction for reply */
|
||||||
t = kzalloc(sizeof(*t), GFP_KERNEL);
|
t = kzalloc_preempt_disabled(sizeof(*t));
|
||||||
if (t == NULL) {
|
if (t == NULL) {
|
||||||
return_error = BR_FAILED_REPLY;
|
return_error = BR_FAILED_REPLY;
|
||||||
goto err_alloc_t_failed;
|
goto err_alloc_t_failed;
|
||||||
}
|
}
|
||||||
binder_stats_created(BINDER_STAT_TRANSACTION);
|
binder_stats_created(BINDER_STAT_TRANSACTION);
|
||||||
|
|
||||||
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
|
tcomplete = kzalloc_preempt_disabled(sizeof(*tcomplete));
|
||||||
if (tcomplete == NULL) {
|
if (tcomplete == NULL) {
|
||||||
return_error = BR_FAILED_REPLY;
|
return_error = BR_FAILED_REPLY;
|
||||||
goto err_alloc_tcomplete_failed;
|
goto err_alloc_tcomplete_failed;
|
||||||
|
@ -1502,14 +1565,14 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
offp = (binder_size_t *)(t->buffer->data +
|
offp = (binder_size_t *)(t->buffer->data +
|
||||||
ALIGN(tr->data_size, sizeof(void *)));
|
ALIGN(tr->data_size, sizeof(void *)));
|
||||||
|
|
||||||
if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
|
if (copy_from_user_preempt_disabled(t->buffer->data, (const void __user *)(uintptr_t)
|
||||||
tr->data.ptr.buffer, tr->data_size)) {
|
tr->data.ptr.buffer, tr->data_size)) {
|
||||||
binder_user_error("%d:%d got transaction with invalid data ptr\n",
|
binder_user_error("%d:%d got transaction with invalid data ptr\n",
|
||||||
proc->pid, thread->pid);
|
proc->pid, thread->pid);
|
||||||
return_error = BR_FAILED_REPLY;
|
return_error = BR_FAILED_REPLY;
|
||||||
goto err_copy_data_failed;
|
goto err_copy_data_failed;
|
||||||
}
|
}
|
||||||
if (copy_from_user(offp, (const void __user *)(uintptr_t)
|
if (copy_from_user_preempt_disabled(offp, (const void __user *)(uintptr_t)
|
||||||
tr->data.ptr.offsets, tr->offsets_size)) {
|
tr->data.ptr.offsets, tr->offsets_size)) {
|
||||||
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
|
binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
|
||||||
proc->pid, thread->pid);
|
proc->pid, thread->pid);
|
||||||
|
@ -1778,7 +1841,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
void __user *end = buffer + size;
|
void __user *end = buffer + size;
|
||||||
|
|
||||||
while (ptr < end && thread->return_error == BR_OK) {
|
while (ptr < end && thread->return_error == BR_OK) {
|
||||||
if (get_user(cmd, (uint32_t __user *)ptr))
|
if (get_user_preempt_disabled(cmd, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
trace_binder_command(cmd);
|
trace_binder_command(cmd);
|
||||||
|
@ -1796,7 +1859,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
struct binder_ref *ref;
|
struct binder_ref *ref;
|
||||||
const char *debug_string;
|
const char *debug_string;
|
||||||
|
|
||||||
if (get_user(target, (uint32_t __user *)ptr))
|
if (get_user_preempt_disabled(target, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
if (target == 0 && binder_context_mgr_node &&
|
if (target == 0 && binder_context_mgr_node &&
|
||||||
|
@ -1846,10 +1909,10 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
binder_uintptr_t cookie;
|
binder_uintptr_t cookie;
|
||||||
struct binder_node *node;
|
struct binder_node *node;
|
||||||
|
|
||||||
if (get_user(node_ptr, (binder_uintptr_t __user *)ptr))
|
if (get_user_preempt_disabled(node_ptr, (binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
node = binder_get_node(proc, node_ptr);
|
node = binder_get_node(proc, node_ptr);
|
||||||
|
@ -1907,7 +1970,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
binder_uintptr_t data_ptr;
|
binder_uintptr_t data_ptr;
|
||||||
struct binder_buffer *buffer;
|
struct binder_buffer *buffer;
|
||||||
|
|
||||||
if (get_user(data_ptr, (binder_uintptr_t __user *)ptr))
|
if (get_user_preempt_disabled(data_ptr, (binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
|
|
||||||
|
@ -1949,7 +2012,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
case BC_REPLY: {
|
case BC_REPLY: {
|
||||||
struct binder_transaction_data tr;
|
struct binder_transaction_data tr;
|
||||||
|
|
||||||
if (copy_from_user(&tr, ptr, sizeof(tr)))
|
if (copy_from_user_preempt_disabled(&tr, ptr, sizeof(tr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(tr);
|
ptr += sizeof(tr);
|
||||||
binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
|
binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
|
||||||
|
@ -1999,10 +2062,10 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
struct binder_ref *ref;
|
struct binder_ref *ref;
|
||||||
struct binder_ref_death *death;
|
struct binder_ref_death *death;
|
||||||
|
|
||||||
if (get_user(target, (uint32_t __user *)ptr))
|
if (get_user_preempt_disabled(target, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
ref = binder_get_ref(proc, target);
|
ref = binder_get_ref(proc, target);
|
||||||
|
@ -2031,7 +2094,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
proc->pid, thread->pid);
|
proc->pid, thread->pid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
death = kzalloc(sizeof(*death), GFP_KERNEL);
|
death = kzalloc_preempt_disabled(sizeof(*death));
|
||||||
if (death == NULL) {
|
if (death == NULL) {
|
||||||
thread->return_error = BR_ERROR;
|
thread->return_error = BR_ERROR;
|
||||||
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
|
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
|
||||||
|
@ -2085,8 +2148,7 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
struct binder_work *w;
|
struct binder_work *w;
|
||||||
binder_uintptr_t cookie;
|
binder_uintptr_t cookie;
|
||||||
struct binder_ref_death *death = NULL;
|
struct binder_ref_death *death = NULL;
|
||||||
|
if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr))
|
||||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ptr += sizeof(cookie);
|
ptr += sizeof(cookie);
|
||||||
|
@ -2118,7 +2180,8 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||||
wake_up_interruptible(&proc->wait);
|
wake_up_interruptible(&proc->wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pr_err("%d:%d unknown command %d\n",
|
pr_err("%d:%d unknown command %d\n",
|
||||||
|
@ -2167,7 +2230,7 @@ static int binder_thread_read(struct binder_proc *proc,
|
||||||
int wait_for_proc_work;
|
int wait_for_proc_work;
|
||||||
|
|
||||||
if (*consumed == 0) {
|
if (*consumed == 0) {
|
||||||
if (put_user(BR_NOOP, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(BR_NOOP, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
@ -2178,7 +2241,7 @@ retry:
|
||||||
|
|
||||||
if (thread->return_error != BR_OK && ptr < end) {
|
if (thread->return_error != BR_OK && ptr < end) {
|
||||||
if (thread->return_error2 != BR_OK) {
|
if (thread->return_error2 != BR_OK) {
|
||||||
if (put_user(thread->return_error2, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(thread->return_error2, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
binder_stat_br(proc, thread, thread->return_error2);
|
binder_stat_br(proc, thread, thread->return_error2);
|
||||||
|
@ -2186,7 +2249,7 @@ retry:
|
||||||
goto done;
|
goto done;
|
||||||
thread->return_error2 = BR_OK;
|
thread->return_error2 = BR_OK;
|
||||||
}
|
}
|
||||||
if (put_user(thread->return_error, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(thread->return_error, (uint32_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
binder_stat_br(proc, thread, thread->return_error);
|
binder_stat_br(proc, thread, thread->return_error);
|
||||||
|
@ -2264,7 +2327,7 @@ retry:
|
||||||
} break;
|
} break;
|
||||||
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
||||||
cmd = BR_TRANSACTION_COMPLETE;
|
cmd = BR_TRANSACTION_COMPLETE;
|
||||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(cmd, (uint32_t __user *) ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
|
|
||||||
|
@ -2306,14 +2369,14 @@ retry:
|
||||||
node->has_weak_ref = 0;
|
node->has_weak_ref = 0;
|
||||||
}
|
}
|
||||||
if (cmd != BR_NOOP) {
|
if (cmd != BR_NOOP) {
|
||||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(cmd, (uint32_t __user *) ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
if (put_user(node->ptr,
|
if (put_user_preempt_disabled(node->ptr, (binder_uintptr_t __user *)
|
||||||
(binder_uintptr_t __user *)ptr))
|
(binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
if (put_user(node->cookie,
|
if (put_user_preempt_disabled(node->cookie, (binder_uintptr_t __user *)
|
||||||
(binder_uintptr_t __user *)ptr))
|
(binder_uintptr_t __user *)ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
|
@ -2357,11 +2420,10 @@ retry:
|
||||||
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
|
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
|
||||||
else
|
else
|
||||||
cmd = BR_DEAD_BINDER;
|
cmd = BR_DEAD_BINDER;
|
||||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(cmd, (uint32_t __user *) ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
if (put_user(death->cookie,
|
if (put_user_preempt_disabled(death->cookie, (binder_uintptr_t __user *) ptr))
|
||||||
(binder_uintptr_t __user *)ptr))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(binder_uintptr_t);
|
ptr += sizeof(binder_uintptr_t);
|
||||||
binder_stat_br(proc, thread, cmd);
|
binder_stat_br(proc, thread, cmd);
|
||||||
|
@ -2428,10 +2490,10 @@ retry:
|
||||||
ALIGN(t->buffer->data_size,
|
ALIGN(t->buffer->data_size,
|
||||||
sizeof(void *));
|
sizeof(void *));
|
||||||
|
|
||||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
if (put_user_preempt_disabled(cmd, (uint32_t __user *) ptr))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(uint32_t);
|
ptr += sizeof(uint32_t);
|
||||||
if (copy_to_user(ptr, &tr, sizeof(tr)))
|
if (copy_to_user_preempt_disabled(ptr, &tr, sizeof(tr)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ptr += sizeof(tr);
|
ptr += sizeof(tr);
|
||||||
|
|
||||||
|
@ -2473,7 +2535,7 @@ done:
|
||||||
binder_debug(BINDER_DEBUG_THREADS,
|
binder_debug(BINDER_DEBUG_THREADS,
|
||||||
"%d:%d BR_SPAWN_LOOPER\n",
|
"%d:%d BR_SPAWN_LOOPER\n",
|
||||||
proc->pid, thread->pid);
|
proc->pid, thread->pid);
|
||||||
if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
|
if (put_user_preempt_disabled(BR_SPAWN_LOOPER, (uint32_t __user *) buffer))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
|
binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
|
||||||
}
|
}
|
||||||
|
@ -2548,7 +2610,7 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*p == NULL) {
|
if (*p == NULL) {
|
||||||
thread = kzalloc(sizeof(*thread), GFP_KERNEL);
|
thread = kzalloc_preempt_disabled(sizeof(*thread));
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
binder_stats_created(BINDER_STAT_THREAD);
|
binder_stats_created(BINDER_STAT_THREAD);
|
||||||
|
@ -2652,7 +2714,7 @@ static int binder_ioctl_write_read(struct file *filp,
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
|
if (copy_from_user_preempt_disabled(&bwr, ubuf, sizeof(bwr))) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2670,7 +2732,7 @@ static int binder_ioctl_write_read(struct file *filp,
|
||||||
trace_binder_write_done(ret);
|
trace_binder_write_done(ret);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bwr.read_consumed = 0;
|
bwr.read_consumed = 0;
|
||||||
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
|
if (copy_to_user_preempt_disabled(ubuf, &bwr, sizeof(bwr)))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2684,7 +2746,7 @@ static int binder_ioctl_write_read(struct file *filp,
|
||||||
if (!list_empty(&proc->todo))
|
if (!list_empty(&proc->todo))
|
||||||
wake_up_interruptible(&proc->wait);
|
wake_up_interruptible(&proc->wait);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
|
if (copy_to_user_preempt_disabled(ubuf, &bwr, sizeof(bwr)))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2694,7 +2756,7 @@ static int binder_ioctl_write_read(struct file *filp,
|
||||||
proc->pid, thread->pid,
|
proc->pid, thread->pid,
|
||||||
(u64)bwr.write_consumed, (u64)bwr.write_size,
|
(u64)bwr.write_consumed, (u64)bwr.write_size,
|
||||||
(u64)bwr.read_consumed, (u64)bwr.read_size);
|
(u64)bwr.read_consumed, (u64)bwr.read_size);
|
||||||
if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
|
if (copy_to_user_preempt_disabled(ubuf, &bwr, sizeof(bwr))) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -2772,7 +2834,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
case BINDER_SET_MAX_THREADS:
|
case BINDER_SET_MAX_THREADS:
|
||||||
if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
|
if (copy_from_user_preempt_disabled(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -2795,8 +2857,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
|
if (put_user_preempt_disabled(BINDER_CURRENT_PROTOCOL_VERSION, &ver->protocol_version)) {
|
||||||
&ver->protocol_version)) {
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -2858,6 +2919,7 @@ static const struct vm_operations_struct binder_vm_ops = {
|
||||||
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
struct vm_struct *area;
|
struct vm_struct *area;
|
||||||
struct binder_proc *proc = filp->private_data;
|
struct binder_proc *proc = filp->private_data;
|
||||||
const char *failure_string;
|
const char *failure_string;
|
||||||
|
@ -2918,7 +2980,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
vma->vm_ops = &binder_vm_ops;
|
vma->vm_ops = &binder_vm_ops;
|
||||||
vma->vm_private_data = proc;
|
vma->vm_private_data = proc;
|
||||||
|
|
||||||
if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
|
/* binder_update_page_range assumes preemption is disabled */
|
||||||
|
preempt_disable();
|
||||||
|
ret = binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma);
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
if (ret) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
failure_string = "alloc small buf";
|
failure_string = "alloc small buf";
|
||||||
goto err_alloc_small_buf_failed;
|
goto err_alloc_small_buf_failed;
|
||||||
|
@ -3188,8 +3254,12 @@ static void binder_deferred_func(struct work_struct *work)
|
||||||
int defer;
|
int defer;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
binder_lock(__func__);
|
trace_binder_lock(__func__);
|
||||||
|
mutex_lock(&binder_main_lock);
|
||||||
|
trace_binder_locked(__func__);
|
||||||
|
|
||||||
mutex_lock(&binder_deferred_lock);
|
mutex_lock(&binder_deferred_lock);
|
||||||
|
preempt_disable();
|
||||||
if (!hlist_empty(&binder_deferred_list)) {
|
if (!hlist_empty(&binder_deferred_list)) {
|
||||||
proc = hlist_entry(binder_deferred_list.first,
|
proc = hlist_entry(binder_deferred_list.first,
|
||||||
struct binder_proc, deferred_work_node);
|
struct binder_proc, deferred_work_node);
|
||||||
|
@ -3215,7 +3285,9 @@ static void binder_deferred_func(struct work_struct *work)
|
||||||
if (defer & BINDER_DEFERRED_RELEASE)
|
if (defer & BINDER_DEFERRED_RELEASE)
|
||||||
binder_deferred_release(proc); /* frees proc */
|
binder_deferred_release(proc); /* frees proc */
|
||||||
|
|
||||||
binder_unlock(__func__);
|
trace_binder_unlock(__func__);
|
||||||
|
mutex_unlock(&binder_main_lock);
|
||||||
|
preempt_enable_no_resched();
|
||||||
if (files)
|
if (files)
|
||||||
put_files_struct(files);
|
put_files_struct(files);
|
||||||
} while (proc);
|
} while (proc);
|
||||||
|
|
Loading…
Add table
Reference in a new issue