Skip to content

Commit 6dc15df

Browse files
committed
Revert "Use proot instead of nix-user-chroot."
This reverts commit f24309c.
1 parent 0692fad commit 6dc15df

File tree

4 files changed

+154
-4
lines changed

4 files changed

+154
-4
lines changed

default.nix

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ let
1616
inherit arx maketar;
1717
};
1818

19+
nix-user-chroot = callPackage ./nix-user-chroot.nix {};
20+
1921
nix-bootstrap = callPackage ./nix-bootstrap.nix {
20-
inherit makebootstrap;
22+
inherit nix-user-chroot makebootstrap;
2123
};
2224

2325
in {

nix-bootstrap.nix

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
{ stdenv, writeText, proot, makebootstrap }:
1+
{ stdenv, writeText, nix-user-chroot, makebootstrap }:
22

33
{ name, target, run }:
44

55
makebootstrap {
66
inherit name;
7-
startup = ".${proot}/bin/proot -b./nix:/nix ${target}${run}";
8-
targets = [ proot target ];
7+
startup = ".${nix-user-chroot}/bin/nix-user-chroot ./nix ${target}${run}";
8+
targets = [ nix-user-chroot target ];
99
}

nix-user-chroot.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#define _GNU_SOURCE
2+
#include <sched.h>
3+
#include <unistd.h>
4+
#include <stdlib.h>
5+
#include <sys/wait.h>
6+
#include <signal.h>
7+
#include <fcntl.h>
8+
#include <stdio.h>
9+
#include <string.h>
10+
#include <limits.h>
11+
#include <errno.h>
12+
#include <sys/mount.h>
13+
#include <sys/types.h>
14+
#include <dirent.h>
15+
#include <sys/stat.h>
16+
17+
#define err_exit(format, ...) { fprintf(stderr, format ": %s\n", ##__VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE); }
18+
19+
static void usage(char *pname) {
20+
fprintf(stderr, "Usage: %s <nixpath> <command>\n", pname);
21+
22+
exit(EXIT_FAILURE);
23+
}
24+
25+
static void update_map(char *mapping, char *map_file) {
26+
int fd;
27+
28+
fd = open(map_file, O_WRONLY);
29+
if (fd < 0) {
30+
err_exit("map open");
31+
}
32+
33+
int map_len = strlen(mapping);
34+
if (write(fd, mapping, map_len) != map_len) {
35+
err_exit("map write");
36+
}
37+
38+
close(fd);
39+
}
40+
41+
static void add_path(const char* name, const char* rootdir) {
42+
char path_buf[PATH_MAX];
43+
char path_buf2[PATH_MAX];
44+
45+
snprintf(path_buf, sizeof(path_buf), "/%s", name);
46+
47+
struct stat statbuf;
48+
if (stat(path_buf, &statbuf) < 0) {
49+
fprintf(stderr, "Cannot stat %s: %s\n", path_buf, strerror(errno));
50+
return;
51+
}
52+
53+
snprintf(path_buf2, sizeof(path_buf2), "%s/%s", rootdir, name);
54+
55+
if (S_ISDIR(statbuf.st_mode)) {
56+
mkdir(path_buf2, statbuf.st_mode & ~S_IFMT);
57+
if (mount(path_buf, path_buf2, "none", MS_BIND | MS_REC, NULL) < 0) {
58+
fprintf(stderr, "Cannot bind mount %s to %s: %s\n", path_buf, path_buf2, strerror(errno));
59+
}
60+
}
61+
}
62+
63+
int main(int argc, char *argv[]) {
64+
if (argc < 3) {
65+
usage(argv[0]);
66+
}
67+
68+
// Create skeleton root dir in temp. All dirs will be mounted here.
69+
char template[] = "/tmp/nixXXXXXX";
70+
char *rootdir = mkdtemp(template);
71+
if (!rootdir) {
72+
err_exit("mkdtemp(%s)", template);
73+
}
74+
75+
// determine absolute directory for nix dir
76+
char *nixdir = realpath(argv[1], NULL);
77+
if (!nixdir) {
78+
err_exit("realpath(%s)", argv[1]);
79+
}
80+
81+
// get uid, gid before going to new namespace
82+
uid_t uid = getuid();
83+
gid_t gid = getgid();
84+
85+
// "unshare" into new namespace
86+
if (unshare(CLONE_NEWNS | CLONE_NEWUSER) < 0) {
87+
err_exit("unshare()");
88+
}
89+
90+
// add necessary system stuff to rootdir namespace
91+
add_path("dev", rootdir);
92+
add_path("proc", rootdir);
93+
add_path("sys", rootdir);
94+
add_path("run", rootdir);
95+
add_path("tmp", rootdir);
96+
add_path("var", rootdir);
97+
98+
// make sure nixdir exists
99+
struct stat statbuf2;
100+
if (stat(nixdir, &statbuf2) < 0) {
101+
err_exit("stat(%s)", nixdir);
102+
}
103+
104+
// mount /nix to new namespace
105+
char path_buf[PATH_MAX];
106+
snprintf(path_buf, sizeof(path_buf), "%s/nix", rootdir);
107+
mkdir(path_buf, statbuf2.st_mode & ~S_IFMT);
108+
if (mount(nixdir, path_buf, "none", MS_BIND | MS_REC, NULL) < 0) {
109+
err_exit("mount(%s, %s)", nixdir, path_buf);
110+
}
111+
112+
// fixes issue #1 where writing to /proc/self/gid_map fails
113+
// see user_namespaces(7) for more documentation
114+
int fd_setgroups = open("/proc/self/setgroups", O_WRONLY);
115+
if (fd_setgroups > 0) {
116+
write(fd_setgroups, "deny", 4);
117+
}
118+
119+
// map the original uid/gid in the new ns
120+
char map_buf[1024];
121+
snprintf(map_buf, sizeof(map_buf), "%d %d 1", uid, uid);
122+
update_map(map_buf, "/proc/self/uid_map");
123+
snprintf(map_buf, sizeof(map_buf), "%d %d 1", gid, gid);
124+
update_map(map_buf, "/proc/self/gid_map");
125+
126+
// chroot to rootdir
127+
if (chroot(rootdir) < 0) {
128+
err_exit("chroot(%s)", rootdir);
129+
}
130+
131+
// execute the command
132+
execvp(argv[2], argv+2);
133+
err_exit("execvp(%s)", argv[2]);
134+
}

nix-user-chroot.nix

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{ stdenv, fetchFromGitHub }:
2+
3+
stdenv.mkDerivation {
4+
name = "nix-user-chroot";
5+
phases = [ "buildPhase" "installPhase" "fixupPhase" ];
6+
buildPhase = ''
7+
cp ${./nix-user-chroot.c} nix-user-chroot.c
8+
$CC nix-user-chroot.c -o nix-user-chroot
9+
'';
10+
installPhase = ''
11+
mkdir -p $out/bin/
12+
cp nix-user-chroot $out/bin/nix-user-chroot
13+
'';
14+
}

0 commit comments

Comments
 (0)