On 9/1/22 16:16, Pavel Begunkov wrote:
Older kernels lack io_uring POLLFREE handling. As only affected files
are signalfd and android binder the safest option would be to disable
polling those files via io_uring and hope there are no users.
It differs from how it's fixed upstream, but IMHO porting is too
difficult to be reliable enough, this one is quick and simple.
The upstream fix:
commit 791f3465c4afde02d7f16cf7424ca87070b69396
Author: Pavel Begunkov <asml.silence@xxxxxxxxx>
Date: Fri Jan 14 11:59:10 2022 +0000
io_uring: fix UAF due to missing POLLFREE handling
I also forgot Fixes tag if required:
Fixes: 221c5eb233823 ("io_uring: add support for IORING_OP_POLL")
Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx>
---
drivers/android/binder.c | 1 +
fs/io_uring.c | 5 +++++
fs/signalfd.c | 1 +
include/linux/fs.h | 1 +
4 files changed, 8 insertions(+)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 366b12405708..a5d5247c4f3e 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -6069,6 +6069,7 @@ const struct file_operations binder_fops = {
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
+ .may_pollfree = true,
};
static int __init init_binder_device(const char *name)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index a952288b2ab8..9654b60a06a5 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -5198,6 +5198,11 @@ static __poll_t __io_arm_poll_handler(struct io_kiocb *req,
struct io_ring_ctx *ctx = req->ctx;
bool cancel = false;
+ if (req->file->f_op->may_pollfree) {
+ spin_lock_irq(&ctx->completion_lock);
+ return -EOPNOTSUPP;
+ }
+
INIT_HLIST_NODE(&req->hash_node);
io_init_poll_iocb(poll, mask, wake_func);
poll->file = req->file;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index b94fb5f81797..41dc597b78cc 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -248,6 +248,7 @@ static const struct file_operations signalfd_fops = {
.poll = signalfd_poll,
.read = signalfd_read,
.llseek = noop_llseek,
+ .may_pollfree = true,
};
static int do_signalfd4(int ufd, sigset_t *mask, int flags)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 42d246a94228..c8f887641878 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1859,6 +1859,7 @@ struct file_operations {
struct file *file_out, loff_t pos_out,
loff_t len, unsigned int remap_flags);
int (*fadvise)(struct file *, loff_t, loff_t, int);
+ bool may_pollfree;
} __randomize_layout;
struct inode_operations {
--
Pavel Begunkov