This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
On 29 Dec 2016 20:47, Florian Weimer wrote: > On 12/29/2016 07:08 PM, Mike Frysinger wrote: > > does it help if you run all the tests in a unique net namespace ? > > i think our skel test framework should set up unique namespaces > > all the time anyways to prevent inadvertent leakage, and to handle > > issues like port collisions. > > This is an interesting idea. > > I don't see how I can set up interfaces in a network namespace as an > unprivileged user. it's trivial: - create a new user namespace - map current id to root - create all the namespaces you want (like net) - set up the loopback interface as needed - create a new user namespace (or not if you want to run as "root") - map root back to current id - run all tests against loopback the `unshare` program can be used to experiment (but it wouldn't be used by tests themselves). just run: $ id uid=8282(vapier) gid=100(users) groups=100(users) $ unshare -Urn # id uid=0(root) gid=0(root) groups=0(root) # ip a s dev lo 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # ip link set up dev lo # ip a s dev lo 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever here's some code below that i've written that should show how to do all of this. you can do: $ gcc -Wall quick-unshare.c -o quick-unshare $ ./quick-unshare -Un bash it would mean you don't have access to the network if you want to hit external services, but i don't think tests should be written in general to require a working network connection. -mike
#define _GNU_SOURCE #include <err.h> #include <errno.h> #include <fcntl.h> #include <getopt.h> #include <sched.h> #include <signal.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> #include <unistd.h> #include <net/if.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/prctl.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> static bool vunshare(int flags) { if (unshare(flags) == -1) { if (errno != EINVAL) err(1, "unshare failed"); return false; } return true; } static void unshare_net(void) { if (!vunshare(CLONE_NEWNET)) return; int sock; struct ifreq ifr; sock = socket(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0); if (sock < 0) err(1, "socket(AF_LOCAL) failed"); /* Equiv of `ip link set up lo`. Kernel will assign 127.0.0.1 for us. */ strcpy(ifr.ifr_name, "lo"); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) err(1, "ioctl(SIOCGIFFLAGS) failed"); /* The kernel preserves ifr.ifr_name for use. */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) err(1, "ioctl(SIOCSIFFLAGS) failed"); close(sock); } static void map_uid_gid(uid_t iuid, gid_t igid, uid_t ouid, gid_t ogid) { FILE *fp; fp = fopen("/proc/self/setgroups", "w"); if (fp) { fputs("deny\n", fp); fclose(fp); } fp = fopen("/proc/self/uid_map", "w"); fprintf(fp, "%u %u 1\n", iuid, ouid); fclose(fp); fp = fopen("/proc/self/gid_map", "w"); fprintf(fp, "%u %u 1\n", igid, ogid); fclose(fp); } static void usage(void) { puts("Usage: unshare [options] <program>"); exit(EX_USAGE); } int main(int argc, char *argv[]) { int c; bool newipc = false; bool newmnt = false; bool newnet = false; bool newuts = false; bool newusr = false; uid_t uid; gid_t gid; while ((c = getopt(argc, argv, "+imnuU")) != -1) { switch (c) { case 'i': newipc = true; break; case 'm': newmnt = true; break; case 'n': newnet = true; break; case 'u': newuts = true; break; case 'U': newusr = true; break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); if (newusr) { uid = getuid(); gid = getgid(); if (vunshare(CLONE_NEWUSER)) map_uid_gid(0, 0, uid, gid); else newusr = false; } if (newmnt) vunshare(CLONE_NEWNS); if (newuts) vunshare(CLONE_NEWUTS); if (newipc) vunshare(CLONE_NEWIPC); if (newnet) unshare_net(); if (newusr) if (vunshare(CLONE_NEWUSER)) map_uid_gid(uid, gid, 0, 0); execvp(argv[0], argv); fprintf(stderr, "%s: %s\n", argv[0], strerror(errno)); return 127; }
Attachment:
signature.asc
Description: Digital signature
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |