1: /*************************************************************************
2: * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
3: * by Michael Pounov <misho@aitbg.com>
4: *
5: * $Author: misho $
6: * $Id: wdog.c,v 1.3.4.1 2014/01/30 01:03:27 misho Exp $
7: *
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:
15: Copyright 2004 - 2014
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: */
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>