Re: [PATCH] fs, USB gadget: Rework kiocb cancellation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2/7/24 1:56 AM, Christian Brauner wrote:
> On Tue, Feb 06, 2024 at 03:47:18PM -0800, Bart Van Assche wrote:
>> Calling kiocb_set_cancel_fn() without knowing whether the caller
>> submitted a struct kiocb or a struct aio_kiocb is unsafe. Fix this by
>> introducing the cancel_kiocb() method in struct file_operations. The
>> following call trace illustrates that without this patch an
>> out-of-bounds write happens if I/O is submitted by io_uring (from a
>> phone with an ARM CPU and kernel 6.1):
>>
>> WARNING: CPU: 3 PID: 368 at fs/aio.c:598 kiocb_set_cancel_fn+0x9c/0xa8
>> Call trace:
>>  kiocb_set_cancel_fn+0x9c/0xa8
>>  ffs_epfile_read_iter+0x144/0x1d0
>>  io_read+0x19c/0x498
>>  io_issue_sqe+0x118/0x27c
>>  io_submit_sqes+0x25c/0x5fc
>>  __arm64_sys_io_uring_enter+0x104/0xab0
>>  invoke_syscall+0x58/0x11c
>>  el0_svc_common+0xb4/0xf4
>>  do_el0_svc+0x2c/0xb0
>>  el0_svc+0x2c/0xa4
>>  el0t_64_sync_handler+0x68/0xb4
>>  el0t_64_sync+0x1a4/0x1a8
>>
>> The following patch has been used as the basis of this patch: Christoph
>> Hellwig, "[PATCH 08/32] aio: replace kiocb_set_cancel_fn with a
>> cancel_kiocb file operation", May 2018
>> (https://lore.kernel.org/all/20180515194833.6906-9-hch@xxxxxx/).
> 
> What's changed that voids Al's objections on that patch from 2018?
> Specifically
> https://lore.kernel.org/all/20180406021553.GS30522@xxxxxxxxxxxxxxxxxx
> https://lore.kernel.org/all/20180520052720.GY30522@xxxxxxxxxxxxxxxxxx

Nothing, it's definitely still broken in the same UAF way.

But so is the cancelation bits, the assumption of the kiocb being
contained within some aio specific struct is just awful.

Does the cancelation support even work, or is needed? It would seem a
lot more prudent to get rid of it. Barring that, we should probably do
something like the below upfront until the whole thing is sorted out.


diff --git a/fs/aio.c b/fs/aio.c
index bb2ff48991f3..159648f43238 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -593,6 +593,10 @@ void kiocb_set_cancel_fn(struct kiocb *iocb, kiocb_cancel_fn *cancel)
 	struct kioctx *ctx = req->ki_ctx;
 	unsigned long flags;
 
+	/* kiocb didn't come from aio, so just ignore it */
+	if (!(iocb->ki_flags & IOCB_FROM_AIO))
+		return;
+
 	if (WARN_ON_ONCE(!list_empty(&req->ki_list)))
 		return;
 
@@ -1509,7 +1513,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
 	req->ki_complete = aio_complete_rw;
 	req->private = NULL;
 	req->ki_pos = iocb->aio_offset;
-	req->ki_flags = req->ki_filp->f_iocb_flags;
+	req->ki_flags = req->ki_filp->f_iocb_flags | IOCB_FROM_AIO;
 	if (iocb->aio_flags & IOCB_FLAG_RESFD)
 		req->ki_flags |= IOCB_EVENTFD;
 	if (iocb->aio_flags & IOCB_FLAG_IOPRIO) {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ed5966a70495..2870b3d61866 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -352,6 +352,10 @@ enum rw_hint {
  * unrelated IO (like cache flushing, new IO generation, etc).
  */
 #define IOCB_DIO_CALLER_COMP	(1 << 22)
+ /*
+  * kiocb came from fs/aio.c
+  */
+#define IOCB_FROM_AIO		(1 << 23)
 
 /* for use in trace events */
 #define TRACE_IOCB_STRINGS \

-- 
Jens Axboe





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux