From b705c0226334d8763a9f1b9ee06fe7a78a5558e7 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 15 Jan 2018 19:09:16 +0100 Subject: executor: fix tun/device setup for sandbox=namespace For sandbox=namespace we first create network devices and then do CLONE_NEWNS, which brings us into a new namespace which actually does not have any of these devices. Tun mostly worked, because we hold fd to the tun device. However, even for tun we could not see the "syz0" device. --- executor/common_linux.h | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'executor') diff --git a/executor/common_linux.h b/executor/common_linux.h index ce7466789..3e84f333e 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -735,12 +735,21 @@ static void sandbox_common() // CLONE_NEWNS/NEWCGROUP cause EINVAL on some systems, // so we do them separately of clone in do_sandbox_namespace. - unshare(CLONE_NEWNS); - unshare(CLONE_NEWIPC); - unshare(CLONE_NEWCGROUP); - unshare(CLONE_NEWNET); - unshare(CLONE_NEWUTS); - unshare(CLONE_SYSVSEM); + if (unshare(CLONE_NEWNS)) { + debug("unshare(CLONE_NEWNS): %d\n", errno); + } + if (unshare(CLONE_NEWIPC)) { + debug("unshare(CLONE_NEWIPC): %d\n", errno); + } + if (unshare(CLONE_NEWCGROUP)) { + debug("unshare(CLONE_NEWCGROUP): %d\n", errno); + } + if (unshare(CLONE_NEWUTS)) { + debug("unshare(CLONE_NEWUTS): %d\n", errno); + } + if (unshare(CLONE_SYSVSEM)) { + debug("unshare(CLONE_SYSVSEM): %d\n", errno); + } } #endif @@ -749,7 +758,13 @@ static int do_sandbox_none(int executor_pid, bool enable_tun) { // CLONE_NEWPID takes effect for the first child of the current process, // so we do it before fork to make the loop "init" process of the namespace. - unshare(CLONE_NEWPID); + // We ought to do fail here, but sandbox=none is used in pkg/ipc tests + // and they are usually run under non-root. + // Also since debug is stripped by pkg/csource, we need to do {} + // even though we generally don't do {} around single statements. + if (unshare(CLONE_NEWPID)) { + debug("unshare(CLONE_NEWPID): %d\n", errno); + } int pid = fork(); if (pid < 0) fail("sandbox fork failed"); @@ -757,6 +772,9 @@ static int do_sandbox_none(int executor_pid, bool enable_tun) return pid; sandbox_common(); + if (unshare(CLONE_NEWNET)) { + debug("unshare(CLONE_NEWNET): %d\n", errno); + } #if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -769,7 +787,8 @@ static int do_sandbox_none(int executor_pid, bool enable_tun) #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID) static int do_sandbox_setuid(int executor_pid, bool enable_tun) { - unshare(CLONE_NEWPID); + if (unshare(CLONE_NEWPID)) + fail("unshare(CLONE_NEWPID)"); int pid = fork(); if (pid < 0) fail("sandbox fork failed"); @@ -777,6 +796,8 @@ static int do_sandbox_setuid(int executor_pid, bool enable_tun) return pid; sandbox_common(); + if (unshare(CLONE_NEWNET)) + fail("unshare(CLONE_NEWNET)"); #if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) setup_tun(executor_pid, enable_tun); #endif @@ -893,6 +914,10 @@ static int do_sandbox_namespace(int executor_pid, bool enable_tun) { int pid; + // CLONE_NEWNET must always happen before tun setup, + // because we want the tun device in the test namespace. + if (unshare(CLONE_NEWNET)) + fail("unshare(CLONE_NEWNET)"); #if defined(SYZ_EXECUTOR) || defined(SYZ_TUN_ENABLE) // For sandbox namespace we setup tun before dropping privs, // because IFF_NAPI_FRAGS requires root. -- cgit mrf-deployment