Commit 2d1e952a authored by Lee Jones's avatar Lee Jones Committed by Jassi Brar

mailbox: mailbox-test: Fix potential double-free in mbox_test_message_write()

If a user can make copy_from_user() fail, there is a potential for
UAF/DF due to a lack of locking around the allocation, use and freeing
of the data buffers.

This issue is not theoretical.  I managed to author a POC for it:

    BUG: KASAN: double-free in kfree+0x5c/0xac
    Free of addr ffff29280be5de00 by task poc/356
    CPU: 1 PID: 356 Comm: poc Not tainted 6.1.0-00001-g961aa6552c04-dirty #20
    Hardware name: linux,dummy-virt (DT)
    Call trace:
     dump_backtrace.part.0+0xe0/0xf0
     show_stack+0x18/0x40
     dump_stack_lvl+0x64/0x80
     print_report+0x188/0x48c
     kasan_report_invalid_free+0xa0/0xc0
     ____kasan_slab_free+0x174/0x1b0
     __kasan_slab_free+0x18/0x24
     __kmem_cache_free+0x130/0x2e0
     kfree+0x5c/0xac
     mbox_test_message_write+0x208/0x29c
     full_proxy_write+0x90/0xf0
     vfs_write+0x154/0x440
     ksys_write+0xcc/0x180
     __arm64_sys_write+0x44/0x60
     invoke_syscall+0x60/0x190
     el0_svc_common.constprop.0+0x7c/0x160
     do_el0_svc+0x40/0xf0
     el0_svc+0x2c/0x6c
     el0t_64_sync_handler+0xf4/0x120
     el0t_64_sync+0x18c/0x190

    Allocated by task 356:
     kasan_save_stack+0x3c/0x70
     kasan_set_track+0x2c/0x40
     kasan_save_alloc_info+0x24/0x34
     __kasan_kmalloc+0xb8/0xc0
     kmalloc_trace+0x58/0x70
     mbox_test_message_write+0x6c/0x29c
     full_proxy_write+0x90/0xf0
     vfs_write+0x154/0x440
     ksys_write+0xcc/0x180
     __arm64_sys_write+0x44/0x60
     invoke_syscall+0x60/0x190
     el0_svc_common.constprop.0+0x7c/0x160
     do_el0_svc+0x40/0xf0
     el0_svc+0x2c/0x6c
     el0t_64_sync_handler+0xf4/0x120
     el0t_64_sync+0x18c/0x190

    Freed by task 357:
     kasan_save_stack+0x3c/0x70
     kasan_set_track+0x2c/0x40
     kasan_save_free_info+0x38/0x5c
     ____kasan_slab_free+0x13c/0x1b0
     __kasan_slab_free+0x18/0x24
     __kmem_cache_free+0x130/0x2e0
     kfree+0x5c/0xac
     mbox_test_message_write+0x208/0x29c
     full_proxy_write+0x90/0xf0
     vfs_write+0x154/0x440
     ksys_write+0xcc/0x180
     __arm64_sys_write+0x44/0x60
     invoke_syscall+0x60/0x190
     el0_svc_common.constprop.0+0x7c/0x160
     do_el0_svc+0x40/0xf0
     el0_svc+0x2c/0x6c
     el0t_64_sync_handler+0xf4/0x120
     el0t_64_sync+0x18c/0x190
Signed-off-by: default avatarLee Jones <lee@kernel.org>
Signed-off-by: default avatarJassi Brar <jaswinder.singh@linaro.org>
parent be884585
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mailbox_client.h> #include <linux/mailbox_client.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/poll.h> #include <linux/poll.h>
...@@ -39,6 +40,7 @@ struct mbox_test_device { ...@@ -39,6 +40,7 @@ struct mbox_test_device {
char *signal; char *signal;
char *message; char *message;
spinlock_t lock; spinlock_t lock;
struct mutex mutex;
wait_queue_head_t waitq; wait_queue_head_t waitq;
struct fasync_struct *async_queue; struct fasync_struct *async_queue;
struct dentry *root_debugfs_dir; struct dentry *root_debugfs_dir;
...@@ -111,6 +113,8 @@ static ssize_t mbox_test_message_write(struct file *filp, ...@@ -111,6 +113,8 @@ static ssize_t mbox_test_message_write(struct file *filp,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&tdev->mutex);
tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL); tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
if (!tdev->message) if (!tdev->message)
return -ENOMEM; return -ENOMEM;
...@@ -145,6 +149,8 @@ static ssize_t mbox_test_message_write(struct file *filp, ...@@ -145,6 +149,8 @@ static ssize_t mbox_test_message_write(struct file *filp,
kfree(tdev->message); kfree(tdev->message);
tdev->signal = NULL; tdev->signal = NULL;
mutex_unlock(&tdev->mutex);
return ret < 0 ? ret : count; return ret < 0 ? ret : count;
} }
...@@ -393,6 +399,7 @@ static int mbox_test_probe(struct platform_device *pdev) ...@@ -393,6 +399,7 @@ static int mbox_test_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tdev); platform_set_drvdata(pdev, tdev);
spin_lock_init(&tdev->lock); spin_lock_init(&tdev->lock);
mutex_init(&tdev->mutex);
if (tdev->rx_channel) { if (tdev->rx_channel) {
tdev->rx_buffer = devm_kzalloc(&pdev->dev, tdev->rx_buffer = devm_kzalloc(&pdev->dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment