From 0a83330df989874b861ac4a0b6b8e64c9331627a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 4 Apr 2021 22:09:54 -0400 Subject: [PATCH] Fixes for 4.4 Signed-off-by: Sasha Levin --- ...rror-handling-in-extcon_dev_register.patch | 35 ++++++ ...x-a-use-after-free-bug-in-nosy_ioctl.patch | 119 ++++++++++++++++++ queue-4.4/series | 2 + 3 files changed, 156 insertions(+) create mode 100644 queue-4.4/extcon-fix-error-handling-in-extcon_dev_register.patch create mode 100644 queue-4.4/firewire-nosy-fix-a-use-after-free-bug-in-nosy_ioctl.patch diff --git a/queue-4.4/extcon-fix-error-handling-in-extcon_dev_register.patch b/queue-4.4/extcon-fix-error-handling-in-extcon_dev_register.patch new file mode 100644 index 00000000000..4f2ce40bff3 --- /dev/null +++ b/queue-4.4/extcon-fix-error-handling-in-extcon_dev_register.patch @@ -0,0 +1,35 @@ +From 814b69be1649bd26b9eaf3f1ffeb46e116c9f3ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jan 2021 16:10:55 +0800 +Subject: extcon: Fix error handling in extcon_dev_register + +From: Dinghao Liu + +[ Upstream commit d3bdd1c3140724967ca4136755538fa7c05c2b4e ] + +When devm_kcalloc() fails, we should execute device_unregister() +to unregister edev->dev from system. + +Fixes: 046050f6e623e ("extcon: Update the prototype of extcon_register_notifier() with enum extcon") +Signed-off-by: Dinghao Liu +Signed-off-by: Chanwoo Choi +Signed-off-by: Sasha Levin +--- + drivers/extcon/extcon.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c +index 21a123cadf78..e7fef10bd12c 100644 +--- a/drivers/extcon/extcon.c ++++ b/drivers/extcon/extcon.c +@@ -932,6 +932,7 @@ int extcon_dev_register(struct extcon_dev *edev) + sizeof(*edev->nh) * edev->max_supported, GFP_KERNEL); + if (!edev->nh) { + ret = -ENOMEM; ++ device_unregister(&edev->dev); + goto err_dev; + } + +-- +2.30.2 + diff --git a/queue-4.4/firewire-nosy-fix-a-use-after-free-bug-in-nosy_ioctl.patch b/queue-4.4/firewire-nosy-fix-a-use-after-free-bug-in-nosy_ioctl.patch new file mode 100644 index 00000000000..189a2c78242 --- /dev/null +++ b/queue-4.4/firewire-nosy-fix-a-use-after-free-bug-in-nosy_ioctl.patch @@ -0,0 +1,119 @@ +From c3bf4c8b5721c2dff3751444a1f5ea23c038249c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 3 Apr 2021 06:58:36 +0000 +Subject: firewire: nosy: Fix a use-after-free bug in nosy_ioctl() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Zheyu Ma + +[ Upstream commit 829933ef05a951c8ff140e814656d73e74915faf ] + +For each device, the nosy driver allocates a pcilynx structure. +A use-after-free might happen in the following scenario: + + 1. Open nosy device for the first time and call ioctl with command + NOSY_IOC_START, then a new client A will be malloced and added to + doubly linked list. + 2. Open nosy device for the second time and call ioctl with command + NOSY_IOC_START, then a new client B will be malloced and added to + doubly linked list. + 3. Call ioctl with command NOSY_IOC_START for client A, then client A + will be readded to the doubly linked list. Now the doubly linked + list is messed up. + 4. Close the first nosy device and nosy_release will be called. In + nosy_release, client A will be unlinked and freed. + 5. Close the second nosy device, and client A will be referenced, + resulting in UAF. + +The root cause of this bug is that the element in the doubly linked list +is reentered into the list. + +Fix this bug by adding a check before inserting a client. If a client +is already in the linked list, don't insert it. + +The following KASAN report reveals it: + + BUG: KASAN: use-after-free in nosy_release+0x1ea/0x210 + Write of size 8 at addr ffff888102ad7360 by task poc + CPU: 3 PID: 337 Comm: poc Not tainted 5.12.0-rc5+ #6 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 + Call Trace: + nosy_release+0x1ea/0x210 + __fput+0x1e2/0x840 + task_work_run+0xe8/0x180 + exit_to_user_mode_prepare+0x114/0x120 + syscall_exit_to_user_mode+0x1d/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xae + + Allocated by task 337: + nosy_open+0x154/0x4d0 + misc_open+0x2ec/0x410 + chrdev_open+0x20d/0x5a0 + do_dentry_open+0x40f/0xe80 + path_openat+0x1cf9/0x37b0 + do_filp_open+0x16d/0x390 + do_sys_openat2+0x11d/0x360 + __x64_sys_open+0xfd/0x1a0 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xae + + Freed by task 337: + kfree+0x8f/0x210 + nosy_release+0x158/0x210 + __fput+0x1e2/0x840 + task_work_run+0xe8/0x180 + exit_to_user_mode_prepare+0x114/0x120 + syscall_exit_to_user_mode+0x1d/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xae + + The buggy address belongs to the object at ffff888102ad7300 which belongs to the cache kmalloc-128 of size 128 + The buggy address is located 96 bytes inside of 128-byte region [ffff888102ad7300, ffff888102ad7380) + +[ Modified to use 'list_empty()' inside proper lock - Linus ] + +Link: https://lore.kernel.org/lkml/1617433116-5930-1-git-send-email-zheyuma97@gmail.com/ +Reported-and-tested-by: 马哲宇 (Zheyu Ma) +Signed-off-by: Zheyu Ma +Cc: Greg Kroah-Hartman +Cc: Stefan Richter +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + drivers/firewire/nosy.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c +index 76b2d390f6ec..40ed4d8c61f5 100644 +--- a/drivers/firewire/nosy.c ++++ b/drivers/firewire/nosy.c +@@ -358,6 +358,7 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + struct client *client = file->private_data; + spinlock_t *client_list_lock = &client->lynx->client_list_lock; + struct nosy_stats stats; ++ int ret; + + switch (cmd) { + case NOSY_IOC_GET_STATS: +@@ -372,11 +373,15 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return 0; + + case NOSY_IOC_START: ++ ret = -EBUSY; + spin_lock_irq(client_list_lock); +- list_add_tail(&client->link, &client->lynx->client_list); ++ if (list_empty(&client->link)) { ++ list_add_tail(&client->link, &client->lynx->client_list); ++ ret = 0; ++ } + spin_unlock_irq(client_list_lock); + +- return 0; ++ return ret; + + case NOSY_IOC_STOP: + spin_lock_irq(client_list_lock); +-- +2.30.2 + diff --git a/queue-4.4/series b/queue-4.4/series index ee7796957d8..290f5ab14a8 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -18,3 +18,5 @@ tracing-fix-stack-trace-event-size.patch mm-fix-race-by-making-init_zero_pfn-early_initcall.patch reiserfs-update-reiserfs_xattrs_initialized-condition.patch pinctrl-rockchip-fix-restore-error-in-resume.patch +extcon-fix-error-handling-in-extcon_dev_register.patch +firewire-nosy-fix-a-use-after-free-bug-in-nosy_ioctl.patch -- 2.47.3