mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 21:21:41 +00:00
50252e4b5e
signalfd_poll() and binder_poll() are special in that they use a
waitqueue whose lifetime is the current task, rather than the struct
file as is normally the case. This is okay for blocking polls, since a
blocking poll occurs within one task; however, non-blocking polls
require another solution. This solution is for the queue to be cleared
before it is freed, by sending a POLLFREE notification to all waiters.
Unfortunately, only eventpoll handles POLLFREE. A second type of
non-blocking poll, aio poll, was added in kernel v4.18, and it doesn't
handle POLLFREE. This allows a use-after-free to occur if a signalfd or
binder fd is polled with aio poll, and the waitqueue gets freed.
Fix this by making aio poll handle POLLFREE.
A patch by Ramji Jiyani <ramjiyani@google.com>
(https://lore.kernel.org/r/20211027011834.2497484-1-ramjiyani@google.com)
tried to do this by making aio_poll_wake() always complete the request
inline if POLLFREE is seen. However, that solution had two bugs.
First, it introduced a deadlock, as it unconditionally locked the aio
context while holding the waitqueue lock, which inverts the normal
locking order. Second, it didn't consider that POLLFREE notifications
are missed while the request has been temporarily de-queued.
The second problem was solved by my previous patch. This patch then
properly fixes the use-after-free by handling POLLFREE in a
deadlock-free way. It does this by taking advantage of the fact that
freeing of the waitqueue is RCU-delayed, similar to what eventpoll does.
Fixes: 2c14fa838c
("aio: implement IOCB_CMD_POLL")
Cc: <stable@vger.kernel.org> # v4.18+
Link: https://lore.kernel.org/r/20211209010455.42744-6-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
43 lines
863 B
C
43 lines
863 B
C
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
#ifndef __ASM_GENERIC_POLL_H
|
|
#define __ASM_GENERIC_POLL_H
|
|
|
|
/* These are specified by iBCS2 */
|
|
#define POLLIN 0x0001
|
|
#define POLLPRI 0x0002
|
|
#define POLLOUT 0x0004
|
|
#define POLLERR 0x0008
|
|
#define POLLHUP 0x0010
|
|
#define POLLNVAL 0x0020
|
|
|
|
/* The rest seem to be more-or-less nonstandard. Check them! */
|
|
#define POLLRDNORM 0x0040
|
|
#define POLLRDBAND 0x0080
|
|
#ifndef POLLWRNORM
|
|
#define POLLWRNORM 0x0100
|
|
#endif
|
|
#ifndef POLLWRBAND
|
|
#define POLLWRBAND 0x0200
|
|
#endif
|
|
#ifndef POLLMSG
|
|
#define POLLMSG 0x0400
|
|
#endif
|
|
#ifndef POLLREMOVE
|
|
#define POLLREMOVE 0x1000
|
|
#endif
|
|
#ifndef POLLRDHUP
|
|
#define POLLRDHUP 0x2000
|
|
#endif
|
|
|
|
#define POLLFREE (__force __poll_t)0x4000
|
|
|
|
#define POLL_BUSY_LOOP (__force __poll_t)0x8000
|
|
|
|
struct pollfd {
|
|
int fd;
|
|
short events;
|
|
short revents;
|
|
};
|
|
|
|
#endif /* __ASM_GENERIC_POLL_H */
|