1. 27 7月, 2023 1 次提交
    • C
      binder: fix UAF caused by faulty buffer cleanup · 83bfcd1e
      Carlos Llamas 提交于
      stable inclusion
      from stable-v5.10.182
      commit 2218752325a98861dfb10f59a9b0270d6d4abe21
      category: bugfix
      bugzilla: https://gitee.com/src-openeuler/kernel/issues/I7L0Z9
      CVE: CVE-2023-21255
      
      Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2218752325a98861dfb10f59a9b0270d6d4abe21
      
      --------------------------------
      
      commit bdc1c5fa upstream.
      
      In binder_transaction_buffer_release() the 'failed_at' offset indicates
      the number of objects to clean up. However, this function was changed by
      commit 44d8047f ("binder: use standard functions to allocate fds"),
      to release all the objects in the buffer when 'failed_at' is zero.
      
      This introduced an issue when a transaction buffer is released without
      any objects having been processed so far. In this case, 'failed_at' is
      indeed zero yet it is misinterpreted as releasing the entire buffer.
      
      This leads to use-after-free errors where nodes are incorrectly freed
      and subsequently accessed. Such is the case in the following KASAN
      report:
      
        ==================================================================
        BUG: KASAN: slab-use-after-free in binder_thread_read+0xc40/0x1f30
        Read of size 8 at addr ffff4faf037cfc58 by task poc/474
      
        CPU: 6 PID: 474 Comm: poc Not tainted 6.3.0-12570-g7df047b3 #5
        Hardware name: linux,dummy-virt (DT)
        Call trace:
         dump_backtrace+0x94/0xec
         show_stack+0x18/0x24
         dump_stack_lvl+0x48/0x60
         print_report+0xf8/0x5b8
         kasan_report+0xb8/0xfc
         __asan_load8+0x9c/0xb8
         binder_thread_read+0xc40/0x1f30
         binder_ioctl+0xd9c/0x1768
         __arm64_sys_ioctl+0xd4/0x118
         invoke_syscall+0x60/0x188
        [...]
      
        Allocated by task 474:
         kasan_save_stack+0x3c/0x64
         kasan_set_track+0x2c/0x40
         kasan_save_alloc_info+0x24/0x34
         __kasan_kmalloc+0xb8/0xbc
         kmalloc_trace+0x48/0x5c
         binder_new_node+0x3c/0x3a4
         binder_transaction+0x2b58/0x36f0
         binder_thread_write+0x8e0/0x1b78
         binder_ioctl+0x14a0/0x1768
         __arm64_sys_ioctl+0xd4/0x118
         invoke_syscall+0x60/0x188
        [...]
      
        Freed by task 475:
         kasan_save_stack+0x3c/0x64
         kasan_set_track+0x2c/0x40
         kasan_save_free_info+0x38/0x5c
         __kasan_slab_free+0xe8/0x154
         __kmem_cache_free+0x128/0x2bc
         kfree+0x58/0x70
         binder_dec_node_tmpref+0x178/0x1fc
         binder_transaction_buffer_release+0x430/0x628
         binder_transaction+0x1954/0x36f0
         binder_thread_write+0x8e0/0x1b78
         binder_ioctl+0x14a0/0x1768
         __arm64_sys_ioctl+0xd4/0x118
         invoke_syscall+0x60/0x188
        [...]
        ==================================================================
      
      In order to avoid these issues, let's always calculate the intended
      'failed_at' offset beforehand. This is renamed and wrapped in a helper
      function to make it clear and convenient.
      
      Fixes: 32e9f56a ("binder: don't detect sender/target during buffer cleanup")
      Reported-by: NZi Fan Tan <zifantan@google.com>
      Cc: stable@vger.kernel.org
      Signed-off-by: NCarlos Llamas <cmllamas@google.com>
      Acked-by: NTodd Kjos <tkjos@google.com>
      Link: https://lore.kernel.org/r/20230505203020.4101154-1-cmllamas@google.com
      [cmllamas: resolve trivial conflict due to missing commit 9864bb48]
      Signed-off-by: NCarlos Llamas <cmllamas@google.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      Signed-off-by: NWang Hai <wanghai38@huawei.com>
      Signed-off-by: NLonglong Xia <xialonglong1@huawei.com>
      83bfcd1e
  2. 28 2月, 2023 7 次提交
  3. 19 1月, 2023 1 次提交
  4. 19 10月, 2022 1 次提交
  5. 27 4月, 2022 1 次提交
  6. 14 1月, 2022 2 次提交
  7. 06 12月, 2021 3 次提交
  8. 30 11月, 2021 1 次提交
  9. 15 11月, 2021 1 次提交
  10. 12 1月, 2021 1 次提交
  11. 18 10月, 2020 1 次提交
    • J
      task_work: cleanup notification modes · 91989c70
      Jens Axboe 提交于
      A previous commit changed the notification mode from true/false to an
      int, allowing notify-no, notify-yes, or signal-notify. This was
      backwards compatible in the sense that any existing true/false user
      would translate to either 0 (on notification sent) or 1, the latter
      which mapped to TWA_RESUME. TWA_SIGNAL was assigned a value of 2.
      
      Clean this up properly, and define a proper enum for the notification
      mode. Now we have:
      
      - TWA_NONE. This is 0, same as before the original change, meaning no
        notification requested.
      - TWA_RESUME. This is 1, same as before the original change, meaning
        that we use TIF_NOTIFY_RESUME.
      - TWA_SIGNAL. This uses TIF_SIGPENDING/JOBCTL_TASK_WORK for the
        notification.
      
      Clean up all the callers, switching their 0/1/false/true to using the
      appropriate TWA_* mode for notifications.
      
      Fixes: e91b4816 ("task_work: teach task_work_add() to do signal_wake_up()")
      Reviewed-by: NThomas Gleixner <tglx@linutronix.de>
      Signed-off-by: NJens Axboe <axboe@kernel.dk>
      91989c70
  12. 10 10月, 2020 1 次提交
    • T
      binder: fix UAF when releasing todo list · f3277cbf
      Todd Kjos 提交于
      When releasing a thread todo list when tearing down
      a binder_proc, the following race was possible which
      could result in a use-after-free:
      
      1.  Thread 1: enter binder_release_work from binder_thread_release
      2.  Thread 2: binder_update_ref_for_handle() -> binder_dec_node_ilocked()
      3.  Thread 2: dec nodeA --> 0 (will free node)
      4.  Thread 1: ACQ inner_proc_lock
      5.  Thread 2: block on inner_proc_lock
      6.  Thread 1: dequeue work (BINDER_WORK_NODE, part of nodeA)
      7.  Thread 1: REL inner_proc_lock
      8.  Thread 2: ACQ inner_proc_lock
      9.  Thread 2: todo list cleanup, but work was already dequeued
      10. Thread 2: free node
      11. Thread 2: REL inner_proc_lock
      12. Thread 1: deref w->type (UAF)
      
      The problem was that for a BINDER_WORK_NODE, the binder_work element
      must not be accessed after releasing the inner_proc_lock while
      processing the todo list elements since another thread might be
      handling a deref on the node containing the binder_work element
      leading to the node being freed.
      Signed-off-by: NTodd Kjos <tkjos@google.com>
      Link: https://lore.kernel.org/r/20201009232455.4054810-1-tkjos@google.com
      Cc: <stable@vger.kernel.org> # 4.14, 4.19, 5.4, 5.8
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      f3277cbf
  13. 05 10月, 2020 1 次提交
  14. 04 9月, 2020 2 次提交
  15. 29 7月, 2020 3 次提交
  16. 23 6月, 2020 1 次提交
    • T
      binder: fix null deref of proc->context · d35d3660
      Todd Kjos 提交于
      The binder driver makes the assumption proc->context pointer is invariant after
      initialization (as documented in the kerneldoc header for struct proc).
      However, in commit f0fe2c0f ("binder: prevent UAF for binderfs devices II")
      proc->context is set to NULL during binder_deferred_release().
      
      Another proc was in the middle of setting up a transaction to the dying
      process and crashed on a NULL pointer deref on "context" which is a local
      set to &proc->context:
      
          new_ref->data.desc = (node == context->binder_context_mgr_node) ? 0 : 1;
      
      Here's the stack:
      
      [ 5237.855435] Call trace:
      [ 5237.855441] binder_get_ref_for_node_olocked+0x100/0x2ec
      [ 5237.855446] binder_inc_ref_for_node+0x140/0x280
      [ 5237.855451] binder_translate_binder+0x1d0/0x388
      [ 5237.855456] binder_transaction+0x2228/0x3730
      [ 5237.855461] binder_thread_write+0x640/0x25bc
      [ 5237.855466] binder_ioctl_write_read+0xb0/0x464
      [ 5237.855471] binder_ioctl+0x30c/0x96c
      [ 5237.855477] do_vfs_ioctl+0x3e0/0x700
      [ 5237.855482] __arm64_sys_ioctl+0x78/0xa4
      [ 5237.855488] el0_svc_common+0xb4/0x194
      [ 5237.855493] el0_svc_handler+0x74/0x98
      [ 5237.855497] el0_svc+0x8/0xc
      
      The fix is to move the kfree of the binder_device to binder_free_proc()
      so the binder_device is freed when we know there are no references
      remaining on the binder_proc.
      
      Fixes: f0fe2c0f ("binder: prevent UAF for binderfs devices II")
      Acked-by: NChristian Brauner <christian.brauner@ubuntu.com>
      Signed-off-by: NTodd Kjos <tkjos@google.com>
      Cc: stable <stable@vger.kernel.org>
      Link: https://lore.kernel.org/r/20200622200715.114382-1-tkjos@google.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      d35d3660
  17. 04 3月, 2020 1 次提交
    • C
      binder: prevent UAF for binderfs devices II · f0fe2c0f
      Christian Brauner 提交于
      This is a necessary follow up to the first fix I proposed and we merged
      in 2669b8b0 ("binder: prevent UAF for binderfs devices"). I have been
      overly optimistic that the simple fix I proposed would work. But alas,
      ihold() + iput() won't work since the inodes won't survive the
      destruction of the superblock.
      So all we get with my prior fix is a different race with a tinier
      race-window but it doesn't solve the issue. Fwiw, the problem lies with
      generic_shutdown_super(). It even has this cozy Al-style comment:
      
                if (!list_empty(&sb->s_inodes)) {
                        printk("VFS: Busy inodes after unmount of %s. "
                           "Self-destruct in 5 seconds.  Have a nice day...\n",
                           sb->s_id);
                }
      
      On binder_release(), binder_defer_work(proc, BINDER_DEFERRED_RELEASE) is
      called which punts the actual cleanup operation to a workqueue. At some
      point, binder_deferred_func() will be called which will end up calling
      binder_deferred_release() which will retrieve and cleanup the
      binder_context attach to this struct binder_proc.
      
      If we trace back where this binder_context is attached to binder_proc we
      see that it is set in binder_open() and is taken from the struct
      binder_device it is associated with. This obviously assumes that the
      struct binder_device that context is attached to is _never_ freed. While
      that might be true for devtmpfs binder devices it is most certainly
      wrong for binderfs binder devices.
      
      So, assume binder_open() is called on a binderfs binder devices. We now
      stash away the struct binder_context associated with that struct
      binder_devices:
      	proc->context = &binder_dev->context;
      	/* binderfs stashes devices in i_private */
      	if (is_binderfs_device(nodp)) {
      		binder_dev = nodp->i_private;
      		info = nodp->i_sb->s_fs_info;
      		binder_binderfs_dir_entry_proc = info->proc_log_dir;
      	} else {
      	.
      	.
      	.
      	proc->context = &binder_dev->context;
      
      Now let's assume that the binderfs instance for that binder devices is
      shutdown via umount() and/or the mount namespace associated with it goes
      away. As long as there is still an fd open for that binderfs binder
      device things are fine. But let's assume we now close the last fd for
      that binderfs binder device. Now binder_release() is called and punts to
      the workqueue. Assume that the workqueue has quite a bit of stuff to do
      and doesn't get to cleaning up the struct binder_proc and the associated
      struct binder_context with it for that binderfs binder device right
      away. In the meantime, the VFS is killing the super block and is
      ultimately calling sb->evict_inode() which means it will call
      binderfs_evict_inode() which does:
      
      static void binderfs_evict_inode(struct inode *inode)
      {
      	struct binder_device *device = inode->i_private;
      	struct binderfs_info *info = BINDERFS_I(inode);
      
      	clear_inode(inode);
      
      	if (!S_ISCHR(inode->i_mode) || !device)
      		return;
      
      	mutex_lock(&binderfs_minors_mutex);
      	--info->device_count;
      	ida_free(&binderfs_minors, device->miscdev.minor);
      	mutex_unlock(&binderfs_minors_mutex);
      
      	kfree(device->context.name);
      	kfree(device);
      }
      
      thereby freeing the struct binder_device including struct
      binder_context.
      
      Now the workqueue finally has time to get around to cleaning up struct
      binder_proc and is now trying to access the associate struct
      binder_context. Since it's already freed it will OOPs.
      
      Fix this by introducing a refounct on binder devices.
      
      This is an alternative fix to 51d8a7ec ("binder: prevent UAF read in
      print_binder_transaction_log_entry()").
      
      Fixes: 3ad20fe3 ("binder: implement binderfs")
      Fixes: 2669b8b0 ("binder: prevent UAF for binderfs devices")
      Fixes: 03e2e07e ("binder: Make transaction_log available in binderfs")
      Related : 51d8a7ec ("binder: prevent UAF read in print_binder_transaction_log_entry()")
      Cc: stable@vger.kernel.org
      Signed-off-by: NChristian Brauner <christian.brauner@ubuntu.com>
      Acked-by: NTodd Kjos <tkjos@google.com>
      Link: https://lore.kernel.org/r/20200303164340.670054-1-christian.brauner@ubuntu.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      f0fe2c0f
  18. 03 3月, 2020 1 次提交
    • C
      binder: prevent UAF for binderfs devices · 2669b8b0
      Christian Brauner 提交于
      On binder_release(), binder_defer_work(proc, BINDER_DEFERRED_RELEASE) is
      called which punts the actual cleanup operation to a workqueue. At some
      point, binder_deferred_func() will be called which will end up calling
      binder_deferred_release() which will retrieve and cleanup the
      binder_context attach to this struct binder_proc.
      
      If we trace back where this binder_context is attached to binder_proc we
      see that it is set in binder_open() and is taken from the struct
      binder_device it is associated with. This obviously assumes that the
      struct binder_device that context is attached to is _never_ freed. While
      that might be true for devtmpfs binder devices it is most certainly
      wrong for binderfs binder devices.
      
      So, assume binder_open() is called on a binderfs binder devices. We now
      stash away the struct binder_context associated with that struct
      binder_devices:
      	proc->context = &binder_dev->context;
      	/* binderfs stashes devices in i_private */
      	if (is_binderfs_device(nodp)) {
      		binder_dev = nodp->i_private;
      		info = nodp->i_sb->s_fs_info;
      		binder_binderfs_dir_entry_proc = info->proc_log_dir;
      	} else {
      	.
      	.
      	.
      	proc->context = &binder_dev->context;
      
      Now let's assume that the binderfs instance for that binder devices is
      shutdown via umount() and/or the mount namespace associated with it goes
      away. As long as there is still an fd open for that binderfs binder
      device things are fine. But let's assume we now close the last fd for
      that binderfs binder device. Now binder_release() is called and punts to
      the workqueue. Assume that the workqueue has quite a bit of stuff to do
      and doesn't get to cleaning up the struct binder_proc and the associated
      struct binder_context with it for that binderfs binder device right
      away. In the meantime, the VFS is killing the super block and is
      ultimately calling sb->evict_inode() which means it will call
      binderfs_evict_inode() which does:
      
      static void binderfs_evict_inode(struct inode *inode)
      {
      	struct binder_device *device = inode->i_private;
      	struct binderfs_info *info = BINDERFS_I(inode);
      
      	clear_inode(inode);
      
      	if (!S_ISCHR(inode->i_mode) || !device)
      		return;
      
      	mutex_lock(&binderfs_minors_mutex);
      	--info->device_count;
      	ida_free(&binderfs_minors, device->miscdev.minor);
      	mutex_unlock(&binderfs_minors_mutex);
      
      	kfree(device->context.name);
      	kfree(device);
      }
      
      thereby freeing the struct binder_device including struct
      binder_context.
      
      Now the workqueue finally has time to get around to cleaning up struct
      binder_proc and is now trying to access the associate struct
      binder_context. Since it's already freed it will OOPs.
      
      Fix this by holding an additional reference to the inode that is only
      released once the workqueue is done cleaning up struct binder_proc. This
      is an easy alternative to introducing separate refcounting on struct
      binder_device which we can always do later if it becomes necessary.
      
      This is an alternative fix to 51d8a7ec ("binder: prevent UAF read in
      print_binder_transaction_log_entry()").
      
      Fixes: 3ad20fe3 ("binder: implement binderfs")
      Fixes: 03e2e07e ("binder: Make transaction_log available in binderfs")
      Related : 51d8a7ec ("binder: prevent UAF read in print_binder_transaction_log_entry()")
      Cc: stable@vger.kernel.org
      Signed-off-by: NChristian Brauner <christian.brauner@ubuntu.com>
      Acked-by: NTodd Kjos <tkjos@google.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      2669b8b0
  19. 22 1月, 2020 1 次提交
  20. 21 1月, 2020 1 次提交
  21. 14 12月, 2019 1 次提交
  22. 23 10月, 2019 1 次提交
  23. 17 10月, 2019 2 次提交
  24. 10 10月, 2019 1 次提交
  25. 04 9月, 2019 3 次提交