From 2e3a42ca60fd023c1a904875980940fafc40bf0d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 5 Jun 2022 14:01:42 -0400 Subject: [PATCH] UPSTREAM: fix the breakage in close_fd_get_file() calling conventions change It used to grab an extra reference to struct file rather than just transferring to caller the one it had removed from descriptor table. New variant doesn't, and callers need to be adjusted. Reported-and-tested-by: syzbot+47dd250f527cb7bebf24@syzkaller.appspotmail.com Fixes: 6319194ec57b ("Unify the primitives for file descriptor closing") Signed-off-by: Al Viro (cherry picked from commit 40a1926022d128057376d35167128a7c74e3dca4) Signed-off-by: Greg Kroah-Hartman Change-Id: I5f35765ed03c018123b0e121f7d6ebe7f351f4d4 --- drivers/android/binder.c | 2 ++ fs/file.c | 3 +-- fs/io_uring.c | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index f10ee8ebbceb..1ba5ec60b3a3 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2059,6 +2059,8 @@ static void binder_deferred_fd_close(int fd) init_task_work(&twcb->twork, binder_do_fd_close); twcb->file = close_fd_get_file(fd); if (twcb->file) { + // pin it until binder_do_fd_close(); see comments there + get_file(twcb->file); filp_close(twcb->file, current->files); task_work_add(current, &twcb->twork, TWA_RESUME); } else { diff --git a/fs/file.c b/fs/file.c index dd6692048f4f..3bcc1ecc314a 100644 --- a/fs/file.c +++ b/fs/file.c @@ -800,8 +800,7 @@ struct file *__close_fd_get_file(unsigned int fd) /* * variant of close_fd that gets a ref on the file for later fput. - * The caller must ensure that filp_close() called on the file, and then - * an fput(). + * The caller must ensure that filp_close() called on the file. */ struct file *close_fd_get_file(unsigned int fd) { diff --git a/fs/io_uring.c b/fs/io_uring.c index 86f9df56526b..3aab4182fd89 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6010,7 +6010,7 @@ static int io_close(struct io_kiocb *req, unsigned int issue_flags) struct files_struct *files = current->files; struct io_close *close = &req->close; struct fdtable *fdt; - struct file *file = NULL; + struct file *file; int ret = -EBADF; if (req->close.file_slot) { @@ -6029,7 +6029,6 @@ static int io_close(struct io_kiocb *req, unsigned int issue_flags) lockdep_is_held(&files->file_lock)); if (!file || file->f_op == &io_uring_fops) { spin_unlock(&files->file_lock); - file = NULL; goto err; } @@ -6049,8 +6048,6 @@ static int io_close(struct io_kiocb *req, unsigned int issue_flags) err: if (ret < 0) req_set_fail(req); - if (file) - fput(file); __io_req_complete(req, issue_flags, ret, 0); return 0; }