2004-03-13 Dmitry V. Levin Improve chroot jailing support. * common/common.c: (become_user): Moved initgroups call from here ... (get_user_pwent): ... to here. (chroot_start): Call tzset(3) before chroot(2) call. Preopen /dev/null before chroot(2) call ... (background): ... and use the descriptor for redirection. (background): Do not close standard descriptors in parent process. --- nut-2.0.0/common/common.c.orig 2004-03-08 15:09:54 +0300 +++ nut-2.0.0/common/common.c 2004-04-04 23:53:38 +0400 @@ -26,6 +26,7 @@ int nut_debug_level = 0; static int upslog_flags = UPSLOG_STDERR; + static int null_fd = -1; static void xbit_set(int *val, int flag) { @@ -66,28 +67,29 @@ /* close ttys and become a daemon */ void background(void) { - int pid; + int fd; + pid_t pid; if ((pid = fork()) < 0) fatal("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("open /dev/null"); - dup(0); - dup(0); + for (fd = 0; fd<= 2; ++fd) + if ((null_fd != fd) && (dup2(null_fd, fd) < 0)) + fatal("dup2 /dev/null"); + if ((null_fd > 2) && (close(null_fd) < 0)) + fatal("close /dev/null"); + null_fd = -1; #ifdef HAVE_SETSID setsid(); /* make a new session to dodge signals */ @@ -99,7 +101,12 @@ /* do this here to keep pwd/grp stuff out of the main files */ struct passwd *get_user_pwent(const char *name) { - return getpwnam(name); + struct passwd *pw = getpwnam(name); + + if (pw && !geteuid() && initgroups(pw->pw_name, pw->pw_gid) == -1) + fatal("initgroups"); + + return pw; } /* change to the user defined in the struct */ @@ -113,9 +120,6 @@ void become_user(struct passwd *pw) if (seteuid(0)) fatal("getuid gave 0, but seteuid(0) failed"); - if (initgroups(pw->pw_name, pw->pw_gid) == -1) - fatal("initgroups"); - if (setgid(pw->pw_gid) == -1) fatal("setgid"); @@ -126,6 +130,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("open /dev/null"); + if (chdir(path)) fatal("chdir(%s)", path);