Loading android/GKI_VERSION +1 −1 Original line number Diff line number Diff line LTS_5.4.147_e785a25f5262 LTS_5.4.147_983a7e7c981b drivers/android/binder.c +235 −32 Original line number Diff line number Diff line Loading @@ -1644,6 +1644,12 @@ static void binder_free_transaction(struct binder_transaction *t) if (target_proc) { binder_inner_proc_lock(target_proc); target_proc->outstanding_txns--; if (target_proc->outstanding_txns < 0) pr_warn("%s: Unexpected outstanding_txns %d\n", __func__, target_proc->outstanding_txns); if (!target_proc->outstanding_txns && target_proc->is_frozen) wake_up_interruptible_all(&target_proc->freeze_wait); if (t->buffer) t->buffer->transaction = NULL; binder_inner_proc_unlock(target_proc); Loading Loading @@ -2185,7 +2191,8 @@ static int binder_translate_binder(struct flat_binder_object *fp, ret = -EINVAL; goto done; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { if (security_binder_transfer_binder(binder_get_cred(proc), binder_get_cred(target_proc))) { ret = -EPERM; goto done; } Loading Loading @@ -2231,7 +2238,8 @@ static int binder_translate_handle(struct flat_binder_object *fp, proc->pid, thread->pid, fp->handle); return -EINVAL; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { if (security_binder_transfer_binder(binder_get_cred(proc), binder_get_cred(target_proc))) { ret = -EPERM; goto done; } Loading Loading @@ -2319,7 +2327,8 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, ret = -EBADF; goto err_fget; } ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file); ret = security_binder_transfer_file(binder_get_cred(proc), binder_get_cred(target_proc), file); if (ret < 0) { ret = -EPERM; goto err_security; Loading Loading @@ -2475,10 +2484,11 @@ static int binder_fixup_parent(struct binder_transaction *t, * If the @thread parameter is not NULL, the transaction is always queued * to the waitlist of that specific thread. * * Return: true if the transactions was successfully queued * false if the target process or thread is dead * Return: 0 if the transaction was successfully queued * BR_DEAD_REPLY if the target process or thread is dead * BR_FROZEN_REPLY if the target process or thread is frozen */ static bool binder_proc_transaction(struct binder_transaction *t, static int binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, struct binder_thread *thread) { Loading @@ -2502,11 +2512,16 @@ static bool 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_dead || (thread && thread->is_dead)) { if ((proc->is_frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { binder_inner_proc_unlock(proc); binder_node_unlock(node); return false; return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; } if (!thread && !pending_async) Loading @@ -2525,10 +2540,11 @@ static bool binder_proc_transaction(struct binder_transaction *t, if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); proc->outstanding_txns++; binder_inner_proc_unlock(proc); binder_node_unlock(node); return true; return 0; } /** Loading Loading @@ -2718,8 +2734,8 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_binder; } e->to_node = target_node->debug_id; if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { if (security_binder_transaction(binder_get_cred(proc), binder_get_cred(target_proc)) < 0) { return_error = BR_FAILED_REPLY; return_error_param = -EPERM; return_error_line = __LINE__; Loading Loading @@ -2854,7 +2870,7 @@ static void binder_transaction(struct binder_proc *proc, u32 secid; size_t added_size; security_task_getsecid(proc->tsk, &secid); security_cred_getsecid(binder_get_cred(proc), &secid); ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); if (ret) { return_error = BR_FAILED_REPLY; Loading Loading @@ -3168,12 +3184,14 @@ static void binder_transaction(struct binder_proc *proc, binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); if (target_thread->is_dead) { return_error = BR_DEAD_REPLY; binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction_ilocked(target_thread, in_reply_to); binder_enqueue_thread_work_ilocked(target_thread, &t->work); target_proc->outstanding_txns++; binder_inner_proc_unlock(target_proc); wake_up_interruptible_sync(&target_thread->wait); trace_android_vh_binder_restore_priority(in_reply_to, current); Loading @@ -3194,7 +3212,9 @@ static void binder_transaction(struct binder_proc *proc, t->from_parent = thread->transaction_stack; thread->transaction_stack = t; binder_inner_proc_unlock(proc); if (!binder_proc_transaction(t, target_proc, target_thread)) { return_error = binder_proc_transaction(t, target_proc, target_thread); if (return_error) { binder_inner_proc_lock(proc); binder_pop_transaction_ilocked(thread, t); binder_inner_proc_unlock(proc); Loading @@ -3204,7 +3224,8 @@ static void binder_transaction(struct binder_proc *proc, BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); binder_enqueue_thread_work(thread, tcomplete); if (!binder_proc_transaction(t, target_proc, NULL)) return_error = binder_proc_transaction(t, target_proc, NULL); if (return_error) goto err_dead_proc_or_thread; } if (target_thread) Loading @@ -3221,7 +3242,6 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: return_error = BR_DEAD_REPLY; return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: Loading Loading @@ -3846,7 +3866,7 @@ static int binder_wait_for_work(struct binder_thread *thread, binder_inner_proc_lock(proc); list_del_init(&thread->waiting_thread_node); if (signal_pending(current)) { ret = -ERESTARTSYS; ret = -EINTR; break; } } Loading Loading @@ -4451,9 +4471,14 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) static void binder_free_proc(struct binder_proc *proc) { struct binder_device *device; struct binder_proc_ext *eproc = container_of(proc, struct binder_proc_ext, proc); BUG_ON(!list_empty(&proc->todo)); BUG_ON(!list_empty(&proc->delivered_death)); if (proc->outstanding_txns) pr_warn("%s: Unexpected outstanding_txns %d\n", __func__, proc->outstanding_txns); device = container_of(proc->context, struct binder_device, context); if (refcount_dec_and_test(&device->ref)) { kfree(proc->context->name); Loading @@ -4461,8 +4486,9 @@ static void binder_free_proc(struct binder_proc *proc) } binder_alloc_deferred_release(&proc->alloc); put_task_struct(proc->tsk); put_cred(eproc->cred); binder_stats_deleted(BINDER_STAT_PROC); kfree(proc); kfree(eproc); } static void binder_free_thread(struct binder_thread *thread) Loading Loading @@ -4516,6 +4542,7 @@ static int binder_thread_release(struct binder_proc *proc, (t->to_thread == thread) ? "in" : "out"); if (t->to_thread == thread) { thread->proc->outstanding_txns--; t->to_proc = NULL; t->to_thread = NULL; if (t->buffer) { Loading @@ -4538,23 +4565,20 @@ static int binder_thread_release(struct binder_proc *proc, __release(&t->lock); /* * If this thread used poll, make sure we remove the waitqueue * from any epoll data structures holding it with POLLFREE. * waitqueue_active() is safe to use here because we're holding * the inner lock. * If this thread used poll, make sure we remove the waitqueue from any * poll data structures holding it. */ if ((thread->looper & BINDER_LOOPER_STATE_POLL) && waitqueue_active(&thread->wait)) { wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); } if (thread->looper & BINDER_LOOPER_STATE_POLL) wake_up_pollfree(&thread->wait); binder_inner_proc_unlock(thread->proc); /* * This is needed to avoid races between wake_up_poll() above and * and ep_remove_waitqueue() called for other reasons (eg the epoll file * descriptor being closed); ep_remove_waitqueue() holds an RCU read * lock, so we can be sure it's done after calling synchronize_rcu(). * This is needed to avoid races between wake_up_pollfree() above and * someone else removing the last entry from the queue for other reasons * (e.g. ep_remove_wait_queue() being called due to an epoll file * descriptor being closed). Such other users hold an RCU read lock, so * we can be sure they're done after we call synchronize_rcu(). */ if (thread->looper & BINDER_LOOPER_STATE_POLL) synchronize_rcu(); Loading Loading @@ -4672,7 +4696,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp, ret = -EBUSY; goto out; } ret = security_binder_set_context_mgr(proc->tsk); ret = security_binder_set_context_mgr(binder_get_cred(proc)); if (ret < 0) goto out; if (uid_valid(context->binder_context_mgr_uid)) { Loading Loading @@ -4766,6 +4790,100 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } static bool binder_txns_pending_ilocked(struct binder_proc *proc) { struct rb_node *n; struct binder_thread *thread; if (proc->outstanding_txns > 0) return true; for (n = rb_first(&proc->threads); n; n = rb_next(n)) { thread = rb_entry(n, struct binder_thread, rb_node); if (thread->transaction_stack) return true; } return false; } static int binder_ioctl_freeze(struct binder_freeze_info *info, struct binder_proc *target_proc) { int ret = 0; 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; } /* * Freezing the target. Prevent new transactions by * setting frozen state. If timeout specified, wait * 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); if (info->timeout_ms > 0) ret = wait_event_interruptible_timeout( target_proc->freeze_wait, (!target_proc->outstanding_txns), msecs_to_jiffies(info->timeout_ms)); /* Check pending transactions that wait for reply */ if (ret >= 0) { binder_inner_proc_lock(target_proc); if (binder_txns_pending_ilocked(target_proc)) ret = -EAGAIN; binder_inner_proc_unlock(target_proc); } if (ret < 0) { binder_inner_proc_lock(target_proc); target_proc->is_frozen = false; binder_inner_proc_unlock(target_proc); } return ret; } static int binder_ioctl_get_freezer_info( struct binder_frozen_status_info *info) { struct binder_proc *target_proc; bool found = false; __u32 txns_pending; 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); txns_pending = binder_txns_pending_ilocked(target_proc); info->sync_recv |= target_proc->sync_recv | (txns_pending << 1); 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; Loading Loading @@ -4884,6 +5002,84 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; } case BINDER_FREEZE: { struct binder_freeze_info info; 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) target_procs_count++; } if (target_procs_count == 0) { mutex_unlock(&binder_procs_lock); ret = -EINVAL; goto err; } target_procs = kcalloc(target_procs_count, sizeof(struct binder_proc *), GFP_KERNEL); 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; } 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; Loading @@ -4893,7 +5089,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (thread) thread->looper_need_return = false; wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -ERESTARTSYS) if (ret && ret != -EINTR) pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); err_unlocked: trace_binder_ioctl_done(ret); Loading Loading @@ -4974,6 +5170,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc, *itr; struct binder_proc_ext *eproc; struct binder_device *binder_dev; struct binderfs_info *info; struct dentry *binder_binderfs_dir_entry_proc = NULL; Loading @@ -4982,14 +5179,17 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, current->group_leader->pid, current->pid); proc = kzalloc(sizeof(*proc), GFP_KERNEL); eproc = kzalloc(sizeof(*eproc), GFP_KERNEL); proc = &eproc->proc; if (proc == NULL) return -ENOMEM; spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); proc->tsk = current->group_leader; eproc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->freeze_wait); if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; proc->default_priority.prio = current->normal_prio; Loading Loading @@ -5209,6 +5409,9 @@ static void binder_deferred_release(struct binder_proc *proc) proc->tmp_ref++; 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))) { Loading drivers/android/binder_internal.h +43 −0 Original line number Diff line number Diff line Loading @@ -388,9 +388,24 @@ struct binder_priority { * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform * (protected by binder_deferred_lock) * @outstanding_txns: number of transactions to be transmitted before * processes in freeze_wait are woken up * (protected by @inner_lock) * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up * (protected by @inner_lock) * @is_frozen: process is frozen and unable to service * binder transactions * (protected by @inner_lock) * @sync_recv: process received sync transactions since last frozen * bit 0: received sync transaction after being frozen * bit 1: new pending sync transaction during freezing * (protected by @inner_lock) * @async_recv: process received async transactions since last frozen * (protected by @inner_lock) * @freeze_wait: waitqueue of processes waiting for all outstanding * transactions to be processed * (protected by @inner_lock) * @todo: list of work for this process * (protected by @inner_lock) * @stats: per-process binder statistics Loading Loading @@ -431,7 +446,12 @@ struct binder_proc { struct task_struct *tsk; struct hlist_node deferred_work_node; int deferred_work; int outstanding_txns; bool is_dead; bool is_frozen; bool sync_recv; bool async_recv; wait_queue_head_t freeze_wait; struct list_head todo; struct binder_stats stats; Loading @@ -449,6 +469,29 @@ struct binder_proc { struct dentry *binderfs_entry; }; /** * struct binder_proc_ext - binder process bookkeeping * @proc: element for binder_procs list * @cred struct cred associated with the `struct file` * in binder_open() * (invariant after initialized) * * Extended binder_proc -- needed to add the "cred" field without * changing the KMI for binder_proc. */ struct binder_proc_ext { struct binder_proc proc; const struct cred *cred; }; static inline const struct cred *binder_get_cred(struct binder_proc *proc) { struct binder_proc_ext *eproc; eproc = container_of(proc, struct binder_proc_ext, proc); return eproc->cred; } /** * struct binder_thread - binder thread bookkeeping * @proc: binder process for this thread Loading drivers/hid/Kconfig +5 −5 Original line number Diff line number Diff line Loading @@ -206,14 +206,14 @@ config HID_CHERRY config HID_CHICONY tristate "Chicony devices" depends on HID depends on USB_HID default !EXPERT ---help--- Support for Chicony Tactical pad and special keys on Chicony keyboards. config HID_CORSAIR tristate "Corsair devices" depends on HID && USB && LEDS_CLASS depends on USB_HID && LEDS_CLASS ---help--- Support for Corsair devices that are not fully compliant with the HID standard. Loading Loading @@ -244,7 +244,7 @@ config HID_MACALLY config HID_PRODIKEYS tristate "Prodikeys PC-MIDI Keyboard support" depends on HID && SND depends on USB_HID && SND select SND_RAWMIDI ---help--- Support for Prodikeys PC-MIDI Keyboard device support. Loading Loading @@ -524,7 +524,7 @@ config HID_LENOVO config HID_LOGITECH tristate "Logitech devices" depends on HID depends on USB_HID default !EXPERT ---help--- Support for Logitech devices that are not fully compliant with HID standard. Loading Loading @@ -900,7 +900,7 @@ config HID_SAITEK config HID_SAMSUNG tristate "Samsung InfraRed remote control or keyboards" depends on HID depends on USB_HID ---help--- Support for Samsung InfraRed remote control or keyboards. Loading drivers/hid/hid-asus.c +1 −1 Original line number Diff line number Diff line Loading @@ -849,7 +849,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) if (drvdata->quirks & QUIRK_IS_MULTITOUCH) drvdata->tp = &asus_i2c_tp; if (drvdata->quirks & QUIRK_T100_KEYBOARD) { if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { Loading Loading
android/GKI_VERSION +1 −1 Original line number Diff line number Diff line LTS_5.4.147_e785a25f5262 LTS_5.4.147_983a7e7c981b
drivers/android/binder.c +235 −32 Original line number Diff line number Diff line Loading @@ -1644,6 +1644,12 @@ static void binder_free_transaction(struct binder_transaction *t) if (target_proc) { binder_inner_proc_lock(target_proc); target_proc->outstanding_txns--; if (target_proc->outstanding_txns < 0) pr_warn("%s: Unexpected outstanding_txns %d\n", __func__, target_proc->outstanding_txns); if (!target_proc->outstanding_txns && target_proc->is_frozen) wake_up_interruptible_all(&target_proc->freeze_wait); if (t->buffer) t->buffer->transaction = NULL; binder_inner_proc_unlock(target_proc); Loading Loading @@ -2185,7 +2191,8 @@ static int binder_translate_binder(struct flat_binder_object *fp, ret = -EINVAL; goto done; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { if (security_binder_transfer_binder(binder_get_cred(proc), binder_get_cred(target_proc))) { ret = -EPERM; goto done; } Loading Loading @@ -2231,7 +2238,8 @@ static int binder_translate_handle(struct flat_binder_object *fp, proc->pid, thread->pid, fp->handle); return -EINVAL; } if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { if (security_binder_transfer_binder(binder_get_cred(proc), binder_get_cred(target_proc))) { ret = -EPERM; goto done; } Loading Loading @@ -2319,7 +2327,8 @@ static int binder_translate_fd(u32 fd, binder_size_t fd_offset, ret = -EBADF; goto err_fget; } ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file); ret = security_binder_transfer_file(binder_get_cred(proc), binder_get_cred(target_proc), file); if (ret < 0) { ret = -EPERM; goto err_security; Loading Loading @@ -2475,10 +2484,11 @@ static int binder_fixup_parent(struct binder_transaction *t, * If the @thread parameter is not NULL, the transaction is always queued * to the waitlist of that specific thread. * * Return: true if the transactions was successfully queued * false if the target process or thread is dead * Return: 0 if the transaction was successfully queued * BR_DEAD_REPLY if the target process or thread is dead * BR_FROZEN_REPLY if the target process or thread is frozen */ static bool binder_proc_transaction(struct binder_transaction *t, static int binder_proc_transaction(struct binder_transaction *t, struct binder_proc *proc, struct binder_thread *thread) { Loading @@ -2502,11 +2512,16 @@ static bool 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_dead || (thread && thread->is_dead)) { if ((proc->is_frozen && !oneway) || proc->is_dead || (thread && thread->is_dead)) { binder_inner_proc_unlock(proc); binder_node_unlock(node); return false; return proc->is_frozen ? BR_FROZEN_REPLY : BR_DEAD_REPLY; } if (!thread && !pending_async) Loading @@ -2525,10 +2540,11 @@ static bool binder_proc_transaction(struct binder_transaction *t, if (!pending_async) binder_wakeup_thread_ilocked(proc, thread, !oneway /* sync */); proc->outstanding_txns++; binder_inner_proc_unlock(proc); binder_node_unlock(node); return true; return 0; } /** Loading Loading @@ -2718,8 +2734,8 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_binder; } e->to_node = target_node->debug_id; if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { if (security_binder_transaction(binder_get_cred(proc), binder_get_cred(target_proc)) < 0) { return_error = BR_FAILED_REPLY; return_error_param = -EPERM; return_error_line = __LINE__; Loading Loading @@ -2854,7 +2870,7 @@ static void binder_transaction(struct binder_proc *proc, u32 secid; size_t added_size; security_task_getsecid(proc->tsk, &secid); security_cred_getsecid(binder_get_cred(proc), &secid); ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); if (ret) { return_error = BR_FAILED_REPLY; Loading Loading @@ -3168,12 +3184,14 @@ static void binder_transaction(struct binder_proc *proc, binder_enqueue_thread_work(thread, tcomplete); binder_inner_proc_lock(target_proc); if (target_thread->is_dead) { return_error = BR_DEAD_REPLY; binder_inner_proc_unlock(target_proc); goto err_dead_proc_or_thread; } BUG_ON(t->buffer->async_transaction != 0); binder_pop_transaction_ilocked(target_thread, in_reply_to); binder_enqueue_thread_work_ilocked(target_thread, &t->work); target_proc->outstanding_txns++; binder_inner_proc_unlock(target_proc); wake_up_interruptible_sync(&target_thread->wait); trace_android_vh_binder_restore_priority(in_reply_to, current); Loading @@ -3194,7 +3212,9 @@ static void binder_transaction(struct binder_proc *proc, t->from_parent = thread->transaction_stack; thread->transaction_stack = t; binder_inner_proc_unlock(proc); if (!binder_proc_transaction(t, target_proc, target_thread)) { return_error = binder_proc_transaction(t, target_proc, target_thread); if (return_error) { binder_inner_proc_lock(proc); binder_pop_transaction_ilocked(thread, t); binder_inner_proc_unlock(proc); Loading @@ -3204,7 +3224,8 @@ static void binder_transaction(struct binder_proc *proc, BUG_ON(target_node == NULL); BUG_ON(t->buffer->async_transaction != 1); binder_enqueue_thread_work(thread, tcomplete); if (!binder_proc_transaction(t, target_proc, NULL)) return_error = binder_proc_transaction(t, target_proc, NULL); if (return_error) goto err_dead_proc_or_thread; } if (target_thread) Loading @@ -3221,7 +3242,6 @@ static void binder_transaction(struct binder_proc *proc, return; err_dead_proc_or_thread: return_error = BR_DEAD_REPLY; return_error_line = __LINE__; binder_dequeue_work(proc, tcomplete); err_translate_failed: Loading Loading @@ -3846,7 +3866,7 @@ static int binder_wait_for_work(struct binder_thread *thread, binder_inner_proc_lock(proc); list_del_init(&thread->waiting_thread_node); if (signal_pending(current)) { ret = -ERESTARTSYS; ret = -EINTR; break; } } Loading Loading @@ -4451,9 +4471,14 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) static void binder_free_proc(struct binder_proc *proc) { struct binder_device *device; struct binder_proc_ext *eproc = container_of(proc, struct binder_proc_ext, proc); BUG_ON(!list_empty(&proc->todo)); BUG_ON(!list_empty(&proc->delivered_death)); if (proc->outstanding_txns) pr_warn("%s: Unexpected outstanding_txns %d\n", __func__, proc->outstanding_txns); device = container_of(proc->context, struct binder_device, context); if (refcount_dec_and_test(&device->ref)) { kfree(proc->context->name); Loading @@ -4461,8 +4486,9 @@ static void binder_free_proc(struct binder_proc *proc) } binder_alloc_deferred_release(&proc->alloc); put_task_struct(proc->tsk); put_cred(eproc->cred); binder_stats_deleted(BINDER_STAT_PROC); kfree(proc); kfree(eproc); } static void binder_free_thread(struct binder_thread *thread) Loading Loading @@ -4516,6 +4542,7 @@ static int binder_thread_release(struct binder_proc *proc, (t->to_thread == thread) ? "in" : "out"); if (t->to_thread == thread) { thread->proc->outstanding_txns--; t->to_proc = NULL; t->to_thread = NULL; if (t->buffer) { Loading @@ -4538,23 +4565,20 @@ static int binder_thread_release(struct binder_proc *proc, __release(&t->lock); /* * If this thread used poll, make sure we remove the waitqueue * from any epoll data structures holding it with POLLFREE. * waitqueue_active() is safe to use here because we're holding * the inner lock. * If this thread used poll, make sure we remove the waitqueue from any * poll data structures holding it. */ if ((thread->looper & BINDER_LOOPER_STATE_POLL) && waitqueue_active(&thread->wait)) { wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); } if (thread->looper & BINDER_LOOPER_STATE_POLL) wake_up_pollfree(&thread->wait); binder_inner_proc_unlock(thread->proc); /* * This is needed to avoid races between wake_up_poll() above and * and ep_remove_waitqueue() called for other reasons (eg the epoll file * descriptor being closed); ep_remove_waitqueue() holds an RCU read * lock, so we can be sure it's done after calling synchronize_rcu(). * This is needed to avoid races between wake_up_pollfree() above and * someone else removing the last entry from the queue for other reasons * (e.g. ep_remove_wait_queue() being called due to an epoll file * descriptor being closed). Such other users hold an RCU read lock, so * we can be sure they're done after we call synchronize_rcu(). */ if (thread->looper & BINDER_LOOPER_STATE_POLL) synchronize_rcu(); Loading Loading @@ -4672,7 +4696,7 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp, ret = -EBUSY; goto out; } ret = security_binder_set_context_mgr(proc->tsk); ret = security_binder_set_context_mgr(binder_get_cred(proc)); if (ret < 0) goto out; if (uid_valid(context->binder_context_mgr_uid)) { Loading Loading @@ -4766,6 +4790,100 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc, return 0; } static bool binder_txns_pending_ilocked(struct binder_proc *proc) { struct rb_node *n; struct binder_thread *thread; if (proc->outstanding_txns > 0) return true; for (n = rb_first(&proc->threads); n; n = rb_next(n)) { thread = rb_entry(n, struct binder_thread, rb_node); if (thread->transaction_stack) return true; } return false; } static int binder_ioctl_freeze(struct binder_freeze_info *info, struct binder_proc *target_proc) { int ret = 0; 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; } /* * Freezing the target. Prevent new transactions by * setting frozen state. If timeout specified, wait * 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); if (info->timeout_ms > 0) ret = wait_event_interruptible_timeout( target_proc->freeze_wait, (!target_proc->outstanding_txns), msecs_to_jiffies(info->timeout_ms)); /* Check pending transactions that wait for reply */ if (ret >= 0) { binder_inner_proc_lock(target_proc); if (binder_txns_pending_ilocked(target_proc)) ret = -EAGAIN; binder_inner_proc_unlock(target_proc); } if (ret < 0) { binder_inner_proc_lock(target_proc); target_proc->is_frozen = false; binder_inner_proc_unlock(target_proc); } return ret; } static int binder_ioctl_get_freezer_info( struct binder_frozen_status_info *info) { struct binder_proc *target_proc; bool found = false; __u32 txns_pending; 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); txns_pending = binder_txns_pending_ilocked(target_proc); info->sync_recv |= target_proc->sync_recv | (txns_pending << 1); 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; Loading Loading @@ -4884,6 +5002,84 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; } case BINDER_FREEZE: { struct binder_freeze_info info; 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) target_procs_count++; } if (target_procs_count == 0) { mutex_unlock(&binder_procs_lock); ret = -EINVAL; goto err; } target_procs = kcalloc(target_procs_count, sizeof(struct binder_proc *), GFP_KERNEL); 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; } 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; Loading @@ -4893,7 +5089,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (thread) thread->looper_need_return = false; wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); if (ret && ret != -ERESTARTSYS) if (ret && ret != -EINTR) pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); err_unlocked: trace_binder_ioctl_done(ret); Loading Loading @@ -4974,6 +5170,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc, *itr; struct binder_proc_ext *eproc; struct binder_device *binder_dev; struct binderfs_info *info; struct dentry *binder_binderfs_dir_entry_proc = NULL; Loading @@ -4982,14 +5179,17 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, current->group_leader->pid, current->pid); proc = kzalloc(sizeof(*proc), GFP_KERNEL); eproc = kzalloc(sizeof(*eproc), GFP_KERNEL); proc = &eproc->proc; if (proc == NULL) return -ENOMEM; spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); get_task_struct(current->group_leader); proc->tsk = current->group_leader; eproc->cred = get_cred(filp->f_cred); INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->freeze_wait); if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; proc->default_priority.prio = current->normal_prio; Loading Loading @@ -5209,6 +5409,9 @@ static void binder_deferred_release(struct binder_proc *proc) proc->tmp_ref++; 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))) { Loading
drivers/android/binder_internal.h +43 −0 Original line number Diff line number Diff line Loading @@ -388,9 +388,24 @@ struct binder_priority { * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform * (protected by binder_deferred_lock) * @outstanding_txns: number of transactions to be transmitted before * processes in freeze_wait are woken up * (protected by @inner_lock) * @is_dead: process is dead and awaiting free * when outstanding transactions are cleaned up * (protected by @inner_lock) * @is_frozen: process is frozen and unable to service * binder transactions * (protected by @inner_lock) * @sync_recv: process received sync transactions since last frozen * bit 0: received sync transaction after being frozen * bit 1: new pending sync transaction during freezing * (protected by @inner_lock) * @async_recv: process received async transactions since last frozen * (protected by @inner_lock) * @freeze_wait: waitqueue of processes waiting for all outstanding * transactions to be processed * (protected by @inner_lock) * @todo: list of work for this process * (protected by @inner_lock) * @stats: per-process binder statistics Loading Loading @@ -431,7 +446,12 @@ struct binder_proc { struct task_struct *tsk; struct hlist_node deferred_work_node; int deferred_work; int outstanding_txns; bool is_dead; bool is_frozen; bool sync_recv; bool async_recv; wait_queue_head_t freeze_wait; struct list_head todo; struct binder_stats stats; Loading @@ -449,6 +469,29 @@ struct binder_proc { struct dentry *binderfs_entry; }; /** * struct binder_proc_ext - binder process bookkeeping * @proc: element for binder_procs list * @cred struct cred associated with the `struct file` * in binder_open() * (invariant after initialized) * * Extended binder_proc -- needed to add the "cred" field without * changing the KMI for binder_proc. */ struct binder_proc_ext { struct binder_proc proc; const struct cred *cred; }; static inline const struct cred *binder_get_cred(struct binder_proc *proc) { struct binder_proc_ext *eproc; eproc = container_of(proc, struct binder_proc_ext, proc); return eproc->cred; } /** * struct binder_thread - binder thread bookkeeping * @proc: binder process for this thread Loading
drivers/hid/Kconfig +5 −5 Original line number Diff line number Diff line Loading @@ -206,14 +206,14 @@ config HID_CHERRY config HID_CHICONY tristate "Chicony devices" depends on HID depends on USB_HID default !EXPERT ---help--- Support for Chicony Tactical pad and special keys on Chicony keyboards. config HID_CORSAIR tristate "Corsair devices" depends on HID && USB && LEDS_CLASS depends on USB_HID && LEDS_CLASS ---help--- Support for Corsair devices that are not fully compliant with the HID standard. Loading Loading @@ -244,7 +244,7 @@ config HID_MACALLY config HID_PRODIKEYS tristate "Prodikeys PC-MIDI Keyboard support" depends on HID && SND depends on USB_HID && SND select SND_RAWMIDI ---help--- Support for Prodikeys PC-MIDI Keyboard device support. Loading Loading @@ -524,7 +524,7 @@ config HID_LENOVO config HID_LOGITECH tristate "Logitech devices" depends on HID depends on USB_HID default !EXPERT ---help--- Support for Logitech devices that are not fully compliant with HID standard. Loading Loading @@ -900,7 +900,7 @@ config HID_SAITEK config HID_SAMSUNG tristate "Samsung InfraRed remote control or keyboards" depends on HID depends on USB_HID ---help--- Support for Samsung InfraRed remote control or keyboards. Loading
drivers/hid/hid-asus.c +1 −1 Original line number Diff line number Diff line Loading @@ -849,7 +849,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) if (drvdata->quirks & QUIRK_IS_MULTITOUCH) drvdata->tp = &asus_i2c_tp; if (drvdata->quirks & QUIRK_T100_KEYBOARD) { if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { Loading