diff options
author | Marco Ballesio <balejs@google.com> | 2021-03-16 04:16:30 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-03-24 10:26:31 +0300 |
commit | ae28c1be1e54f2eda1c8b4469c4652e8a24056ed (patch) | |
tree | 064fcddd4945ff28d6504a3e64859017f7a45814 /drivers/android/binder.c | |
parent | 95c16f9d9cf9db090ae16179f1f721284a6f3aef (diff) | |
download | linux-ae28c1be1e54f2eda1c8b4469c4652e8a24056ed.tar.xz |
binder: BINDER_GET_FROZEN_INFO ioctl
User space needs to know if binder transactions occurred to frozen
processes. Introduce a new BINDER_GET_FROZEN ioctl and keep track of
transactions occurring to frozen proceses.
Signed-off-by: Marco Ballesio <balejs@google.com>
Signed-off-by: Li Li <dualli@google.com>
Acked-by: Todd Kjos <tkjos@google.com>
Link: https://lore.kernel.org/r/20210316011630.1121213-4-dualli@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/android/binder.c')
-rw-r--r-- | drivers/android/binder.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index fe16c455a76e..e1a484ab0366 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2360,6 +2360,10 @@ static int binder_proc_transaction(struct binder_transaction *t, } binder_inner_proc_lock(proc); + if (proc->is_frozen) { + proc->sync_recv |= !oneway; + proc->async_recv |= oneway; + } if ((proc->is_frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { @@ -4634,6 +4638,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, if (!info->enable) { binder_inner_proc_lock(target_proc); + target_proc->sync_recv = false; + target_proc->async_recv = false; target_proc->is_frozen = false; binder_inner_proc_unlock(target_proc); return 0; @@ -4645,6 +4651,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, * for transactions to drain. */ binder_inner_proc_lock(target_proc); + target_proc->sync_recv = false; + target_proc->async_recv = false; target_proc->is_frozen = true; binder_inner_proc_unlock(target_proc); @@ -4666,6 +4674,33 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info, return ret; } +static int binder_ioctl_get_freezer_info( + struct binder_frozen_status_info *info) +{ + struct binder_proc *target_proc; + bool found = false; + + info->sync_recv = 0; + info->async_recv = 0; + + mutex_lock(&binder_procs_lock); + hlist_for_each_entry(target_proc, &binder_procs, proc_node) { + if (target_proc->pid == info->pid) { + found = true; + binder_inner_proc_lock(target_proc); + info->sync_recv |= target_proc->sync_recv; + info->async_recv |= target_proc->async_recv; + binder_inner_proc_unlock(target_proc); + } + } + mutex_unlock(&binder_procs_lock); + + if (!found) + return -EINVAL; + + return 0; +} + static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; @@ -4844,6 +4879,24 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; break; } + case BINDER_GET_FROZEN_INFO: { + struct binder_frozen_status_info info; + + if (copy_from_user(&info, ubuf, sizeof(info))) { + ret = -EFAULT; + goto err; + } + + ret = binder_ioctl_get_freezer_info(&info); + if (ret < 0) + goto err; + + if (copy_to_user(ubuf, &info, sizeof(info))) { + ret = -EFAULT; + goto err; + } + break; + } default: ret = -EINVAL; goto err; @@ -5154,6 +5207,8 @@ static void binder_deferred_release(struct binder_proc *proc) proc->is_dead = true; proc->is_frozen = false; + proc->sync_recv = false; + proc->async_recv = false; threads = 0; active_transactions = 0; while ((n = rb_first(&proc->threads))) { |