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] |