Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

aio: fix io_setup/io_destroy race

Have ioctx_alloc() return an extra reference, so that caller would drop it
on success and not bother with re-grabbing it on failure exit. The current
code is obviously broken - io_destroy() from another thread that managed
to guess the address io_setup() would've returned would free ioctx right
under us; gets especially interesting if aio_context_t * we pass to
io_setup() points to PROT_READ mapping, so put_user() fails and we end
up doing io_destroy() on kioctx another thread has just got freed...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Benjamin LaHaise <bcrl@kvack.org>
Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Al Viro and committed by
Linus Torvalds
86b62a2c 86e06008

+4 -4
+4 -4
fs/aio.c
··· 273 273 mm = ctx->mm = current->mm; 274 274 atomic_inc(&mm->mm_count); 275 275 276 - atomic_set(&ctx->users, 1); 276 + atomic_set(&ctx->users, 2); 277 277 spin_lock_init(&ctx->ctx_lock); 278 278 spin_lock_init(&ctx->ring_info.ring_lock); 279 279 init_waitqueue_head(&ctx->wait); ··· 1338 1338 ret = PTR_ERR(ioctx); 1339 1339 if (!IS_ERR(ioctx)) { 1340 1340 ret = put_user(ioctx->user_id, ctxp); 1341 - if (!ret) 1341 + if (!ret) { 1342 + put_ioctx(ioctx); 1342 1343 return 0; 1343 - 1344 - get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */ 1344 + } 1345 1345 io_destroy(ioctx); 1346 1346 } 1347 1347