int main(int argc, char **argv) { unsigned pid = 0; int i; // handle CTRL-C signal (SIGINT, my_handler); signal (SIGTERM, my_handler); for (i = 1; i < argc; i++) { // default options if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-?") == 0) { usage(); return 0; } else if (strcmp(argv[i], "--version") == 0) { printf("firemon version %s\n\n", VERSION); return 0; } // options without a pid argument else if (strcmp(argv[i], "--top") == 0) { top(); // never to return } else if (strcmp(argv[i], "--list") == 0) { list(); return 0; } else if (strcmp(argv[i], "--netstats") == 0) { struct stat s; if (getuid() != 0 && stat("/proc/sys/kernel/grsecurity", &s) == 0) { fprintf(stderr, "Error: this feature is not available on Grsecurity systems\n"); exit(1); } netstats(); return 0; } // cumulative options with or without a pid argument else if (strcmp(argv[i], "--x11") == 0) { arg_x11 = 1; } else if (strcmp(argv[i], "--cgroup") == 0) { arg_cgroup = 1; } else if (strcmp(argv[i], "--cpu") == 0) { arg_cpu = 1; } else if (strcmp(argv[i], "--seccomp") == 0) { arg_seccomp = 1; } else if (strcmp(argv[i], "--caps") == 0) { arg_caps = 1; } else if (strcmp(argv[i], "--tree") == 0) { arg_tree = 1; } else if (strcmp(argv[i], "--interface") == 0) { arg_interface = 1; } else if (strcmp(argv[i], "--route") == 0) { arg_route = 1; } else if (strcmp(argv[i], "--arp") == 0) { arg_arp = 1; } else if (strncmp(argv[i], "--name=", 7) == 0) { char *name = argv[i] + 7; if (name2pid(name, (pid_t *) &pid)) { fprintf(stderr, "Error: cannot find sandbox %s\n", name); return 1; } } // etc else if (strcmp(argv[i], "--nowrap") == 0) arg_nowrap = 1; // invalid option else if (*argv[i] == '-') { fprintf(stderr, "Error: invalid option\n"); return 1; } // PID argument else { // this should be a pid number char *ptr = argv[i]; while (*ptr != '\0') { if (!isdigit(*ptr)) { fprintf(stderr, "Error: not a valid PID number\n"); exit(1); } ptr++; } sscanf(argv[i], "%u", &pid); break; } } if (arg_tree) tree((pid_t) pid); if (arg_interface) interface((pid_t) pid); if (arg_route) route((pid_t) pid); if (arg_arp) arp((pid_t) pid); if (arg_seccomp) seccomp((pid_t) pid); if (arg_caps) caps((pid_t) pid); if (arg_cpu) cpu((pid_t) pid); if (arg_cgroup) cgroup((pid_t) pid); if (arg_x11) x11((pid_t) pid); if (!arg_route && !arg_arp && !arg_interface && !arg_tree && !arg_caps && !arg_seccomp && !arg_x11) procevent((pid_t) pid); // never to return return 0; }
int main(int argc, char *argv[]) { int c; int fd; char path[PATH_MAX]; int nsid; int pid; int tdf; static struct sched_param sp; while ((c = getopt(argc, argv, "+cdn:t:pa:g:r:vh")) != -1) { switch(c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ if (getpgrp() == getpid()) { switch(fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); break; case 'n': // /* run in network and mount namespaces */ // if (unshare(CLONE_NEWNET|CLONE_NEWNS) == -1) { // perror("unshare"); // return 1; // } tdf = atoi(optarg); /* run in network, mount namespaces and set dilation */ if (virtualtimeunshare(CLONE_NEWNET|CLONE_NEWNS, tdf) == -1) { perror("virtualtimeunshare"); return 1; } /* mount sysfs to pick up the new network namespace */ if (mount("sysfs", "/sys", "sysfs", MS_MGC_VAL, NULL) == -1) { perror("mount"); return 1; } break; case 't': tdf = atoi(optarg); int ppid = getppid(); // maybe ppid, by which we ID host, should give as argument parameter /* try set tdf to be another value */ if (settimedilationfactor(tdf, ppid) == -1) { perror("settimedilationfactor"); printf("[process %d child of %d] settimedilationfactor fail\n", getpid(), getppid()); return 1; } // printf("[process %d child of %d] settimedilationfactor success\n", getpid(), getppid()); break; case 'p': /* print pid */ printf("\001%d\n", getpid()); fflush(stdout); break; case 'a': /* Attach to pid's network namespace and mount namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/net", pid); nsid = open(path, O_RDONLY); if (nsid < 0) { perror(path); return 1; } if (setns(nsid, 0) != 0) { perror("setns"); return 1; } /* Plan A: call setns() to attach to mount namespace */ sprintf(path, "/proc/%d/ns/mnt", pid); nsid = open(path, O_RDONLY); if (nsid < 0 || setns(nsid, 0) != 0) { char *cwd = get_current_dir_name(); /* Plan B: chroot/chdir into pid's root file system */ sprintf(path, "/proc/%d/root", pid); if (chroot(path) < 0) { perror(path); return 1; } /* need to chdir to correct working directory */ if (chdir(cwd) != 0) { perror(cwd); return 1; } } break; case 'g': /* Attach to cgroup */ cgroup(optarg); break; case 'r': /* Set RT scheduling priority */ sp.sched_priority = atoi(optarg); if (sched_setscheduler(getpid(), SCHED_RR, &sp) < 0) { perror("sched_setscheduler"); return 1; } break; case 'v': printf("%s\n", VERSION); exit(0); case 'h': usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } } if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } // usage(argv[0]); return 0; }
int main(int argc, char *argv[]) { int c; int fd; char path[PATH_MAX]; int nsid; int pid; char *cwd = get_current_dir_name(); static struct sched_param sp; while ((c = getopt(argc, argv, "+cdnpa:g:r:vh")) != -1) switch(c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ if (getpgrp() == getpid()) { switch(fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); break; case 'n': /* run in network and mount namespaces */ if (unshare(CLONE_NEWNET|CLONE_NEWNS) == -1) { perror("unshare"); return 1; } /* Mark our whole hierarchy recursively as private, so that our * mounts do not propagate to other processes. */ if (mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL) == -1) { perror("remount"); return 1; } /* mount sysfs to pick up the new network namespace */ if (mount("sysfs", "/sys", "sysfs", MS_MGC_VAL, NULL) == -1) { perror("mount"); return 1; } break; case 'p': /* print pid */ printf("\001%d\n", getpid()); fflush(stdout); break; case 'a': /* Attach to pid's network namespace and mount namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/net", pid); nsid = open(path, O_RDONLY); if (nsid < 0) { perror(path); return 1; } if (setns(nsid, 0) != 0) { perror("setns"); return 1; } /* Plan A: call setns() to attach to mount namespace */ sprintf(path, "/proc/%d/ns/mnt", pid); nsid = open(path, O_RDONLY); if (nsid < 0 || setns(nsid, 0) != 0) { /* Plan B: chroot/chdir into pid's root file system */ sprintf(path, "/proc/%d/root", pid); if (chroot(path) < 0) { perror(path); return 1; } } /* chdir to correct working directory */ if (chdir(cwd) != 0) { perror(cwd); return 1; } break; case 'g': /* Attach to cgroup */ cgroup(optarg); break; case 'r': /* Set RT scheduling priority */ sp.sched_priority = atoi(optarg); if (sched_setscheduler(getpid(), SCHED_RR, &sp) < 0) { perror("sched_setscheduler"); return 1; } break; case 'v': printf("%s\n", VERSION); exit(0); case 'h': usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } usage(argv[0]); return 0; }
int main(int argc, char *argv[]) { int c; int fd; char path[PATH_MAX]; int pid; int detach = 0; int netns = 0; int mountns = 0; int mountnspid = 0; int pidns = 0; int printpid = 0; int mountprocfs = 0; static struct sched_param sp; while ((c = getopt(argc, argv, "+cdnmiufpa:b:k:j:g:r:vh")) != -1) switch (c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ detach = 1; /* delay setsid() incase new PID namespace */ break; case 'n': /* run in network namespace */ if (unshare(CLONE_NEWNET) == -1) { perror("unshare"); return 1; } netns = NET_NS_CREATE; break; case 'm': /* run in mount namespace */ if (unshare(CLONE_NEWNS) == -1) { perror("unshare"); return 1; } /* mount sysfs to pick up the new network namespace */ mountns = MOUNT_NS_CREATE; /* delay mount of /sysfs */ break; case 'i': /* run in new PID namespace */ if (unshare(CLONE_NEWPID) == -1) { perror("unshare"); return 1; } pidns = PID_NS_CREATE; /* record creation of PID namespace */ break; case 'u': /* run in new UTS namespace */ if (unshare(CLONE_NEWUTS) == -1) { perror("unshare"); return 1; } break; case 'f': /* mount procfs (for new PID namespaces) */ mountprocfs = TRUE; /* delay mounting proc until new NS established */ break; case 'p': /* print pid */ printpid = TRUE; /* delay printing PID until after NS procesisng*/ break; case 'a': /* Attach to pid's network namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/net", pid); if (attachToNS(path) != 0) { return 1; } netns = NET_NS_JOIN; break; case 'b': /* Attach to pid's mount namespace */ mountns = MOUNT_NS_JOIN; /* delay joining mount namespace */ mountnspid = atoi(optarg); /* record PID to join */ break; case 'k': /* Attach to pid's PID namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/pid", pid); if (attachToNS(path) != 0) { return 1; } pidns = PID_NS_JOIN; /* record join of PID namespace */ break; case 'j': /* Attach to pid's UTS namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/uts", pid); if (attachToNS(path) != 0) { return 1; } break; case 'g': /* Attach to cgroup */ cgroup(optarg); break; case 'r': /* Set RT scheduling priority */ sp.sched_priority = atoi(optarg); if (sched_setscheduler(getpid(), SCHED_RR, &sp) < 0) { perror("sched_setscheduler"); return 1; } break; case 'v': printf("%s\n", VERSION); exit(0); case 'h': usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } /* fork to create / join PID namespace */ if (pidns == PID_NS_CREATE || pidns == PID_NS_JOIN) { int status = 0; pid_t pid = fork(); switch (pid) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ /* print global PID (not namespace PID)*/ if (printpid == 1) { printf("\001%d\n", pid); fflush(stdout); } /* wait on the PID to handle attachment for 'mx'*/ if (waitpid(pid, &status, 0) == -1) return 1; if (WIFEXITED(status)) /* caught child exit, forward return code*/ return WEXITSTATUS(status); else if (WIFSIGNALED(status)) kill(getpid(), WTERMSIG(status)); /* child exit failed, (although return won't distinguish) */ return 1; } } /* if requested, we are in the new/requested PID namespace */ /* completed performing other namespaces (PID/network) operations */ /* go ahead and join the mount namespace if requested */ if (mountns == MOUNT_NS_JOIN && mountnspid != FALSE) { sprintf(path, "/proc/%d/ns/mnt", pid); if (attachToNS(path) != 0) { return 1; } } /* if mount of procfs requested, check for pidns and mountns */ if (mountprocfs && (pidns != PID_NS_CREATE || mountns != MOUNT_NS_CREATE)) { /* requested procfs, but required PID and/or mount namespace missing */ return 1; } /* mount procfs to pick up the new PID namespace */ if (mountprocfs && (mount("none", "/proc", NULL, MS_PRIVATE | MS_REC, NULL) != 0 || mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL) != 0)) { perror("mount"); } /* mount sysfs to pick up the new PID namespace */ if (netns == NET_NS_CREATE && mountns == MOUNT_NS_CREATE) { if (mount("sysfs", "/sys", "sysfs", MS_MGC_VAL, NULL) == -1) { perror("mount"); return 1; } } /* setsid() if requested & required (not needed if using PID namespace) */ if (detach == 1 && pidns == FALSE) { if (getpgrp() == getpid()) { switch (fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); } /* print pid if requested (if in new namespace, we don't print local PID) */ if (printpid == 1 && pidns == 0) { printf("\001%d\n", getpid()); fflush(stdout); } /* launch if requested */ if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } usage(argv[0]); return 0; }
int main(int argc, char *argv[]) { int c; int fd; char path[PATH_MAX]; int nsid; int pid; static struct sched_param sp; while ((c = getopt(argc, argv, "+cdnpa:g:r:vh")) != -1) switch(c) { case 'c': /* close file descriptors except stdin/out/error */ for (fd = getdtablesize(); fd > 2; fd--) close(fd); break; case 'd': /* detach from tty */ if (getpgrp() == getpid()) { switch(fork()) { case -1: perror("fork"); return 1; case 0: /* child */ break; default: /* parent */ return 0; } } setsid(); break; case 'n': /* run in network namespace */ if (unshare(CLONE_NEWNET) == -1) { perror("unshare"); return 1; } break; case 'p': /* print pid */ printf("\001%d\n", getpid()); fflush(stdout); break; case 'a': /* Attach to pid's network namespace */ pid = atoi(optarg); sprintf(path, "/proc/%d/ns/net", pid ); nsid = open(path, O_RDONLY); if (nsid < 0) { perror(path); return 1; } if (setns(nsid, 0) != 0) { perror("setns"); return 1; } break; case 'g': /* Attach to cgroup */ cgroup(optarg); break; case 'r': /* Set RT scheduling priority */ sp.sched_priority = atoi(optarg); if (sched_setscheduler(getpid(), SCHED_RR, &sp) < 0) { perror("sched_setscheduler"); return 1; } break; case 'v': printf("%s\n", VERSION); exit(0); case 'h': usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } if (optind < argc) { execvp(argv[optind], &argv[optind]); perror(argv[optind]); return 1; } usage(argv[0]); }