From 119bc55ba66542a1c2fb7fc1c4e6c85f46b97c57 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Thu, 5 Apr 2018 11:04:21 -0400 Subject: [PATCH] prevent bypass of guarantee that suids start with fd 0/1/2 open it was reported by Erik Bosman that poll fails without setting revents when the nfds argument exceeds the current value for RLIMIT_NOFILE, causing the subsequent open calls to be bypassed. if the rlimit is either 1 or 2, this leaves fd 0 and 1 potentially closed but openable when the application code is reached. based on a brief reading of the poll syscall documentation and code, it may be possible for poll to fail under other attacker-controlled conditions as well. if it turns out these are reasonable conditions that may happen in the real world, we may have to go back and implement fallbacks to probe each fd individually if poll fails, but for now, keep things simple and treat all poll failures as fatal. --- src/env/__libc_start_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c index 2d758af7..0583f686 100644 --- a/src/env/__libc_start_main.c +++ b/src/env/__libc_start_main.c @@ -42,11 +42,13 @@ void __init_libc(char **envp, char *pn) && !aux[AT_SECURE]) return; struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} }; + int r = #ifdef SYS_poll __syscall(SYS_poll, pfd, 3, 0); #else __syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8); #endif + if (r<0) a_crash(); for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL) if (__sys_open("/dev/null", O_RDWR)<0) a_crash(); -- 2.25.1