{
name = "sandbox";
machine = { pkgs, lib, ... }: {
system.activationScripts.inject-link = ''
ln -svf ${pkgs.hello} /run/foo-test-sandbox
ln -svf ${pkgs.gnused} /run/bar-test-sandbox
ln -svf ${pkgs.gnugrep} /run/baz-test-sandbox
'';
environment.sessionVariables.COLLECT_ME = [
"/run/foo-test-sandbox"
"/run/bar-test-sandbox"
"/run/baz-test-sandbox"
];
# Only needed so we get the right XDG paths in the system path.
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; } ''
ln -s "$to" "$out"
'';
in mkLink "nested-1" (mkLink "nested-2" (mkLink "nested-3" drv));
testPackage = pkgs.runCommand "test-sandbox" {
program = ''
#!${pkgs.stdenv.shell} -ex
if [ "$1" != canary ]; then
echo 'Canary check failed, so the test program probably' \
'was not executed via the XDG desktop entry.' >&2
exit 1
fi
# Should fail because we can't access the host's PATH
! echo foo | grep -qF foo
# No /bin/sh by default
test ! -e /bin
test ! -e /bin/sh
# Write PID information to files, so that we can later verify whether
# we were in a PID namespace.
echo $$ > /home/foo/.cache/xdg/ownpid
ls -d1 /proc/[0-9]* > /home/foo/.cache/xdg/procpids
# Check whether we can access files behind nested storepaths that are
# symlinks.
lfile="$(< ${mkNestedLinksTo (pkgs.writeText "target" "file")})"
test "$lfile" = file
ldir="$(< ${mkNestedLinksTo (pkgs.runCommandLocal "target" {} ''
mkdir -p "$out"
echo dir > "$out/canary"
'')}/canary)"
test "$ldir" = dir
export PATH=/run/baz-test-sandbox/bin
echo foo > /home/foo/existing/bar
test ! -d /home/foo/nonexisting
/run/foo-test-sandbox/bin/hello
echo aaa | /run/bar-test-sandbox/bin/sed -e 's/a/b/g'
echo XDG1 > /home/foo/.local/share/xdg/1
echo XDG2 > /home/foo/.config/xdg/2
echo XDG3 > /home/foo/.cache/xdg/3
echo > /home/foo/.cache/xdg/done
'';
} ''
mkdir -p "$out/bin" "$out/share/applications" "$out/share/test-sandbox"
echo -n "$program" > "$out/bin/test-sandbox"
chmod +x "$out/bin/test-sandbox"
echo '' \
> "$out/share/test-sandbox/icon.svg"
cat > "$out/share/applications/test.desktop" <&2')
machine.wait_for_file('/home/foo/.cache/xdg/done')
machine.succeed('test -d /home/foo/existing')
machine.succeed('grep -qF foo /home/foo/existing/bar')
machine.fail('test -d /home/foo/nonexisting')
machine.succeed('grep -qF XDG1 /home/foo/.local/share/xdg/1')
machine.succeed('grep -qF XDG2 /home/foo/.config/xdg/2')
machine.succeed('grep -qF XDG3 /home/foo/.cache/xdg/3')
machine.succeed('test "$(< /home/foo/.cache/xdg/procpids)" = /proc/1')
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')
machine.succeed('test "$(su -c test-sandbox4 foo)" = "no pid namespace"')
'';
}