Blob Blame History Raw
From e71be55b86a61afd39e90363919cec7ca9912197 Mon Sep 17 00:00:00 2001
From: David Disseldorp <ddiss@suse.de>
Date: Tue, 27 Sep 2022 11:01:53 +0200
Subject: [PATCH] io_uring: disable polling signalfd pollfree files
Patch-mainline: Never, patch based on stable-5.4 (commit fc78b2fc21f10)
References: CVE-2022-3176 bsc#1203391

Older kernels lack io_uring POLLFREE handling, which is added via
791f3465c4afd ("io_uring: fix UAF due to missing 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.

Fixes: 221c5eb233823 ("io_uring: add support for IORING_OP_POLL")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ddiss: preserve kABI by checking for signalfd_poll in file_operations.
        Binder is disabled for SLE so can be ignored]
Signed-off-by: David Disseldorp <ddiss@suse.de>
Acked-by: Jan Kara <jack@suse.cz>
---
 fs/io_uring.c | 7 +++++++
 fs/signalfd.c | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index 31057f44257cc..31a3a00ef48e2 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1753,6 +1753,13 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	bool cancel = false;
 	__poll_t mask;
 	u16 events;
+#ifdef CONFIG_SIGNALFD
+	extern __poll_t signalfd_poll(struct file *file, poll_table *wait);
+
+	/* unhandled pollfree: Binder (SLE-disabled) and signalfd only */
+	if (req->file->f_op->poll == &signalfd_poll)
+		return -EOPNOTSUPP;
+#endif
 
 	if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
 		return -EINVAL;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 2d815ab9ecc2d..9ddd1c593b146 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -48,7 +48,7 @@ static int signalfd_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static __poll_t signalfd_poll(struct file *file, poll_table *wait)
+__poll_t signalfd_poll(struct file *file, poll_table *wait)
 {
 	struct signalfd_ctx *ctx = file->private_data;
 	__poll_t events = 0;
-- 
2.35.3