binder: don't unlock procs while scanning contexts

Releasing the procs lock while freezing a binder context allows for
other processes to modify the process list while the scan is still
ongoing.

Don't release the process locks during the scan operatoin, but store
matching processes in a dynamic array and process them at a later phase.

Signed-off-by: Marco Ballesio <balejs@google.com>
Bug: 176996063
Test: verified that all contexts are correctly frozen and unfrozen
Change-Id: Iea527e3b9188b04303f8b9b08b404e0c062a0189
urubino
Marco Ballesio 3 years ago committed by Jenna-they-them
parent 1346a19582
commit 8e0fba4569
  1. 54
      drivers/android/binder.c

@ -5188,32 +5188,60 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
case BINDER_FREEZE: {
struct binder_freeze_info info;
struct binder_proc *target_proc;
ret = -EINVAL;
struct binder_proc **target_procs = NULL, *target_proc;
int target_procs_count = 0, i = 0;
ret = 0;
if (copy_from_user(&info, ubuf, sizeof(info))) {
ret = -EFAULT;
goto err;
}
mutex_lock(&binder_procs_lock);
hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
if (target_proc->pid == info.pid) {
binder_inner_proc_lock(target_proc);
target_proc->tmp_ref++;
binder_inner_proc_unlock(target_proc);
if (target_proc->pid == info.pid)
target_procs_count++;
}
mutex_unlock(&binder_procs_lock);
ret = binder_ioctl_freeze(&info, target_proc);
mutex_lock(&binder_procs_lock);
if (target_procs_count == 0) {
mutex_unlock(&binder_procs_lock);
ret = -EINVAL;
goto err;
}
binder_proc_dec_tmpref(target_proc);
target_procs = kmalloc(sizeof(struct binder_proc *) *
target_procs_count,
GFP_KERNEL);
if (ret < 0)
break;
}
if (!target_procs) {
mutex_unlock(&binder_procs_lock);
ret = -ENOMEM;
goto err;
}
hlist_for_each_entry(target_proc, &binder_procs, proc_node) {
if (target_proc->pid != info.pid)
continue;
binder_inner_proc_lock(target_proc);
target_proc->tmp_ref++;
binder_inner_proc_unlock(target_proc);
target_procs[i++] = target_proc;
}
mutex_unlock(&binder_procs_lock);
for (i = 0; i < target_procs_count; i++) {
if (ret >= 0)
ret = binder_ioctl_freeze(&info,
target_procs[i]);
binder_proc_dec_tmpref(target_procs[i]);
}
kfree(target_procs);
if (ret < 0)
goto err;
break;

Loading…
Cancel
Save