Change in bazel[master]: Introduce two new options to Linux sandbox wrapper: * -n: Cr...

181 views
Skip to first unread message

Ming Zhao (Gerrit)

unread,
Oct 6, 2015, 2:26:46 AM10/6/15
to bazel-de...@googlegroups.com
Ming Zhao has uploaded a new change for review.

https://bazel-review.googlesource.com/2101

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................

Introduce two new options to Linux sandbox wrapper:
* -n: Create a new network namespace with only loopback interface.
* -r: set the uid/gid inside the sandbox to be root(instead of nobody)
so that setuid program like ping can still run when needed.

Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
---
M scripts/bootstrap/compile.sh
M src/main/tools/BUILD
M src/main/tools/namespace-sandbox.c
A src/main/tools/network-tools.c
A src/main/tools/network-tools.h
M src/test/shell/bazel/namespace-runner_test.sh
6 files changed, 133 insertions(+), 14 deletions(-)



diff --git a/scripts/bootstrap/compile.sh b/scripts/bootstrap/compile.sh
index e1a3512..5f46c11 100755
--- a/scripts/bootstrap/compile.sh
+++ b/scripts/bootstrap/compile.sh
@@ -328,11 +328,11 @@
run_silent "${CXX}" -o ${OUTPUT_DIR}/build-runfiles -std=c++0x
src/main/tools/build-runfiles.cc -l stdc++

log "Compiling process-wrapper..."
-run_silent "${CC}" -o ${OUTPUT_DIR}/process-wrapper -std=c99
src/main/tools/process-wrapper.c src/main/tools/process-tools.c -lm
+run_silent "${CC}" -o ${OUTPUT_DIR}/process-wrapper -std=c99
src/main/tools/network-tools.c src/main/tools/process-wrapper.c
src/main/tools/process-tools.c -lm

log "Compiling namespace-sandbox..."
if [[ $PLATFORM == "linux" ]]; then
- run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox.c src/main/tools/process-tools.c -lm
+ run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox.c src/main/tools/network-tools.c
src/main/tools/process-tools.c -lm
else
run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox-dummy.c -lm
fi
diff --git a/src/main/tools/BUILD b/src/main/tools/BUILD
index 67b3888..7eb8aa3 100644
--- a/src/main/tools/BUILD
+++ b/src/main/tools/BUILD
@@ -1,6 +1,14 @@
package(default_visibility = ["//src:__subpackages__"])

cc_library(
+ name = "network-tools",
+ srcs = ["network-tools.c"],
+ hdrs = ["network-tools.h"],
+ deps = [":process-tools"],
+ copts = ["-std=c99"],
+)
+
+cc_library(
name = "process-tools",
srcs = ["process-tools.c"],
hdrs = ["process-tools.h"],
@@ -29,7 +37,10 @@
}),
copts = ["-std=c99"],
linkopts = ["-lm"],
- deps = [":process-tools"],
+ deps = [
+ ":process-tools",
+ ":network-tools",
+ ],
)

filegroup(
diff --git a/src/main/tools/namespace-sandbox.c
b/src/main/tools/namespace-sandbox.c
index dd5103d..62c486e 100644
--- a/src/main/tools/namespace-sandbox.c
+++ b/src/main/tools/namespace-sandbox.c
@@ -32,6 +32,7 @@
#include <sys/wait.h>
#include <unistd.h>

+#include "network-tools.h"
#include "process-tools.h"

#define PRINT_DEBUG(...) \
@@ -63,6 +64,8 @@
char **mount_sources; // Map of directories to mount, from
char **mount_targets; // sources -> targets (-m)
int num_mounts; // How many mounts were specified
+ int fake_root; // Pretend to be root inside the namespace.
+ int create_netns; // If 1, create a new network namespace.
};

// Child function used by CheckNamespacesSupported() in call to clone().
@@ -132,6 +135,8 @@
" be mounted readonly. The -M option specifies which
directory\n"
" to mount, the -m option specifies where to mount it in
the\n"
" sandbox.\n"
+ " -n if set, a new network namespace will be created\n"
+ " -r if set, make the uid/gid be root, otherwise use nobody\n"
" -D if set, debug info will be printed\n"
" -l redirect stdout to a file\n"
" -L redirect stderr to a file\n");
@@ -145,7 +150,7 @@
extern int optind, optopt;
int c;

- while ((c = getopt(argc, argv, ":CDS:W:t:T:M:m:l:L:")) != -1) {
+ while ((c = getopt(argc, argv, ":CDnrS:W:t:T:M:m:l:L:")) != -1) {
switch (c) {
case 'C':
// Shortcut for the "does this system support sandboxing" check.
@@ -209,6 +214,12 @@
}
opt->mount_targets[opt->num_mounts++] = optarg;
break;
+ case 'n':
+ opt->create_netns = 1;
+ break;
+ case 'r':
+ opt->fake_root = 1;
+ break;
case 'D':
global_debug = true;
break;
@@ -254,7 +265,7 @@
}
}

-static void CreateNamespaces() {
+static void CreateNamespaces(int create_netns) {
// This weird workaround is necessary due to unshare seldomly failing
with
// EINVAL due to a race condition in the Linux kernel (see
// https://lkml.org/lkml/2015/7/28/833). An alternative would be to use
@@ -263,7 +274,8 @@
int tries = 0;
const int max_tries = 100;
while (tries++ < max_tries) {
- if (unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)
==
+ if (unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+ (create_netns ? CLONE_NEWNET : 0)) ==
0) {
PRINT_DEBUG("unshare succeeded after %d tries\n", tries);
return;
@@ -431,7 +443,7 @@
return r;
}

-static void SetupUserNamespace(int uid, int gid) {
+static void SetupUserNamespace(int uid, int gid, int new_uid, int new_gid)
{
// Disable needs for CAP_SETGID
int r = WriteFile("/proc/self/setgroups", "deny");
if (r < 0 && errno != ENOENT) {
@@ -447,11 +459,11 @@
// We can't be root in the child, because some code may assume that
running as
// root grants it certain capabilities that it doesn't in fact have. It's
// safer to let the child think that it is just a normal user.
- CHECK_CALL(WriteFile("/proc/self/uid_map", "%d %d 1\n", kNobodyUid,
uid));
- CHECK_CALL(WriteFile("/proc/self/gid_map", "%d %d 1\n", kNobodyGid,
gid));
+ CHECK_CALL(WriteFile("/proc/self/uid_map", "%d %d 1\n", new_uid, uid));
+ CHECK_CALL(WriteFile("/proc/self/gid_map", "%d %d 1\n", new_gid, gid));

- CHECK_CALL(setresuid(kNobodyUid, kNobodyUid, kNobodyUid));
- CHECK_CALL(setresgid(kNobodyGid, kNobodyGid, kNobodyGid));
+ CHECK_CALL(setresuid(new_uid, new_uid, new_uid));
+ CHECK_CALL(setresgid(new_gid, new_gid, new_gid));
}

static void ChangeRoot(struct Options *opt) {
@@ -561,14 +573,23 @@
PRINT_DEBUG("working dir is %s\n",
(opt.working_dir != NULL) ? opt.working_dir : "/ (default)");

- CreateNamespaces();
+ CreateNamespaces(opt.create_netns);
+ if (opt.create_netns) {
+ // Enable the loopback interface because some application may want
+ // to use it.
+ BringupInterface("lo");
+ }

// Make our mount namespace private, so that further mounts do not
affect the
// outside environment.
CHECK_CALL(mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL));

SetupDirectories(&opt);
- SetupUserNamespace(uid, gid);
+ if (opt.fake_root) {
+ SetupUserNamespace(uid, gid, 0, 0);
+ } else {
+ SetupUserNamespace(uid, gid, kNobodyUid, kNobodyGid);
+ }
ChangeRoot(&opt);

SpawnCommand(opt.args, opt.timeout_secs);
diff --git a/src/main/tools/network-tools.c b/src/main/tools/network-tools.c
new file mode 100644
index 0000000..ac49b3c
--- /dev/null
+++ b/src/main/tools/network-tools.c
@@ -0,0 +1,46 @@
+// Copyright 2015 The Bazel Authors. 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.
+
+#define _GNU_SOURCE
+
+#include <net/if.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "process-tools.h"
+#include "network-tools.h"
+
+void BringupInterface(const char *name) {
+ int fd;
+
+ struct ifreq ifr;
+
+ CHECK_CALL(fd = socket(AF_INET, SOCK_DGRAM, 0));
+
+ memset(&ifr, 0, sizeof(ifr));
+ memcpy(ifr.ifr_name, name, IF_NAMESIZE);
+
+ CHECK_CALL(ioctl(fd, SIOCGIFINDEX, &ifr));
+
+ // Enable the interface
+ ifr.ifr_flags |= IFF_UP;
+ CHECK_CALL(ioctl(fd, SIOCSIFFLAGS, &ifr));
+
+ close(fd);
+}
diff --git a/src/main/tools/network-tools.h b/src/main/tools/network-tools.h
new file mode 100644
index 0000000..9c90aab
--- /dev/null
+++ b/src/main/tools/network-tools.h
@@ -0,0 +1,21 @@
+// Copyright 2015 The Bazel Authors. 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 NETWORK_TOOLS_H__
+#define NETWORK_TOOLS_H__
+
+// Bring up the given network interface like "lo".
+void BringupInterface(const char *name);
+
+#endif // NETWORK_TOOLS_H__
diff --git a/src/test/shell/bazel/namespace-runner_test.sh
b/src/test/shell/bazel/namespace-runner_test.sh
index 4e8f91a..2b52012 100755
--- a/src/test/shell/bazel/namespace-runner_test.sh
+++ b/src/test/shell/bazel/namespace-runner_test.sh
@@ -59,7 +59,7 @@
#define _GNU_SOURCE
#include <sched.h>
int main() {
- return unshare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
CLONE_NEWUSER);
+ return unshare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER
| CLONE_NEWNET);
}
EOF
cat <<'EOF' >test/BUILD
@@ -93,6 +93,26 @@
assert_output "hi there" ""
}

+function test_default_user_is_nobody() {
+ $WRAPPER $WRAPPER_DEFAULT_OPTS -l $OUT -L $ERR -- /usr/bin/id || fail
+ assert_output "uid=65534 gid=65534 groups=65534" ""
+}
+
+function test_user_switched_to_root() {
+ $WRAPPER $WRAPPER_DEFAULT_OPTS -r -l $OUT -L $ERR -- /usr/bin/id || fail
+ assert_output "uid=0 gid=0 groups=65534,0" ""
+}
+
+function test_network_namespace() {
+ $WRAPPER $WRAPPER_DEFAULT_OPTS -n -l $OUT -L $ERR -- /bin/ip link ls ||
fail
+ assert_contains "LOOPBACK,UP" "$OUT"
+}
+
+function test_ping_loopback() {
+ $WRAPPER $WRAPPER_DEFAULT_OPTS -n -r -l $OUT -L $ERR -- /bin/ping -c 1
127.0.0.1 || fail
+ assert_contains "1 received" "$OUT"
+}
+
function test_to_stderr() {
$WRAPPER $WRAPPER_DEFAULT_OPTS -l $OUT -L $ERR -- /bin/bash
-c "/bin/echo hi there >&2" || fail
assert_output "" "hi there"

--
To view, visit https://bazel-review.googlesource.com/2101
To unsubscribe, visit https://bazel-review.googlesource.com/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 1
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Han-Wen Nienhuys (Gerrit)

unread,
Oct 6, 2015, 5:00:37 AM10/6/15
to Ming Zhao, Philipp Wollermann
Han-Wen Nienhuys has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2: Code-Review+2

(2 comments)

https://bazel-review.googlesource.com/#/c/2101/2/src/main/tools/namespace-sandbox.c
File src/main/tools/namespace-sandbox.c:

PS2, Line 153: :
can you sort these?


https://bazel-review.googlesource.com/#/c/2101/2/src/main/tools/network-tools.c
File src/main/tools/network-tools.c:

PS2, Line 32: ;
ifr = {};

is a shorter way to init to 0.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: Yes

Han-Wen Nienhuys (Gerrit)

unread,
Oct 6, 2015, 5:01:00 AM10/6/15
to Ming Zhao, Philipp Wollermann
Han-Wen Nienhuys has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2:

I'll wait for philipp to come in so he can comment if he likes.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: No

Philipp Wollermann (Gerrit)

unread,
Oct 6, 2015, 7:04:50 AM10/6/15
to Ming Zhao, Han-Wen Nienhuys
Philipp Wollermann has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2: Code-Review+2

Thanks a lot!
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Ming Zhao (Gerrit)

unread,
Oct 6, 2015, 12:34:26 PM10/6/15
to Philipp Wollermann, Han-Wen Nienhuys
Hello Philipp Wollermann, Han-Wen Nienhuys,

I'd like you to reexamine a change. Please visit

https://bazel-review.googlesource.com/2101

to look at the new patch set (#3).

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................

Introduce two new options to Linux sandbox wrapper:
* -n: Create a new network namespace with only loopback interface.
* -r: set the uid/gid inside the sandbox to be root(instead of nobody)
so that setuid program like ping can still run when needed.

Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
---
M scripts/bootstrap/compile.sh
M src/main/tools/BUILD
M src/main/tools/namespace-sandbox.c
A src/main/tools/network-tools.c
A src/main/tools/network-tools.h
M src/test/shell/bazel/namespace-runner_test.sh
6 files changed, 134 insertions(+), 15 deletions(-)
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 3
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Ming Zhao (Gerrit)

unread,
Oct 6, 2015, 12:35:12 PM10/6/15
to Han-Wen Nienhuys, Philipp Wollermann
Ming Zhao has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2:

(2 comments)

PTAL. Thanks!

https://bazel-review.googlesource.com/#/c/2101/2/src/main/tools/namespace-sandbox.c
File src/main/tools/namespace-sandbox.c:

PS2, Line 153: :
> can you sort these?
Done


https://bazel-review.googlesource.com/#/c/2101/2/src/main/tools/network-tools.c
File src/main/tools/network-tools.c:

PS2, Line 32: ;
> ifr = {};
I don't know whether it's affected by '-c99' option, but I got "ioctl(fd,
SIOCGIFINDEX, &ifr): No such device" error after using {} initializer.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: Yes

Han-Wen Nienhuys (Gerrit)

unread,
Oct 6, 2015, 12:49:13 PM10/6/15
to Ming Zhao, Philipp Wollermann
Han-Wen Nienhuys has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2:

(1 comment)

https://bazel-review.googlesource.com/#/c/2101/2/src/main/tools/network-tools.c
File src/main/tools/network-tools.c:

PS2, Line 32: ;
> I don't know whether it's affected by '-c99' option, but I got "ioctl(fd,
> S
Curious. Well, never mind. This is OK too.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Han-Wen Nienhuys (Gerrit)

unread,
Oct 6, 2015, 12:51:20 PM10/6/15
to Ming Zhao, Philipp Wollermann
Han-Wen Nienhuys has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 2:

I'll import this.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 2
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: No

Brian Silverman (Gerrit)

unread,
Oct 6, 2015, 1:48:15 PM10/6/15
to Ming Zhao, Han-Wen Nienhuys, Philipp Wollermann
Brian Silverman has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 3:

(2 comments)

https://bazel-review.googlesource.com/#/c/2101/3/src/main/tools/network-tools.c
File src/main/tools/network-tools.c:

PS3, Line 37: memcpy
Shouldn't this be strncpy so it doesn't copy bytes from off the end of name?


Line 45: close(fd);
Seems like this should also be a CHECK_CALL because sometimes errors show
up when you close FDs, and it's nice to be told about those rather than
having them go by silently.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 3
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Brian Silverman <bsilve...@gmail.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: Yes

Ming Zhao (Gerrit)

unread,
Oct 6, 2015, 2:27:59 PM10/6/15
to Philipp Wollermann, Han-Wen Nienhuys, Brian Silverman
Hello Philipp Wollermann, Han-Wen Nienhuys,

I'd like you to reexamine a change. Please visit

https://bazel-review.googlesource.com/2101

to look at the new patch set (#4).

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................

Introduce two new options to Linux sandbox wrapper:
* -n: Create a new network namespace with only loopback interface.
* -r: set the uid/gid inside the sandbox to be root(instead of nobody)
so that setuid program like ping can still run when needed.

Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
---
M scripts/bootstrap/compile.sh
M src/main/tools/BUILD
M src/main/tools/namespace-sandbox.c
A src/main/tools/network-tools.c
A src/main/tools/network-tools.h
M src/test/shell/bazel/namespace-runner_test.sh
6 files changed, 134 insertions(+), 15 deletions(-)
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 4
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Ming Zhao (Gerrit)

unread,
Oct 6, 2015, 2:28:32 PM10/6/15
to Han-Wen Nienhuys, Philipp Wollermann, Brian Silverman
Ming Zhao has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 3:

(2 comments)

Thanks, PTAL

https://bazel-review.googlesource.com/#/c/2101/3/src/main/tools/network-tools.c
File src/main/tools/network-tools.c:

PS3, Line 37: memcpy
> Shouldn't this be strncpy so it doesn't copy bytes from off the end of
> name
Done


Line 45: close(fd);
> Seems like this should also be a CHECK_CALL because sometimes errors show
> u
Done
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 3
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Brian Silverman <bsilve...@gmail.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: Yes

Brian Silverman (Gerrit)

unread,
Oct 6, 2015, 2:30:09 PM10/6/15
to Ming Zhao, Han-Wen Nienhuys, Philipp Wollermann
Brian Silverman has posted comments on this change.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root(instead of nobody) so that setuid
program like ping can still run when needed.
......................................................................


Patch Set 4: Code-Review+1

I like the idea of sandboxing this.
Gerrit-MessageType: comment
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 4
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Brian Silverman <bsilve...@gmail.com>
Gerrit-Reviewer: Han-Wen Nienhuys <han...@google.com>
Gerrit-Reviewer: Ming Zhao <mz...@luminatewireless.com>
Gerrit-Reviewer: Philipp Wollermann <phi...@google.com>
Gerrit-HasComments: No

Han-Wen Nienhuys (Gerrit)

unread,
Oct 8, 2015, 8:14:34 AM10/8/15
to Ming Zhao, Philipp Wollermann, Brian Silverman
Hello Philipp Wollermann, Brian Silverman,

I'd like you to reexamine a change. Please visit

https://bazel-review.googlesource.com/2101

to look at the new patch set (#5).

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root (instead of nobody) so that setuid
programs like ping can still run when needed.
......................................................................

Introduce two new options to Linux sandbox wrapper:
* -n: Create a new network namespace with only loopback interface.
* -r: set the uid/gid inside the sandbox to be root (instead of nobody)
so that setuid programs like ping can still run when needed.

--
Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Reviewed-on: https://bazel-review.googlesource.com/#/c/2101/
MOS_MIGRATED_REVID=104858163
---
M scripts/bootstrap/compile.sh
M src/main/tools/BUILD
M src/main/tools/namespace-sandbox.c
A src/main/tools/network-tools.c
A src/main/tools/network-tools.h
M src/test/shell/bazel/namespace-runner_test.sh
6 files changed, 139 insertions(+), 15 deletions(-)
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 5
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>

Han-Wen Nienhuys (Gerrit)

unread,
Oct 8, 2015, 8:14:35 AM10/8/15
to Ming Zhao, Philipp Wollermann, Brian Silverman
Han-Wen Nienhuys has submitted this change and it was merged.

Change subject: Introduce two new options to Linux sandbox wrapper: * -n:
Create a new network namespace with only loopback interface. * -r: set the
uid/gid inside the sandbox to be root (instead of nobody) so that setuid
programs like ping can still run when needed.
......................................................................


Introduce two new options to Linux sandbox wrapper:
* -n: Create a new network namespace with only loopback interface.
* -r: set the uid/gid inside the sandbox to be root (instead of nobody)
so that setuid programs like ping can still run when needed.

--
Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Reviewed-on: https://bazel-review.googlesource.com/#/c/2101/
MOS_MIGRATED_REVID=104858163
---
M scripts/bootstrap/compile.sh
M src/main/tools/BUILD
M src/main/tools/namespace-sandbox.c
A src/main/tools/network-tools.c
A src/main/tools/network-tools.h
M src/test/shell/bazel/namespace-runner_test.sh
6 files changed, 139 insertions(+), 15 deletions(-)



diff --git a/scripts/bootstrap/compile.sh b/scripts/bootstrap/compile.sh
index 523dab5..f9605b5 100755
--- a/scripts/bootstrap/compile.sh
+++ b/scripts/bootstrap/compile.sh
@@ -332,7 +332,7 @@

log "Compiling namespace-sandbox..."
if [[ $PLATFORM == "linux" ]]; then
- run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox.c src/main/tools/process-tools.c -lm
+ run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox.c src/main/tools/network-tools.c
src/main/tools/process-tools.c -lm
else
run_silent "${CC}" -o ${OUTPUT_DIR}/namespace-sandbox -std=c99
src/main/tools/namespace-sandbox-dummy.c -lm
fi
diff --git a/src/main/tools/BUILD b/src/main/tools/BUILD
index 67b3888..4a87f65 100644
--- a/src/main/tools/BUILD
+++ b/src/main/tools/BUILD
@@ -1,6 +1,14 @@
package(default_visibility = ["//src:__subpackages__"])

cc_library(
+ name = "network-tools",
+ srcs = ["network-tools.c"],
+ hdrs = ["network-tools.h"],
+ copts = ["-std=c99"],
+ deps = [":process-tools"],
+)
+
+cc_library(
name = "process-tools",
srcs = ["process-tools.c"],
hdrs = ["process-tools.h"],
@@ -29,7 +37,14 @@
}),
copts = ["-std=c99"],
linkopts = ["-lm"],
- deps = [":process-tools"],
+ deps = select({
+ "//src:darwin": [],
+ "//src:freebsd": [],
+ "//conditions:default": [
+ ":process-tools",
+ ":network-tools",
+ ],
+ }),
)

filegroup(
diff --git a/src/main/tools/namespace-sandbox.c
b/src/main/tools/namespace-sandbox.c
index 4380e93..ef13213 100644
--- a/src/main/tools/namespace-sandbox.c
+++ b/src/main/tools/namespace-sandbox.c
@@ -32,6 +32,7 @@
#include <sys/wait.h>
#include <unistd.h>

+#include "network-tools.h"
#include "process-tools.h"

#define PRINT_DEBUG(...) \
@@ -65,6 +66,8 @@
int num_mounts; // How many mounts were specified
char **create_dirs; // empty dirs to create (-d)
int num_create_dirs; // How many empty dirs to create were
specified
+ int fake_root; // Pretend to be root inside the namespace.
+ int create_netns; // If 1, create a new network namespace.
};

// Child function used by CheckNamespacesSupported() in call to clone().
@@ -92,7 +95,7 @@
// spend time sleeping and retrying here until it eventually works (or
not).
CHECK_CALL(pid = clone(CheckNamespacesSupportedChild, stackTop,
CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS |
- CLONE_NEWIPC | SIGCHLD,
+ CLONE_NEWIPC | CLONE_NEWNET | SIGCHLD,
NULL));
CHECK_CALL(waitpid(pid, NULL, 0));

@@ -134,9 +137,12 @@
" The -M option specifies which directory to mount, the -m
option "
"specifies where to\n"
" mount it in the sandbox.\n"
+ " -n if set, a new network namespace will be created\n"
+ " -r if set, make the uid/gid be root, otherwise use nobody\n"
" -D if set, debug info will be printed\n"
" -l <file> redirect stdout to a file\n"
- " -L <file> redirect stderr to a file\n");
+ " -L <file> redirect stderr to a file\n"
+ );
exit(EXIT_FAILURE);
}

@@ -147,7 +153,7 @@
extern int optind, optopt;
int c;

- while ((c = getopt(argc, argv, ":CDS:W:t:T:d:M:m:l:L:")) != -1) {
+ while ((c = getopt(argc, argv, ":CDd:l:L:m:M:nrt:T:S:W:")) != -1) {
switch (c) {
case 'C':
// Shortcut for the "does this system support sandboxing" check.
@@ -222,6 +228,12 @@
}
opt->mount_targets[opt->num_mounts++] = optarg;
break;
+ case 'n':
+ opt->create_netns = 1;
+ break;
+ case 'r':
+ opt->fake_root = 1;
+ break;
case 'D':
global_debug = true;
break;
@@ -268,7 +280,7 @@
}
}

-static void CreateNamespaces() {
+static void CreateNamespaces(int create_netns) {
// This weird workaround is necessary due to unshare seldomly failing
with
// EINVAL due to a race condition in the Linux kernel (see
// https://lkml.org/lkml/2015/7/28/833). An alternative would be to use
@@ -277,7 +289,8 @@
int tries = 0;
const int max_tries = 100;
while (tries++ < max_tries) {
- if (unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)
==
+ if (unshare(CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+ (create_netns ? CLONE_NEWNET : 0)) ==
0) {
PRINT_DEBUG("unshare succeeded after %d tries\n", tries);
return;
@@ -455,7 +468,7 @@
return r;
}

-static void SetupUserNamespace(int uid, int gid) {
+static void SetupUserNamespace(int uid, int gid, int new_uid, int new_gid)
{
// Disable needs for CAP_SETGID
int r = WriteFile("/proc/self/setgroups", "deny");
if (r < 0 && errno != ENOENT) {
@@ -471,11 +484,11 @@
// We can't be root in the child, because some code may assume that
running as
// root grants it certain capabilities that it doesn't in fact have. It's
// safer to let the child think that it is just a normal user.
- CHECK_CALL(WriteFile("/proc/self/uid_map", "%d %d 1\n", kNobodyUid,
uid));
- CHECK_CALL(WriteFile("/proc/self/gid_map", "%d %d 1\n", kNobodyGid,
gid));
+ CHECK_CALL(WriteFile("/proc/self/uid_map", "%d %d 1\n", new_uid, uid));
+ CHECK_CALL(WriteFile("/proc/self/gid_map", "%d %d 1\n", new_gid, gid));

- CHECK_CALL(setresuid(kNobodyUid, kNobodyUid, kNobodyUid));
- CHECK_CALL(setresgid(kNobodyGid, kNobodyGid, kNobodyGid));
+ CHECK_CALL(setresuid(new_uid, new_uid, new_uid));
+ CHECK_CALL(setresgid(new_gid, new_gid, new_gid));
}

static void ChangeRoot(struct Options *opt) {
@@ -588,14 +601,23 @@
PRINT_DEBUG("working dir is %s\n",
(opt.working_dir != NULL) ? opt.working_dir : "/ (default)");

- CreateNamespaces();
+ CreateNamespaces(opt.create_netns);
+ if (opt.create_netns) {
+ // Enable the loopback interface because some application may want
+ // to use it.
+ BringupInterface("lo");
+ }

// Make our mount namespace private, so that further mounts do not
affect the
// outside environment.
CHECK_CALL(mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL));

SetupDirectories(&opt);
- SetupUserNamespace(uid, gid);
+ if (opt.fake_root) {
+ SetupUserNamespace(uid, gid, 0, 0);
+ } else {
+ SetupUserNamespace(uid, gid, kNobodyUid, kNobodyGid);
+ }
ChangeRoot(&opt);

SpawnCommand(opt.args, opt.timeout_secs);
diff --git a/src/main/tools/network-tools.c b/src/main/tools/network-tools.c
new file mode 100644
index 0000000..6e088d4
+ strncpy(ifr.ifr_name, name, IF_NAMESIZE);
+
+ CHECK_CALL(ioctl(fd, SIOCGIFINDEX, &ifr));
+
+ // Enable the interface
+ ifr.ifr_flags |= IFF_UP;
+ CHECK_CALL(ioctl(fd, SIOCSIFFLAGS, &ifr));
+
+ CHECK_CALL(close(fd));
Gerrit-MessageType: merged
Gerrit-Change-Id: I8ab434e47e0f6933ee9de02e135c8daec39fe73f
Gerrit-PatchSet: 5
Gerrit-Project: bazel
Gerrit-Branch: master
Gerrit-Owner: Ming Zhao <mz...@luminatewireless.com>
Reply all
Reply to author
Forward
0 new messages