Annotation of embedtools/src/wdog.c, revision 1.2.2.2

1.2       misho       1: /*************************************************************************
                      2:  * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
                      3:  *  by Michael Pounov <misho@aitbg.com>
                      4:  *
                      5:  * $Author: misho $
1.2.2.2 ! misho       6:  * $Id: wdog.c,v 1.2.2.1 2011/06/13 20:23:35 misho Exp $
1.2       misho       7:  *
1.2.2.1   misho       8:  *************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.2.2.2 ! misho      15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
1.2.2.1   misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
1.2       misho      46: #include "global.h"
                     47: 
                     48: 
                     49: int Verbose, Kill, Log;
                     50: extern char compiled[], compiledby[], compilehost[];
                     51: 
                     52: 
                     53: static void
                     54: Usage()
                     55: {
                     56: 
                     57:        printf( "WatchDog tool for risk process managment\n"
                     58:                "=== %s === %s@%s ===\n\n"
                     59:                "  Syntax: wdog [options] [exec_file]\n\n"
                     60:                "\t-v\t\tVerbose ...\n"
                     61:                "\t-c <dir>\tBefore execute chroot to dir [default=/]\n"
                     62:                "\t-u <user>\tBefore execute change user\n"
                     63:                "\t-P\t\tInfinit loop, bypass penalty timeout\n"
                     64:                "\t-S\t\tDisable send log events to syslog\n"
                     65:                "\n", compiled, compiledby, compilehost);
                     66: }
                     67: 
                     68: static void
                     69: sigHand(int sig)
                     70: {
                     71:        int stat;
                     72: 
                     73:        switch (sig) {
                     74:                case SIGTERM:
                     75:                        Kill++;
                     76:                        break;
                     77:                case SIGCHLD:
                     78:                        while (waitpid(-1, &stat, WNOHANG) > 0);
                     79:                        break;
                     80:        }
                     81: }
                     82: 
                     83: static void
                     84: logmsg(int prio, const char *fmt, ...)
                     85: {
                     86:        va_list lst;
                     87: 
                     88:        va_start(lst, fmt);
                     89:        if (!Log)
                     90:                vsyslog(prio, fmt, lst);
                     91:        else
                     92:                vprintf(fmt, lst);
                     93:        va_end(lst);
                     94: }
                     95: 
                     96: 
                     97: int
                     98: main(int argc, char **argv)
                     99: {
                    100:        char ch, bypass = 0, szChroot[MAXPATHLEN] = DEFAULT_CHROOT;
                    101:        int status = 0, ret = 1;
                    102:        struct sigaction sa;
                    103:        struct passwd *pass = NULL;
                    104:        u_int penalty = 1;
                    105:        uid_t uid = getuid();
                    106: 
                    107:        while ((ch = getopt(argc, argv, "vhSPc:u:")) != -1)
                    108:                switch (ch) {
                    109:                        case 'v':
                    110:                                Verbose++;
                    111:                                break;
                    112:                        case 'P':
                    113:                                bypass = 1;
                    114:                                break;
                    115:                        case 'S':
                    116:                                Log = 1;
                    117:                                break;
                    118:                        case 'c':
                    119:                                if (uid) {
                    120:                                        printf("Error:: can`t chroot, please run as root!\n");
                    121:                                        goto end;
                    122:                                }
                    123:                                if (access(optarg, R_OK)) {
                    124:                                        printf("Error:: can`t chroot to %s #%d - %s\n", optarg, 
                    125:                                                        errno, strerror(errno));
                    126:                                        goto end;
                    127:                                } else
                    128:                                        strlcpy(szChroot, optarg, MAXPATHLEN);
                    129:                                status |= 1;
                    130:                                break;
                    131:                        case 'u':
                    132:                                if (uid) {
                    133:                                        printf("Error:: can`t setuid, please run as root!\n");
                    134:                                        goto end;
                    135:                                }
                    136:                                pass = getpwnam(optarg);
                    137:                                if (!pass) {
                    138:                                        printf("Error:: can`t find user %s\n", optarg);
                    139:                                        goto end;
                    140:                                } else
                    141:                                        uid = pass->pw_uid;
                    142:                                endpwent();
                    143:                                status |= 2;
                    144:                                break;
                    145:                        case 'h':
                    146:                        default:
                    147:                                Usage();
                    148:                                goto end;
                    149:                }
                    150:        argc -= optind;
                    151:        argv += optind;
                    152:        if (!argc || !argv || !*argv) {
                    153:                Usage();
                    154:                goto end;
                    155:        }
                    156: 
                    157:        if (!Log)
                    158:                openlog("wdog", LOG_PID, LOG_USER);
                    159: 
                    160:        VERB(2) logmsg(LOG_NOTICE, "Info:: Chroot=%s Run=%s\n", szChroot, *argv);
                    161: 
                    162:        memset(&sa, 0, sizeof sa);
                    163:        sa.sa_handler = sigHand;
                    164:        sigemptyset(&sa.sa_mask);
                    165:        sigaction(SIGTERM, &sa, NULL);
                    166:        sigaction(SIGCHLD, &sa, NULL);
                    167:        sa.sa_handler = SIG_IGN;
                    168:        sigaction(SIGHUP, &sa, NULL);
                    169:        sigaction(SIGINT, &sa, NULL);
                    170:        sigaction(SIGQUIT, &sa, NULL);
                    171:        sigaction(SIGPIPE, &sa, NULL);
                    172:        sigaction(SIGTSTP, &sa, NULL);
                    173:        sigaction(SIGSTOP, &sa, NULL);
                    174:        VERB(5) logmsg(LOG_NOTICE, "Info:: Catched signals ...\n");
                    175: 
                    176:        if (status & 1 && (ret = chroot(szChroot)) == -1) {
                    177:                printf("Error:: error in chroot to %s #%d - %s\n", szChroot, errno, strerror(errno));
                    178:                ret = 3;
                    179:                goto end;
                    180:        } else
                    181:                VERB(1) logmsg(LOG_NOTICE, "Info:: chrooted to %s\n", szChroot);
                    182: 
                    183:        if (status & 2 && setuid(uid) == -1) {
                    184:                printf("Error:: error in setuid to %u #%d - %s\n", uid, errno, strerror(errno));
                    185:                ret = 4;
                    186:                goto end;
                    187:        } else
                    188:                VERB(1) logmsg(LOG_NOTICE, "Info:: setuid to %u\n", uid);
                    189: 
                    190:        status ^= status;
                    191:        while (!Kill && penalty) {
                    192:                switch ((ret = fork())) {
                    193:                        case -1:
                    194:                                logmsg(LOG_ERR, "Error:: error in fork #%d - %s\n", errno, strerror(errno));
                    195:                                ret = 5;
                    196:                                goto end;
                    197:                        case 0:
                    198:                                VERB(3) logmsg(LOG_NOTICE, "Info:: I`m child of shadows ...\n");
                    199:                                if (execvp(*argv, argv) == -1) {
                    200:                                        logmsg(LOG_ERR, "Error:: error in exec %s #%d - %s\n", 
                    201:                                                        *argv, errno, strerror(errno));
                    202:                                        ret = 6;
                    203:                                        goto end;
                    204:                                }
                    205:                                /* never reached !!! */
                    206:                                break;
                    207:                        default:
                    208:                                wait(&status);
                    209:                                kill(ret, SIGTERM);
                    210:                                ret = status;
                    211:                }
                    212:                /* penalty timeout retry */
                    213:                usleep(penalty);
                    214:                if (!bypass) {
                    215:                        penalty <<= 1;
                    216:                        VERB(2) logmsg(LOG_NOTICE, "Info:: penalty timeout %u microseconds\n", penalty);
                    217:                }
                    218:        }
                    219:        if (!penalty)
                    220:                ret = 9;
                    221: end:
                    222:        if (!Log)
                    223:                closelog();
                    224:        return ret;
                    225: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>