Merge "Don't open /dev/null until we need to."

This commit is contained in:
Treehugger Robot 2021-10-29 01:06:23 +00:00 committed by Gerrit Code Review
commit de6c4cd4e0

View file

@ -149,50 +149,25 @@ __noreturn static void __early_abort(int line) {
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
// Force any of the closed stdin, stdout and stderr to be associated with /dev/null. // Force any of the stdin/stdout/stderr file descriptors that aren't
// open to be associated with /dev/null.
static void __nullify_closed_stdio() { static void __nullify_closed_stdio() {
int dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
if (dev_null == -1) {
// init won't have /dev/null available, but SELinux provides an equivalent.
dev_null = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR));
}
if (dev_null == -1) {
__early_abort(__LINE__);
}
// If any of the stdio file descriptors is valid and not associated
// with /dev/null, dup /dev/null to it.
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
// If it is /dev/null already, we are done. if (TEMP_FAILURE_RETRY(fcntl(i, F_GETFL)) == -1) {
if (i == dev_null) { // The only error we allow is that the file descriptor does not exist.
continue; if (errno != EBADF) __early_abort(__LINE__);
}
// Is this fd already open? // This file descriptor wasn't open, so open /dev/null.
int status = TEMP_FAILURE_RETRY(fcntl(i, F_GETFL)); // init won't have /dev/null available, but SELinux provides an equivalent.
if (status != -1) { // This takes advantage of the fact that open() will take the lowest free
continue; // file descriptor, and we're iterating in order from 0, but we'll
} // double-check we got the right fd anyway...
int fd;
// The only error we allow is that the file descriptor does not if (((fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))) == -1 &&
// exist, in which case we dup /dev/null to it. (fd = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR))) == -1) ||
if (errno == EBADF) { fd != i) {
// Try dupping /dev/null to this stdio file descriptor and
// repeat if there is a signal. Note that any errors in closing
// the stdio descriptor are lost.
status = TEMP_FAILURE_RETRY(dup2(dev_null, i));
if (status == -1) {
__early_abort(__LINE__); __early_abort(__LINE__);
} }
} else {
__early_abort(__LINE__);
}
}
// If /dev/null is not one of the stdio file descriptors, close it.
if (dev_null > 2) {
if (close(dev_null) == -1) {
__early_abort(__LINE__);
} }
} }
} }