Annotation of embedtools/src/cfexec.c, revision 1.2.2.2
1.1 misho 1: /*************************************************************************
2: * (C) 2009 AITNET - Sofia/Bulgaria - <office@aitbg.com>
3: * by Michael Pounov <misho@aitbg.com>
4: *
5: * $Author: misho $
1.2.2.2 ! misho 6: * $Id: cfexec.c,v 1.2.2.1 2011/06/13 20:04:12 misho Exp $
1.1 misho 7: *
1.2.2.2 ! 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:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
! 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.1 misho 46: #include "global.h"
47:
48:
49: sl_config cfg;
50: int Verbose, Timeout, kq;
51: char szUser[MAX_STR], szMount[MAXPATHLEN], szDev[MAXPATHLEN],
52: szChroot[MAXPATHLEN], szSess[MAXPATHLEN], szConfig[MAXPATHLEN];
53: extern char compiled[], compiledby[], compilehost[];
54:
1.2 misho 55:
1.1 misho 56: static void Usage()
57: {
58:
59: printf( "CFExec is tool for managment R/W operation with CompactFlash\n"
60: "=== %s === %s@%s ===\n\n"
61: " Syntax: cfexec [options] [exec_file]\n\n"
62: "\t-v\t\tVerbose ...\n"
63: "\t-c <dir>\tAfter execute chroot to dir [default=/]\n"
64: "\t-u <user>\tAfter execute suid to user [default=root]\n"
1.2 misho 65: "\t-d <dev>\tOther device [default=/dev/ufs/elwix]\n"
1.1 misho 66: "\t-m <mnt>\tOther mount dir [default=/cf]\n"
67: "\t-t <sec>\tTimeout for autolock mount dir after seconds [default=300]\n"
68: "\n", compiled, compiledby, compilehost);
69: }
70:
71: static int update(int flags)
72: {
73: struct ufs_args mnt;
74:
75: memset(&mnt, 0, sizeof mnt);
76: mnt.fspec = szDev;
1.2.2.1 misho 77: #ifdef __NetBSD__
78: if (mount("ufs", szMount, flags, &mnt, sizeof mnt) == -1) {
79: #else
1.1 misho 80: if (mount("ufs", szMount, flags, &mnt) == -1) {
1.2.2.1 misho 81: #endif
1.1 misho 82: printf("Error:: can`t update mount %s #%d - %s\n", szMount, errno, strerror(errno));
83: return -1;
84: }
85:
86: VERB(5) printf("Info(5):: safe mount for device %s to %s operation (%s)\n",
87: szDev, szMount, (flags & MNT_RDONLY) ? "ro" : "rw");
88: return 0;
89: }
90:
91: static void setuser()
92: {
93: struct passwd *pw;
94:
95: pw = getpwnam(szUser);
96: if (pw) {
97: setuid(pw->pw_uid);
98: setgid(pw->pw_gid);
99: endpwent();
100:
101: VERB(5) printf("Info(5):: Suid to user %s.\n", szUser);
102: } else
103: VERB(5) printf("Info(5):: Can`t suid to user %s !\n", szUser);
104: }
105:
106: static int mkevent(struct kevent *chg, struct kevent *evt)
107: {
108: int f;
109: char szStr[MAX_STR];
110:
111: f = open(szSess, O_CREAT | O_WRONLY | O_TRUNC, 0644);
112: if (f == -1) {
113: printf("Error:: can`t lock session #%d - %s\n", errno, strerror(errno));
114: return -1;
115: } else {
116: memset(szStr, 0, MAX_STR);
117: snprintf(szStr, MAX_STR, "%d", getpid());
118: write(f, szStr, strlen(szStr));
119: }
120: VERB(3) printf("Created lock file %s\n", szSess);
121:
122: kq = kqueue();
123: if (kq == -1) {
124: printf("Error:: can`t execute safe mount #%d - %s\n", errno, strerror(errno));
125: close(f);
126: unlink(szSess);
127: return -1;
128: } else {
129: memset(chg, 0, sizeof(struct kevent));
130: memset(evt, 0, sizeof(struct kevent));
131:
1.2.2.1 misho 132: EV_SET(chg, f, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME | NOTE_REVOKE, 0, (intptr_t) NULL);
1.1 misho 133: }
134:
135: return f;
136: }
137:
138: // ---------------------------------
139:
140: int main(int argc, char **argv)
141: {
142: char ch;
1.2.2.1 misho 143: const char *err = NULL;
1.1 misho 144: struct kevent chg, evt;
145: struct timespec ts;
146: pid_t pid;
147: int f, stat = 0;
148: // sigset_t sig, oldsig;
149:
150: strlcpy(szConfig, DEFAULT_CONFIG, MAXPATHLEN);
151: // Load variables from config if exists
152: if (!LoadConfig(szConfig, &cfg)) {
153: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("timeout"), CFG(szUser), MAX_STR, DEFAULT_TIMEOUT);
1.2.2.1 misho 154: #ifndef HAVE_STRTONUM
155: Timeout = (int) strtol(szUser, NULL, 0);
156: #else
1.2 misho 157: Timeout = strtonum(szUser, 0, 3600, &err);
1.2.2.1 misho 158: #endif
1.2 misho 159: if (!Timeout && err) {
1.1 misho 160: printf("Error:: in seconds for timeout %s - %s\n", optarg, err);
161: UnloadConfig(&cfg);
162: return 1;
163: }
164: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("suid"), CFG(szUser), MAX_STR, DEFAULT_USER);
165: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("mount"), CFG(szMount), MAXPATHLEN, DEFAULT_MOUNT);
166: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("device"), CFG(szDev), MAXPATHLEN, DEFAULT_DEVICE);
167: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("chroot"), CFG(szChroot), MAXPATHLEN, DEFAULT_CHROOT);
168:
169: UnloadConfig(&cfg);
170: } else {
171: Timeout = atoi(DEFAULT_TIMEOUT);
172: strlcpy(szUser, DEFAULT_USER, MAX_STR);
173: strlcpy(szMount, DEFAULT_MOUNT, MAXPATHLEN);
174: strlcpy(szDev, DEFAULT_DEVICE, MAXPATHLEN);
175: strlcpy(szChroot, DEFAULT_CHROOT, MAXPATHLEN);
176: }
177:
178: // Load variables from arguments if exists
179: while ((ch = getopt(argc, argv, "hvu:c:d:m:t:")) != -1)
180: switch (ch) {
181: case 'v':
182: Verbose++;
183: break;
184: case 'u':
185: strlcpy(szUser, optarg, MAX_STR);
186: break;
187: case 'c':
188: strlcpy(szChroot, optarg, MAXPATHLEN);
189: break;
190: case 'd':
191: strlcpy(szDev, optarg, MAXPATHLEN);
192: break;
193: case 'm':
194: strlcpy(szMount, optarg, MAXPATHLEN);
195: break;
196: case 't':
1.2.2.1 misho 197: #ifndef HAVE_STRTONUM
198: Timeout = (int) strtol(szUser, NULL, 0);
199: #else
1.2 misho 200: Timeout = strtonum(optarg, 0, 3600, &err);
1.2.2.1 misho 201: #endif
1.2 misho 202: if (!Timeout && err) {
1.1 misho 203: printf("Error:: in seconds for timeout %s - %s\n",
204: optarg, err);
205: return 1;
206: }
207: break;
208: case 'h':
209: default:
210: Usage();
211: return 1;
212: }
213: argc -= optind;
214: argv += optind;
215:
216: memset(szSess, 0, MAXPATHLEN);
217: snprintf(szSess, MAXPATHLEN, "%s%s-cfexec.LCK", DEFAULT_TMP, szMount);
218:
219: VERB(3) printf("Info(3):: Chroot=%s SUID=%s Device=%s Mount=%s Timeout=%d Session=%s\n",
220: szChroot, szUser, szDev, szMount, Timeout, szSess);
221:
222: if (!access(szSess, F_OK)) {
223: printf("cfexec already running ...\n");
224: return 127;
225: }
226:
227: if (!argc) {
228: switch (fork()) {
229: case -1:
230: printf("Error:: can`t execute safe mount #%d - %s\n",
231: errno, strerror(errno));
232: return 3;
233: case 0:
234: VERB(5) printf("Info(5):: Go safe mount.\n");
235: setsid();
236:
237: if (update(MNT_UPDATE) == -1)
238: return 4;
239:
240: if ((f = mkevent(&chg, &evt)) == -1)
241: return 5;
242:
1.2 misho 243: if (Timeout) {
244: memset(&ts, 0, sizeof ts);
245: ts.tv_sec = Timeout;
246: }
247: switch (kevent(kq, &chg, 1, &evt, 1, !Timeout ? NULL : &ts)) {
1.1 misho 248: case -1:
249: printf("Error:: can`t execute safe mount #%d - %s\n",
250: errno, strerror(errno));
251: stat = 7;
252: break;
253: case 0:
254: VERB(1) printf("Timeout reached - secure mount\n");
255: default:
256: VERB(1) printf("Lock file is deleted - secure mount\n");
257: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
258: stat = 8;
259: }
260:
261: close(kq);
262: close(f);
263: unlink(szSess);
264: break;
265: }
266: } else {
267: /*
268: sigemptyset(&sig);
269: sigaddset(&sig, SIGINT);
270: sigaddset(&sig, SIGTSTP);
271: sigprocmask(SIG_BLOCK, &sig, &oldsig);
272: */
273:
274: if (update(MNT_UPDATE) == -1)
275: return 4;
276:
277: switch ((pid = vfork())) {
278: case -1:
279: printf("Error:: can`t execute safe mount #%d - %s\n",
280: errno, strerror(errno));
281: return 5;
282: case 0:
283: VERB(5) printf("Go to running process %s\n", *argv);
284: if (chroot(szChroot) == -1) {
285: printf("Error:: can`t chroot to dir %s #%d - %s\n",
286: szChroot, errno, strerror(errno));
287: } else {
288: if (strncmp(szUser, "root", 5))
289: setuser();
290:
1.2 misho 291: /* chdir("/"); */
1.1 misho 292: execvp(*argv, argv);
293: }
294: _exit(127);
295: break;
296: default:
297: waitpid(pid, &stat, 0);
298: VERB(3) printf("Return code: %d\n", stat);
299: if (stat == 32512)
300: stat = 127;
301:
302: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
303: return 8;
304: }
305:
306: // sigprocmask(SIG_SETMASK, &oldsig, NULL);
307: }
308:
309: return stat;
310: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>