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