diff -U 3 -r nut-2.6.0.orig/common/common.c nut-2.6.0/common/common.c --- nut-2.6.0.orig/common/common.c 2011-02-08 12:12:25 +0200 +++ nut-2.6.0/common/common.c 2011-02-08 12:33:15 +0200 @@ -35,6 +35,7 @@ int nut_debug_level = 0; int nut_log_level = 0; static int upslog_flags = UPSLOG_STDERR; + static int null_fd = -1; static void xbit_set(int *val, int flag) { @@ -114,32 +115,29 @@ /* close ttys and become a daemon */ void background(void) { - int pid; + int fd; + pid_t pid; if ((pid = fork()) < 0) fatal_with_errno(EXIT_FAILURE, "Unable to enter background"); - xbit_set(&upslog_flags, UPSLOG_SYSLOG); - xbit_clear(&upslog_flags, UPSLOG_STDERR); - - close(0); - close(1); - close(2); - if (pid != 0) _exit(EXIT_SUCCESS); /* parent */ /* child */ + xbit_set(&upslog_flags, UPSLOG_SYSLOG); + xbit_clear(&upslog_flags, UPSLOG_STDERR); /* make fds 0-2 point somewhere defined */ - if (open("/dev/null", O_RDWR) != 0) + if ((null_fd < 0) && ((null_fd = open("/dev/null", O_RDWR)) < 0)) fatal_with_errno(EXIT_FAILURE, "open /dev/null"); - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); - - if (dup(0) == -1) - fatal_with_errno(EXIT_FAILURE, "dup"); + for (fd = 0; fd<= 2; ++fd) + if ((null_fd != fd) && (dup2(null_fd, fd) < 0)) + fatal_with_errno(EXIT_FAILURE, "dup2 /dev/null"); + if ((null_fd > 2) && (close(null_fd) < 0)) + fatal_with_errno(EXIT_FAILURE, "close /dev/null"); + null_fd = -1; #ifdef HAVE_SETSID setsid(); /* make a new session to dodge signals */ @@ -153,8 +151,11 @@ { struct passwd *r; errno = 0; - if ((r = getpwnam(name))) + if ((r = getpwnam(name))) { + if (!geteuid() && initgroups(r->pw_name, r->pw_gid) == -1) + fatal_with_errno(EXIT_FAILURE, "initgroups"); return r; + } /* POSIX does not specify that "user not found" is an error, so some implementations of getpwnam() do not set errno when this @@ -178,9 +179,6 @@ if (seteuid(0)) fatal_with_errno(EXIT_FAILURE, "getuid gave 0, but seteuid(0) failed"); - if (initgroups(pw->pw_name, pw->pw_gid) == -1) - fatal_with_errno(EXIT_FAILURE, "initgroups"); - if (setgid(pw->pw_gid) == -1) fatal_with_errno(EXIT_FAILURE, "setgid"); @@ -191,6 +189,11 @@ /* drop down into a directory and throw away pointers to the old path */ void chroot_start(const char *path) { + tzset(); + + if ((null_fd = open("/dev/null", O_RDWR)) < 0) + fatal_with_errno(EXIT_FAILURE, "open /dev/null"); + if (chdir(path)) fatal_with_errno(EXIT_FAILURE, "chdir(%s)", path);