--- embedtools/src/wdog.c 2010/10/18 08:32:39 1.1.2.2 +++ embedtools/src/wdog.c 2010/10/18 10:47:06 1.1.2.4 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ - * $Id: wdog.c,v 1.1.2.2 2010/10/18 08:32:39 misho Exp $ + * $Id: wdog.c,v 1.1.2.4 2010/10/18 10:47:06 misho Exp $ * *************************************************************************/ #include "global.h" @@ -22,6 +22,7 @@ Usage() " Syntax: wdog [options] [exec_file]\n\n" "\t-v\t\tVerbose ...\n" "\t-c \tBefore execute chroot to dir [default=/]\n" + "\t-u \tBefore execute change user\n" "\n", compiled, compiledby, compilehost); } @@ -44,23 +45,44 @@ sigHand(int sig) int main(int argc, char **argv) { - char ch, szRun[MAXPATHLEN], szChroot[MAXPATHLEN] = "/"; - int status, ret = 1; + char ch, szChroot[MAXPATHLEN] = "/"; + int status = 0, ret = 1; struct sigaction sa; + struct passwd *pass = NULL; + uid_t uid = getuid(); - while ((ch = getopt(argc, argv, "vhc:")) != -1) + while ((ch = getopt(argc, argv, "vhc:u:")) != -1) switch (ch) { case 'v': Verbose++; break; case 'c': + if (uid) { + printf("Error:: can`t chroot, please run as root!\n"); + goto end; + } if (access(optarg, R_OK)) { printf("Error:: can`t chroot to %s #%d - %s\n", optarg, errno, strerror(errno)); goto end; } else strlcpy(szChroot, optarg, MAXPATHLEN); + status |= 1; break; + case 'u': + if (uid) { + printf("Error:: can`t setuid, please run as root!\n"); + goto end; + } + pass = getpwnam(optarg); + if (!pass) { + printf("Error:: can`t find user %s\n", optarg); + goto end; + } else + uid = pass->pw_uid; + endpwent(); + status |= 2; + break; case 'h': default: Usage(); @@ -72,8 +94,7 @@ main(int argc, char **argv) Usage(); goto end; } else - strlcpy(szRun, *argv, MAXPATHLEN); - VERB(2) printf("Info:: Chroot=%s Run=%s\n", szChroot, szRun); + VERB(2) printf("Info:: Chroot=%s Run=%s\n", szChroot, *argv); memset(&sa, 0, sizeof sa); sa.sa_handler = sigHand; @@ -89,26 +110,42 @@ main(int argc, char **argv) sigaction(SIGSTOP, &sa, NULL); VERB(5) printf("Info:: Catched signals ...\n"); - if ((ret = chroot(szChroot)) == -1) { + if (status & 1 && (ret = chroot(szChroot)) == -1) { printf("Error:: error in chroot to %s #%d - %s\n", szChroot, errno, strerror(errno)); ret = 3; goto end; } else VERB(1) printf("Info:: chrooted to %s\n", szChroot); + if (status & 2 && setuid(uid) == -1) { + printf("Error:: error in setuid to %u #%d - %s\n", uid, errno, strerror(errno)); + ret = 4; + goto end; + } else + VERB(1) printf("Info:: setuid to %u\n", uid); + + status ^= status; while (!Kill) switch ((ret = fork())) { case -1: printf("Error:: error in fork #%d - %s\n", errno, strerror(errno)); - ret = 4; + ret = 5; goto end; case 0: + VERB(3) printf("Info:: I`m child of shadows ...\n"); + if (execvp(*argv, argv) == -1) { + printf("Error:: error in exec %s #%d - %s\n", + *argv, errno, strerror(errno)); + ret = 6; + goto end; + } + /* never reached */ break; default: - waitpid(ret, &status, 0); + wait(&status); + kill(ret, SIGTERM); + ret = status; } - - ret = 0; end: return ret; }