|
Message-ID: <Y6PQctuK5/GtDRa5@ip-172-31-85-199.ec2.internal> Date: Thu, 22 Dec 2022 11:35:14 +0800 From: Xingyuan Mo <hdthky0@...il.com> To: oss-security@...ts.openwall.com Subject: Linux kernel: use-after-free in io_sqpoll_wait_sq Hello, There is a use-after-free vulnerability in io_sqpoll_wait_sq() in fs/io_uring.c in linux-5.10.y through v5.10.154, which allows an attacker to crash the kernel, resulting in Denial of Service. =*=*=*=*=*=*=*=*= Bug Details =*=*=*=*=*=*=*=*= 9028: static int io_sqpoll_wait_sq(struct io_ring_ctx *ctx) 9029: { 9030: int ret = 0; 9031: DEFINE_WAIT(wait); 9032: 9033: do { 9034: if (!io_sqring_full(ctx)) 9035: break; 9036: 9037: prepare_to_wait(&ctx->sqo_sq_wait, &wait, TASK_INTERRUPTIBLE); 9038: 9039: if (unlikely(ctx->sqo_dead)) { 9040: ret = -EOWNERDEAD; 9041: goto out; 9042: } 9043: 9044: if (!io_sqring_full(ctx)) 9045: break; 9046: 9047: schedule(); 9048: } while (!signal_pending(current)); 9049: 9050: finish_wait(&ctx->sqo_sq_wait, &wait); 9051: out: 9052: return ret; 9053: } On line 9037 of fs/io_uring.c, a wait_queue_entry object on the stack named wait is added to wait queue ctx->sqo_sq_wait, which should be removed from ctx->sqo_sq_wait by calling finish_wait() once the current task does not need to wait for an available submission queue entry. Though, On line 9039, if ctx->sqo_dead is not 0, the control flow jumps to out, skipping the call to finish_wait() on line 9050. As a result, wait still exists in ctx->sqo_sq_wait even when the current task exits kernel mode or comes to an end, which means that the two entries before and after wait each contain a stale pointer to the expired kernel stack space. If one of the two entries is later unlinked from ctx->sqo_dead, the memory of the expired stack space pointed to by the stale pointer will be corrupted, resulting in use-after-free. As mentioned earlier, the condition for triggering the vulnerability is that ctx->sqo_dead is not 0, which can be achieved by forking a new process and terminating it quickly. When the new process exits, the copied io_uring file descriptor will be closed, causing the following call chain to be triggered: io_uring_flush()->io_uring_cancel_task_requests()->io_disable_sqo_submit(). In io_disable_sqo_submit(), ctx->sqo_dead is assigned 1 on line 8732. 8729: static void io_disable_sqo_submit(struct io_ring_ctx *ctx) 8730: { 8731: mutex_lock(&ctx->uring_lock); 8732: ctx->sqo_dead = 1; 8733: if (ctx->flags & IORING_SETUP_R_DISABLED) 8734: io_sq_offload_start(ctx); 8735: mutex_unlock(&ctx->uring_lock); 8736: 8737: /* make sure callers enter the ring to get error */ 8738: if (ctx->rings) 8739: io_ring_set_wakeup_flag(ctx); 8740: } =*=*=*=*=*=*=*=*= Patch =*=*=*=*=*=*=*=*= The patch can be found here: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.10.161&id=0f544353fec8e717d37724d95b92538e1de79e86 =*=*=*=*=*=*=*=*= Credit =*=*=*=*=*=*=*=*= Xingyuan Mo and Gengjia Chen of IceSword Lab, Qihoo 360 Technology Co. Ltd. Best Regards, Xingyuan Mo
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.