Skip to content

Commit

Permalink
lib: Make sure stdin/stdout/stderr have fd at startup and keep /dev/n…
Browse files Browse the repository at this point in the history
…ull always open

This guarantees we will always have a fd that can be used as /dev/null.
It works even inside chroots.
  • Loading branch information
sirainen committed Nov 16, 2016
1 parent 34742a4 commit 05475b8
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/lib/lib.c
Expand Up @@ -4,13 +4,16 @@
#include "array.h"
#include "env-util.h"
#include "hostpid.h"
#include "fd-close-on-exec.h"
#include "ipwd.h"
#include "process-title.h"

#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

static bool lib_initialized = FALSE;
int dev_null_fd = -1;

struct atexit_callback {
int priority;
Expand Down Expand Up @@ -115,6 +118,24 @@ void lib_atexit_run(void)
}
}

static void lib_open_non_stdio_dev_null(void)
{
dev_null_fd = open("/dev/null", O_WRONLY);
if (dev_null_fd == -1)
i_fatal("open(/dev/null) failed: %m");
/* Make sure stdin, stdout and stderr fds exist. We especially rely on
stderr being available and a lot of code doesn't like fd being 0.
We'll open /dev/null as write-only also for stdin, since if any
reads are attempted from it we'll want them to fail. */
while (dev_null_fd < STDERR_FILENO) {
dev_null_fd = dup(dev_null_fd);
if (dev_null_fd == -1)
i_fatal("dup(/dev/null) failed: %m");
}
/* close the actual /dev/null fd on exec*(), but keep it in stdio fds */
fd_close_on_exec(dev_null_fd, TRUE);
}

void lib_init(void)
{
struct timeval tv;
Expand All @@ -127,6 +148,8 @@ void lib_init(void)

data_stack_init();
hostpid_init();
lib_open_non_stdio_dev_null();

lib_initialized = TRUE;
}

Expand All @@ -142,6 +165,7 @@ void lib_deinit(void)
lib_atexit_run();
ipwd_deinit();
hostpid_deinit();
i_close_fd(&dev_null_fd);
data_stack_deinit();
env_deinit();
failures_deinit();
Expand Down
4 changes: 4 additions & 0 deletions src/lib/lib.h
Expand Up @@ -49,6 +49,10 @@ typedef void lib_atexit_callback_t(void);
#define LIB_ATEXIT_PRIORITY_DEFAULT 0
#define LIB_ATEXIT_PRIORITY_LOW 10

/* /dev/null opened as O_WRONLY. Opened at lib_init(), so it can be accessed
also inside chroots. */
extern int dev_null_fd;

int close_keep_errno(int *fd);
/* Call unlink(). If it fails, log an error including the source filename
and line number. */
Expand Down

0 comments on commit 05475b8

Please sign in to comment.