diff options
-rw-r--r-- | pkgs/build-support/build-sandbox/default.nix | 23 | ||||
-rw-r--r-- | pkgs/build-support/build-sandbox/src/Makefile | 2 | ||||
-rw-r--r-- | pkgs/build-support/build-sandbox/src/setup.c | 3 | ||||
-rw-r--r-- | tests/sandbox.nix | 25 |
4 files changed, 49 insertions, 4 deletions
diff --git a/pkgs/build-support/build-sandbox/default.nix b/pkgs/build-support/build-sandbox/default.nix index 0e1d4a4d..50b8f78f 100644 --- a/pkgs/build-support/build-sandbox/default.nix +++ b/pkgs/build-support/build-sandbox/default.nix @@ -16,6 +16,25 @@ let # TODO: get rid of nix & pkg-config if this is enabled (in the Makefile) fullNixStore = attrs.fullNixStore or false; + # The mount and user namespaces are needed for this functionality, so these + # namespaces are always enabled. + # + # However, the following namespaces can be enabled/disabled: + # +----------------+---------+--------------------------------------+ + # | Attribute path | Default | Isolates | + # +----------------+---------+--------------------------------------+ + # | namespaces.pid | true | Process IDs | + # | namespaces.uts | true | Hostname and NIS domain name | + # | namespaces.ipc | true | System V IPC, POSIX message queues | + # | namespaces.net | false | Network devices, stacks, ports, etc. | + # +----------------+---------+--------------------------------------+ + extraNamespaceFlags = let + flags = lib.optional (attrs.namespaces.pid or true) "CLONE_NEWPID" + ++ lib.optional (attrs.namespaces.uts or true) "CLONE_NEWUTS" + ++ lib.optional (attrs.namespaces.ipc or true) "CLONE_NEWIPC" + ++ lib.optional (attrs.namespaces.net or false) "CLONE_NEWNET"; + in if flags == [] then "0" else lib.concatStringsSep "|" flags; + # Create code snippets for params.c to add extra_mount() calls. mkExtraMountParams = isRequired: lib.concatMapStringsSep "\n" (extra: let escaped = lib.escape ["\\" "\""] extra; @@ -80,8 +99,8 @@ in stdenv.mkDerivation ({ nativeBuildInputs = [ pkgconfig ]; buildInputs = [ boost nix ]; - makeFlags = [ "BINDIR=${drv}/bin" ] + makeFlags = [ "BINDIR=${drv}/bin" "EXTRA_NS_FLAGS=${extraNamespaceFlags}" ] ++ lib.optional allowBinSh "BINSH_EXECUTABLE=${dash}/bin/dash" ++ lib.optional fullNixStore "FULL_NIX_STORE=1"; -} // removeAttrs attrs [ "paths" "allowBinSh" ]) +} // removeAttrs attrs [ "namespaces" "paths" "allowBinSh" ]) diff --git a/pkgs/build-support/build-sandbox/src/Makefile b/pkgs/build-support/build-sandbox/src/Makefile index 8e1218f6..ebe66c0e 100644 --- a/pkgs/build-support/build-sandbox/src/Makefile +++ b/pkgs/build-support/build-sandbox/src/Makefile @@ -6,6 +6,8 @@ CFLAGS = -g -Wall -std=gnu11 -DFS_ROOT_DIR=\"$(out)\" CXXFLAGS = -g -Wall -std=c++14 `pkg-config --cflags nix-main` LDFLAGS = -Wl,--copy-dt-needed-entries `pkg-config --libs nix-main` +CFLAGS += -DEXTRA_NS_FLAGS="$(EXTRA_NS_FLAGS)" + ifdef FULL_NIX_STORE CFLAGS += -DFULL_NIX_STORE else diff --git a/pkgs/build-support/build-sandbox/src/setup.c b/pkgs/build-support/build-sandbox/src/setup.c index 98205710..dc8bbf14 100644 --- a/pkgs/build-support/build-sandbox/src/setup.c +++ b/pkgs/build-support/build-sandbox/src/setup.c @@ -850,8 +850,7 @@ bool setup_sandbox(void) close(sync_pipe[0]); _exit(write_maps(parent_pid) ? 0 : 1); default: - if (unshare(CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWPID | - CLONE_NEWUTS | CLONE_NEWIPC) == -1) { + if (unshare(CLONE_NEWNS | CLONE_NEWUSER | EXTRA_NS_FLAGS) == -1) { perror("unshare"); if (write(sync_pipe[1], "X", 1) == -1) perror("signal child exit"); diff --git a/tests/sandbox.nix b/tests/sandbox.nix index 63d8af6e..b9f087a0 100644 --- a/tests/sandbox.nix +++ b/tests/sandbox.nix @@ -17,6 +17,20 @@ services.xserver.enable = true; systemd.services.display-manager.enable = false; + systemd.sockets.netnstest = { + description = "Host Socket for Testing Network Namespaces"; + requiredBy = [ "sockets.target" ]; + + socketConfig.ListenStream = "3000"; + socketConfig.Accept = true; + }; + + systemd.services."netnstest@" = { + description = "Host Service for Testing Network Namespaces"; + serviceConfig.StandardInput = "socket"; + serviceConfig.ExecStart = "${pkgs.coreutils}/bin/tee /tmp/netns.log"; + }; + environment.systemPackages = let mkNestedLinksTo = drv: let mkLink = name: to: pkgs.runCommandLocal name { inherit to; } '' @@ -115,6 +129,12 @@ # Another /bin/sh just to be sure :-) /bin/sh -c 'echo /bin/sh works' '') { allowBinSh = true; }) + + (pkgs.vuizvui.buildSandbox (pkgs.writeScriptBin "test-sandbox3" '' + #!${pkgs.stdenv.shell} + echo hello network | ${pkgs.netcat-openbsd}/bin/nc -N 127.0.0.1 3000 \ + || echo netcat has failed + '') { namespaces.net = true; }) ]; users.users.foo.isNormalUser = true; }; @@ -137,5 +157,10 @@ machine.succeed('test "$(< /home/foo/.cache/xdg/ownpid)" = 1') machine.succeed('test "$(su -c test-sandbox2 foo)" = "/bin/sh works"') + + machine.succeed('su -c "echo root netns | nc -N 127.0.0.1 3000" foo') + machine.succeed('test "$(su -c test-sandbox3 foo)" = "netcat has failed"') + machine.fail('grep -F "hello network" /tmp/netns.log') + machine.succeed('grep -F "root netns" /tmp/netns.log') ''; } |