@@ -26,10 +26,6 @@
2626using namespace std;
2727
2828#define err_exit(format, ...) { fprintf(stderr, format ": %s\n", ##__VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE); }
29−static int child_proc(const char *rootdir, const char *nixdir, uint8_t clear_env, list<struct DirMapping> dirMappings, list<struct SetEnv> envMappings, const char *executable, char * const new_argv[]);
30−
31−volatile uint8_t child_died = 0;
32−int child_pid = 0;
3329
3430static void usage(const char *pname) {
3531 fprintf(stderr, "Usage: %s -n <nixpath> -- <command>\n", pname);
@@ -37,7 +33,6 @@ static void usage(const char *pname) {
3733 fprintf(stderr, "\t-m <src>:<src>\tmap src on the host to dest in the sandbox\n");
3834 fprintf(stderr, "\t-d\tdelete all default dir mappings, may break things\n");
3935 fprintf(stderr, "\t-p <var>\tpreserve the value of a variable across the -c clear\n");
40− fprintf(stderr, "\t-e\tadd an /escape-hatch to the sandbox, and run (outside the sandbox) any strings written to it\n");
4136
4237 exit(EXIT_FAILURE);
4338}
@@ -96,15 +91,8 @@ struct DirMapping parseMapping(string input) {
9691 return (struct DirMapping){ src, dest };
9792}
9893
99−static void handle_child_death(int signo, siginfo_t *info, void *context) {
100− if ( (child_pid == 0) || (info->si_pid == child_pid) ) {
101− child_died = 1;
102− }
103−}
104−
10594int main(int argc, char *argv[]) {
10695 uint8_t clear_env = 0;
107− uint8_t enable_escape_hatch = 0;
10896 char *nixdir = NULL;
10997 list<struct DirMapping> dirMappings;
11098 list<struct SetEnv> envMappings;
@@ -119,19 +107,14 @@ int main(int argc, char *argv[]) {
119107 x("var");
120108 x("etc");
121109 x("usr");
122− x("home");
123− x("root");
124110#undef x
125111
126112 int opt;
127− while ((opt = getopt(argc, argv, "cen:m:dp:")) != -1) {
113+ while ((opt = getopt(argc, argv, "cn:m:dp:")) != -1) {
128114 switch (opt) {
129115 case 'c':
130116 clear_env = 1;
131117 break;
132− case 'e':
133− enable_escape_hatch = 1;
134− break;
135118 case 'n':
136119 // determine absolute directory for nix dir
137120 nixdir = realpath(optarg, NULL);
@@ -179,62 +162,6 @@ int main(int argc, char *argv[]) {
179162 err_exit("mkdtemp(%s)", template_);
180163 }
181164
182− int unrace[2];
183−
184− if (pipe(unrace)) {
185− err_exit("pipe()");
186− }
187−
188− struct sigaction handle_child;
189− handle_child.sa_sigaction = handle_child_death;
190− handle_child.sa_flags = SA_SIGINFO;
191−
192− struct sigaction old_handler;
193− if (sigaction(SIGCHLD, &handle_child, &old_handler)) {
194− err_exit("sigaction()");
195− }
196−
197− int child;
198− child = child_pid = fork();
199− if (child < 0) {
200− err_exit("fork()");
201− } else if (child == 0) {
202− sigaction(SIGCHLD, &old_handler, NULL);
203− close(unrace[1]);
204− char buf[10];
205− read(unrace[0], buf, 10);
206− close(unrace[0]);
207− return child_proc(rootdir, nixdir, clear_env, dirMappings, envMappings, argv[optind], argv + optind);
208− } else {
209− close(unrace[0]);
210− char fifopath[PATH_MAX];
211− if (enable_escape_hatch) {
212− snprintf(fifopath, PATH_MAX, "%s/escape-hatch", rootdir);
213− mkfifo(fifopath, 0600);
214− }
215− close(unrace[1]);
216− if (enable_escape_hatch) {
217− char buffer[1024];
218− while (!child_died) {
219− int fd = open(fifopath, O_RDONLY);
220− if (fd < 0) {
221− if (errno == EINTR) continue;
222− fprintf(stderr, "error opening escape-hatch: %s\n", strerror(errno));
223− continue;
224− }
225− int size = read(fd, buffer, 1024);
226− buffer[size] = 0;
227− system(buffer);
228− close(fd);
229− }
230− }
231− int status;
232− int ret = waitpid(child, &status, 0);
233− return WEXITSTATUS(status);
234− }
235−}
236−
237−static int child_proc(const char *rootdir, const char *nixdir, uint8_t clear_env, list<struct DirMapping> dirMappings, list<struct SetEnv> envMappings, const char *executable, char * const new_argv[]) {
238165 // get uid, gid before going to new namespace
239166 uid_t uid = getuid();
240167 gid_t gid = getgid();
@@ -242,7 +169,7 @@ static int child_proc(const char *rootdir, const char *nixdir, uint8_t clear_env
242169 // "unshare" into new namespace
243170 if (unshare(CLONE_NEWNS | CLONE_NEWUSER) < 0) {
244171 if (errno == EPERM) {
245− fputs("Run the following to enable unprivileged namespace use:\nsudo bash -c \"sysctl -w kernel.unprivileged_userns_clone=1 ; echo kernel.unprivileged_userns_clone=1 > /etc/sysctl.d/nix-user-chroot.conf\"\n\n", stderr);
172+ fputs("Run the following as root to enable unprivileged namespace use:\nsysctl -w kernel.unprivileged_userns_clone=1 ; echo kernel.unprivileged_userns_clone=1 > /etc/sysctl.d/nix-user-chroot.conf\n\n", stderr);
246173 exit(EXIT_FAILURE);
247174 } else {
248175 err_exit("unshare()");
@@ -275,7 +202,6 @@ static int child_proc(const char *rootdir, const char *nixdir, uint8_t clear_env
275202 int fd_setgroups = open("/proc/self/setgroups", O_WRONLY);
276203 if (fd_setgroups > 0) {
277204 write(fd_setgroups, "deny", 4);
278− close(fd_setgroups);
279205 }
280206
281207 // map the original uid/gid in the new ns
@@ -302,6 +228,6 @@ static int child_proc(const char *rootdir, const char *nixdir, uint8_t clear_env
302228 }
303229
304230 // execute the command
305− execvp(executable, new_argv);
306− err_exit("execvp(%s)", executable);
231+ execvp(argv[optind], argv + optind);
232+ err_exit("execvp(%s)", argv[optind]);
307233}