diff options
author | Jacob Moody <moody@posixcafe.org> | 2022-06-07 05:38:08 +0000 |
---|---|---|
committer | Jacob Moody <moody@posixcafe.org> | 2022-06-07 05:38:08 +0000 |
commit | 056ad652a41fde51755aedb8119b37fe5946b12c (patch) | |
tree | 2ecb31ea6377c356ec010ebc954b46c60f2b829a /sys/src/cmd/auth | |
parent | f4840cdba548979969cb2ad25b4c6acbc3e63f8c (diff) |
auth/box: build restricted namespaces using components from the parent.
Diffstat (limited to 'sys/src/cmd/auth')
-rw-r--r-- | sys/src/cmd/auth/box.c | 192 | ||||
-rw-r--r-- | sys/src/cmd/auth/mkfile | 1 |
2 files changed, 193 insertions, 0 deletions
diff --git a/sys/src/cmd/auth/box.c b/sys/src/cmd/auth/box.c new file mode 100644 index 000000000..779cd0f9d --- /dev/null +++ b/sys/src/cmd/auth/box.c @@ -0,0 +1,192 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> + +static int debug; + +static void +binderr(char *new, char *old, int flag) +{ + char dash[4] = { '-' }; + + if(debug){ + if(flag & MCREATE){ + dash[2] = 'c'; + flag &= ~MCREATE; + } + switch(flag){ + case MREPL: + dash[0] = ' '; + if(dash[2] == 'c') + dash[1] = '-'; + else + dash[1] = ' '; + break; + case MBEFORE: + dash[1] = 'b'; + break; + case MAFTER: + dash[1] = 'a'; + break; + } + print("bind %s %s %s\n", dash, new, old); + } + if(bind(new, old, flag) < 0) + sysfatal("bind: %r"); +} + +static void +resolvenames(char **names, int nname) +{ + int i; + char buf[8192]; + int fd; + + fd = open(".", OREAD|OCEXEC); + if(fd < 0) + sysfatal("could not open .: %r"); + fd2path(fd, buf, sizeof buf); + for(i = 0; i < nname; i++){ + if(names[i] == nil) + continue; + cleanname(names[i]); + switch(names[i][0]){ + case '#': + case '/': + break; + case '.': + if(names[i][1] == '/') + break; + default: + names[i] = cleanname(smprint("%s/%s", buf, names[i])); + } + } + close(fd); +} + +static void +sandbox(char **names, int *flags, int nname) +{ + char *parts[32]; + char rootskel[128]; + char src[8192], targ[8192], dir[8192], skel[8192]; + char name[8192]; + char *newroot; + Dir *d; + int i, j, n; + + snprint(rootskel, sizeof rootskel, "#zd/newroot.%d", getpid()); + binderr(rootskel, "/", MBEFORE); + + newroot = rootskel + strlen("#zd"); + + for(j = 0; j < nname; j++){ + if(names[j] == nil) + continue; + utfecpy(name, &name[sizeof name-1], names[j]); + n = gettokens(name, parts, nelem(parts), "/"); + utfecpy(targ, &targ[sizeof targ-1], newroot); + memset(src, 0, sizeof src); + for(i = 0; i < n; i++){ + utfecpy(dir, &dir[sizeof dir-1], targ); + snprint(targ, sizeof targ, "%s/%s", targ, parts[i]); + snprint(src, sizeof src, "%s/%s", src, parts[i]); + d = dirstat(targ); + if(d != nil){ + free(d); + continue; + } + d = dirstat(src); + if(d == nil) + continue; + if(d->mode & DMDIR) + snprint(skel, sizeof skel, "#zd/%s", parts[i]); + else + snprint(skel, sizeof skel, "#zf/%s", parts[i]); + free(d); + binderr(skel, dir, MBEFORE); + } + binderr(names[j], targ, flags[j]); + } + binderr(newroot, "/", MREPL); +} + +static void +run(char **a) +{ + exec(a[0], a); + + if(a[0][0] != '/' && a[0][0] != '#' && + (a[0][0] != '.' || (a[0][1] != '/' && + (a[0][1] != '.' || a[0][2] != '/')))) + exec(smprint("/bin/%s", a[0]), a); + + sysfatal("exec: %s: %r", a[0]); +} + +void +usage(void) +{ + fprint(2, "usage %s: [ -d ] [ -r file ] [ -c dir ] [ -e devs ] cmd args...\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char devs[1024]; + int dfd; + char *parts[256]; + int mflags[256]; + int nparts; + + nparts = 0; + memset(devs, 0, sizeof devs); + ARGBEGIN{ + case 'd': + debug = 1; + break; + case 'r': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MREPL; + break; + case 'c': + parts[nparts] = EARGF(usage()); + mflags[nparts++] = MCREATE|MREPL; + break; + case 'e': + snprint(devs, sizeof devs, "%s%s", devs, EARGF(usage())); + break; + default: + usage(); + break; + }ARGEND + if(argc == 0) + usage(); + + rfork(RFNAMEG|RFENVG); + dfd = open("/dev/drivers", OWRITE|OCEXEC); + if(dfd < 0) + sysfatal("could not /dev/drivers: %r"); + + resolvenames(parts, nparts); + + if(procsetuser("none") < 0) + sysfatal("cant become none: %r"); + putenv("user", "none"); + + sandbox(parts, mflags, nparts); + + if(debug) + print("chdev %s\n", devs); + + if(devs[0] != '\0'){ + if(fprint(dfd, "chdev & %s", devs) <= 0) + sysfatal("could not write chdev: %r"); + } else { + if(fprint(dfd, "chdev ~") <= 0) + sysfatal("could not write chdev: %r"); + } + close(dfd); + run(argv); +} diff --git a/sys/src/cmd/auth/mkfile b/sys/src/cmd/auth/mkfile index f8f6ec829..1dbc46941 100644 --- a/sys/src/cmd/auth/mkfile +++ b/sys/src/cmd/auth/mkfile @@ -9,6 +9,7 @@ TARG=\ asn1dump\ asn12rsa\ authsrv\ + box\ changeuser\ convkeys\ cron\ |