chaosblade
/
nsexec.c
154 строки · 3.3 Кб
1#define _GNU_SOURCE2#include <stdio.h>3#include <unistd.h>4#include <errno.h>5#include <sched.h>6#include <stdio.h>7#include <stdlib.h>8#include <string.h>9#include <fcntl.h>10#include <getopt.h>11#include <sys/types.h>12#include <sys/wait.h>13#include <sys/prctl.h>14#include <sys/stat.h>15#include <sys/syscall.h>16
17extern char** environ;18
19int enter_ns(int pid, const char* type) {20#ifdef __NR_setns21char path[64], selfpath[64];22snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, type);23snprintf(selfpath, sizeof(selfpath), "/proc/self/ns/%s", type);24
25struct stat oldns_stat, newns_stat;26if (stat(selfpath, &oldns_stat) == 0 && stat(path, &newns_stat) == 0) {27// Don't try to call setns() if we're in the same namespace already28if (oldns_stat.st_ino != newns_stat.st_ino) {29int newns = open(path, O_RDONLY);30if (newns < 0) {31return -1;32}33
34// Some ancient Linux distributions do not have setns() function35int result = syscall(__NR_setns, newns, 0);36close(newns);37return result < 0 ? -1 : 1;38}39}40#endif // __NR_setns41return 0;42}
43
44void sig(int signum){}45
46int main(int argc, char *argv[]) {47
48int target = 0;49char *cmd;50
51int stop = 0;52int opt;53int option_index = 0;54char *string = "st:mpuni";55
56int ipcns = 0;57int utsns = 0;58int netns = 0;59int pidns = 0;60int mntns = 0;61
62while((opt =getopt(argc, argv, string))!= -1) {63switch (opt) {64case 's':65stop = 1;66break;67case 't':68target = atoi(optarg);69break;70case 'm':71mntns = 1;72break;73case 'p':74pidns = 1;75break;76case 'u':77utsns = 1;78break;79case 'n':80netns = 1;81break;82case 'i':83ipcns = 1;84break;85default:86break;87}88}89
90// check target pid91if (target <= 0) {92fprintf(stderr, "%s is not a valid process ID\n", target);93return 1;94}95
96// pause97if(stop) {98char *pe = "pause";99prctl(PR_SET_NAME, pe);100signal(SIGCONT,sig);101pause();102char *nc = "nsexec";103prctl(PR_SET_NAME, nc);104}105
106// enter namespace107if(ipcns) {108enter_ns(target, "ipc");109}110
111if(utsns) {112enter_ns(target, "uts");113}114
115if(netns) {116enter_ns(target, "net");117}118
119if(pidns) {120enter_ns(target, "pid");121}122
123if(mntns) {124enter_ns(target, "mnt");125}126
127// fork exec128pid_t pid;129int status;130
131if((pid = fork())<0) {132status = -1;133} else if(pid == 0){134// args135int i,j=0;136char *args[256] = {NULL};137for(i = optind; i < argc; i++, j++) {138args[j] = argv[i];139}140execvp(argv[optind], args);141_exit(127);142} else {143while(waitpid(pid, &status, 0) < 0){144if(errno != EINTR){145status = -1;146break;147}148}149if(WIFEXITED(status)){150exit(WEXITSTATUS(status));151}152}153return 0;154}
155