From 2652872fac21ea7cbf379ce4c40ff724dfaceb64 Mon Sep 17 00:00:00 2001 From: Robert Swiecki Date: Thu, 3 Mar 2016 15:54:15 +0100 Subject: [PATCH] CLONE_NEWUSER routines in a separate module --- Makefile | 5 +-- subproc.c | 3 +- user.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ user.h | 31 ++++++++++++++++++ 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 user.c create mode 100644 user.h diff --git a/Makefile b/Makefile index d768ce5..d8d323f 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ CFLAGS += -O2 -g -ggdb -c -std=c11 \ LDFLAGS += -Wl,-z,now -Wl,-z,relro -pie -SRCS = nsjail.c cmdline.c contain.c log.c net.c mount.c subproc.c sandbox.c util.c seccomp/bpf-helper.c +SRCS = nsjail.c cmdline.c contain.c log.c net.c mount.c user.c subproc.c sandbox.c util.c seccomp/bpf-helper.c OBJS = $(SRCS:.c=.o) BIN = nsjail @@ -59,7 +59,8 @@ contain.o: contain.h common.h log.h mount.h net.h util.h log.o: log.h common.h net.o: net.h common.h log.h mount.o: mount.h common.h log.h -subproc.o: subproc.h common.h contain.h log.h net.h sandbox.h util.h +user.o: user.h common.h log.h util.h +subproc.o: subproc.h common.h contain.h log.h net.h sandbox.h user.h util.h sandbox.o: sandbox.h common.h log.h seccomp/bpf-helper.h util.o: util.h common.h log.h seccomp/bpf-helper.o: seccomp/bpf-helper.h diff --git a/subproc.c b/subproc.c index f6dfc92..6c8462e 100644 --- a/subproc.c +++ b/subproc.c @@ -44,6 +44,7 @@ #include "log.h" #include "net.h" #include "sandbox.h" +#include "user.h" #include "util.h" const char subprocDoneChar = 'D'; @@ -215,7 +216,7 @@ static bool subprocInitParent(struct nsjconf_t *nsjconf, pid_t pid, int pipefd) LOG_E("Couldn't create and put MACVTAP interface into NS of PID '%d'", pid); return false; } - if (containInitUserNs(nsjconf, pid) == false) { + if (userInitNsFromParent(nsjconf, pid) == false) { LOG_E("Couldn't initialize user namespaces for pid %d", pid); return false; } diff --git a/user.c b/user.c new file mode 100644 index 0000000..8d5bfcf --- /dev/null +++ b/user.c @@ -0,0 +1,95 @@ +/* + + nsjail - CLONE_NEWUSER routines + ----------------------------------------- + + Copyright 2014 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#include "user.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "util.h" + +static bool userSetGroups(pid_t pid) +{ + /* + * No need to write 'deny' to /proc/pid/setgroups if our euid==0, as writing to uid_map/gid_map + * will succeed anyway + */ + if (geteuid() == 0) { + return true; + } + + char fname[PATH_MAX]; + snprintf(fname, sizeof(fname), "/proc/%d/setgroups", pid); + const char *denystr = "deny"; + if (utilWriteBufToFile(fname, denystr, strlen(denystr), O_WRONLY) == false) { + LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, denystr); + return false; + } + return true; +} + +static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid) +{ + if (nsjconf->clone_newuser == false) { + return true; + } + + char fname[PATH_MAX]; + char map[128]; + + snprintf(fname, sizeof(fname), "/proc/%d/uid_map", pid); + snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_uid, + (unsigned long)nsjconf->outside_uid); + LOG_D("Writing '%s' to '%s'", map, fname); + if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) { + LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map); + return false; + } + + snprintf(fname, sizeof(fname), "/proc/%d/gid_map", pid); + snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_gid, + (unsigned long)nsjconf->outside_gid); + LOG_D("Writing '%s' to '%s'", map, fname); + if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) { + LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map); + return false; + } + return true; +} + +bool userInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid) +{ + if (userSetGroups(pid) == false) { + return false; + } + if (userUidGidMap(nsjconf, pid) == false) { + return false; + } + return true; +} diff --git a/user.h b/user.h new file mode 100644 index 0000000..c79135c --- /dev/null +++ b/user.h @@ -0,0 +1,31 @@ +/* + + nsjail - CLONE_NEWUSER routines + ----------------------------------------- + + Copyright 2014 Google Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#ifndef _USER_H +#define _USER_H + +#include + +#include "common.h" + +bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid); + +#endif /* _USER_H */