[PATCH] io_uring: fix filename leak in __io_openat_prep()

Prithvi Tambewagh posted 1 patch 1 month, 2 weeks ago
There is a newer version of this series
io_uring/openclose.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
[PATCH] io_uring: fix filename leak in __io_openat_prep()
Posted by Prithvi Tambewagh 1 month, 2 weeks ago
__io_openat_prep() allocates a struct filename using getname(), but
it isn't freed in case the present file is installed in the fixed file
table and simultaneously, it has the flag O_CLOEXEC set in the
open->how.flags field.

This is an erroneous condition, since for a file installed in the fixed
file table, it won't be installed in the normal file table, due to which
the file cannot support close on exec. Earlier, the code just returned
-EINVAL error code for this condition, however, the memory allocated for
that struct filename wasn't freed, resulting in a memory leak.

Hence, the case of file being installed in the fixed file table as well
as having O_CLOEXEC flag in open->how.flags set, is adressed by using
putname() to release the memory allocated to the struct filename, then
setting the field open->filename to NULL, and after that, returning
-EINVAL.

Reported-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=00e61c43eb5e4740438f
Tested-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
Cc: stable@vger.kernel.org
Signed-off-by: Prithvi Tambewagh <activprithvi@gmail.com>
---
 io_uring/openclose.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/io_uring/openclose.c b/io_uring/openclose.c
index bfeb91b31bba..fc190a3d8112 100644
--- a/io_uring/openclose.c
+++ b/io_uring/openclose.c
@@ -75,8 +75,11 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
 	}
 
 	open->file_slot = READ_ONCE(sqe->file_index);
-	if (open->file_slot && (open->how.flags & O_CLOEXEC))
+	if (open->file_slot && (open->how.flags & O_CLOEXEC)) {
+		putname(open->filename);
+		open->filename = NULL;
 		return -EINVAL;
+	}
 
 	open->nofile = rlimit(RLIMIT_NOFILE);
 	req->flags |= REQ_F_NEED_CLEANUP;

base-commit: b927546677c876e26eba308550207c2ddf812a43
-- 
2.34.1
Re: [PATCH] io_uring: fix filename leak in __io_openat_prep()
Posted by Jens Axboe 1 month, 2 weeks ago
On 12/24/25 9:42 AM, Prithvi Tambewagh wrote:
> __io_openat_prep() allocates a struct filename using getname(), but
> it isn't freed in case the present file is installed in the fixed file
> table and simultaneously, it has the flag O_CLOEXEC set in the
> open->how.flags field.
> 
> This is an erroneous condition, since for a file installed in the fixed
> file table, it won't be installed in the normal file table, due to which
> the file cannot support close on exec. Earlier, the code just returned
> -EINVAL error code for this condition, however, the memory allocated for
> that struct filename wasn't freed, resulting in a memory leak.
> 
> Hence, the case of file being installed in the fixed file table as well
> as having O_CLOEXEC flag in open->how.flags set, is adressed by using
> putname() to release the memory allocated to the struct filename, then
> setting the field open->filename to NULL, and after that, returning
> -EINVAL.
> 
> Reported-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=00e61c43eb5e4740438f
> Tested-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
> Cc: stable@vger.kernel.org
> Signed-off-by: Prithvi Tambewagh <activprithvi@gmail.com>
> ---
>  io_uring/openclose.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/io_uring/openclose.c b/io_uring/openclose.c
> index bfeb91b31bba..fc190a3d8112 100644
> --- a/io_uring/openclose.c
> +++ b/io_uring/openclose.c
> @@ -75,8 +75,11 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
>  	}
>  
>  	open->file_slot = READ_ONCE(sqe->file_index);
> -	if (open->file_slot && (open->how.flags & O_CLOEXEC))
> +	if (open->file_slot && (open->how.flags & O_CLOEXEC)) {
> +		putname(open->filename);
> +		open->filename = NULL;
>  		return -EINVAL;
> +	}
>  
>  	open->nofile = rlimit(RLIMIT_NOFILE);
>  	req->flags |= REQ_F_NEED_CLEANUP;

You can probably fix it similarly by just having REQ_F_NEED_CLEANUP set
earlier in the process, then everything that needs undoing will get
undone as part of ending the request.

-- 
Jens Axboe
Re: [PATCH] io_uring: fix filename leak in __io_openat_prep()
Posted by Prithvi 1 month, 2 weeks ago
On Wed, Dec 24, 2025 at 11:01:55AM -0700, Jens Axboe wrote:
> On 12/24/25 9:42 AM, Prithvi Tambewagh wrote:
> > __io_openat_prep() allocates a struct filename using getname(), but
> > it isn't freed in case the present file is installed in the fixed file
> > table and simultaneously, it has the flag O_CLOEXEC set in the
> > open->how.flags field.
> > 
> > This is an erroneous condition, since for a file installed in the fixed
> > file table, it won't be installed in the normal file table, due to which
> > the file cannot support close on exec. Earlier, the code just returned
> > -EINVAL error code for this condition, however, the memory allocated for
> > that struct filename wasn't freed, resulting in a memory leak.
> > 
> > Hence, the case of file being installed in the fixed file table as well
> > as having O_CLOEXEC flag in open->how.flags set, is adressed by using
> > putname() to release the memory allocated to the struct filename, then
> > setting the field open->filename to NULL, and after that, returning
> > -EINVAL.
> > 
> > Reported-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=00e61c43eb5e4740438f
> > Tested-by: syzbot+00e61c43eb5e4740438f@syzkaller.appspotmail.com
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Prithvi Tambewagh <activprithvi@gmail.com>
> > ---
> >  io_uring/openclose.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/io_uring/openclose.c b/io_uring/openclose.c
> > index bfeb91b31bba..fc190a3d8112 100644
> > --- a/io_uring/openclose.c
> > +++ b/io_uring/openclose.c
> > @@ -75,8 +75,11 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
> >  	}
> >  
> >  	open->file_slot = READ_ONCE(sqe->file_index);
> > -	if (open->file_slot && (open->how.flags & O_CLOEXEC))
> > +	if (open->file_slot && (open->how.flags & O_CLOEXEC)) {
> > +		putname(open->filename);
> > +		open->filename = NULL;
> >  		return -EINVAL;
> > +	}
> >  
> >  	open->nofile = rlimit(RLIMIT_NOFILE);
> >  	req->flags |= REQ_F_NEED_CLEANUP;
> 
> You can probably fix it similarly by just having REQ_F_NEED_CLEANUP set
> earlier in the process, then everything that needs undoing will get
> undone as part of ending the request.
> 
> -- 
> Jens Axboe

Sure, I will send v2 patch incorporating this change. Thanks for the 
feedback!

Best Regards, 
Prithvi