From 08923d2c956ece3dc604d5842ba152c2bdb11fb9 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 14 Nov 2016 14:48:20 +0100 Subject: [PATCH] lib-master: Make sure stdin/stdout/stderr fds are open. We'll just open /dev/null for them if they don't already exist. --- src/lib-master/master-service.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index 9294f059f3..5fcd05fa32 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -20,6 +20,7 @@ #include "master-service-settings.h" #include +#include #include #include @@ -167,6 +168,28 @@ master_service_init(const char *name, enum master_service_flags flags, fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024); } #endif + /* 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. */ + for (int fd = 0; fd <= 2; fd++) { + struct stat st; + + if (fstat(fd, &st) < 0 && errno == EBADF) { + int null_fd = open("/dev/null", O_WRONLY); + if (null_fd == -1) + i_fatal("Can't open /dev/null: %m"); + else if (null_fd != fd) { + /* we don't really expect this to happen. + POSIX guarantees that open() returns the + lowest numbered fd. So this would only mean + that fstat() returned EBADF for a fd that + actually existed. */ + if (close(null_fd) < 0) + i_error("close(/dev/null) failed: %m"); + } + } + } if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) { /* make sure we can dump core, at least until privileges are dropped. (i'm not really sure why this