diff --git a/flake.nix b/flake.nix index bdbf54169..c5fa7d6dd 100644 --- a/flake.nix +++ b/flake.nix @@ -598,6 +598,8 @@ ["i686-linux" "x86_64-linux"] (system: runNixOSTestFor system ./tests/nixos/setuid.nix); + tests.cve-2022-24765 = runNixOSTestFor "x86_64-linux" ./tests/nixos/cve-2022-24765.nix; + # Make sure that nix-env still produces the exact same result # on a particular version of Nixpkgs. diff --git a/tests/nixos/cve-2022-24765.nix b/tests/nixos/cve-2022-24765.nix new file mode 100644 index 000000000..5fe91684c --- /dev/null +++ b/tests/nixos/cve-2022-24765.nix @@ -0,0 +1,64 @@ +{ lib, config, nixpkgs, ... }: + +let + pkgs = config.nodes.machine.nixpkgs.pkgs; + + flakeDotNix = pkgs.writeTextFile { + name = "flake.nix"; + destination = "/flake.nix"; + text = '' + { + outputs = { self }: { foo = 1; }; + } + ''; + }; +in +{ + name = "cve-2022-24765"; + + nodes.machine = + { config, lib, pkgs, ... }: + { + virtualisation.writableStore = true; + virtualisation.additionalPaths = [ flakeDotNix ]; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + users.users.user1.isNormalUser = true; + users.users.user2.isNormalUser = true; + }; + + testScript = { nodes }: '' + # fmt: off + start_all() + + # Evaluating a flake in the store. Should just work + machine.succeed('nix eval ${flakeDotNix}#foo') + + # Create the following hierarchy: + # + # /flakeRoot (owned by `user1`) + # /flake.nix (owned by `user1`) + # /subdir (owned by `user2`) + # + machine.execute(r""" + mkdir -p /flakeRoot/subdir + chown -R user1 /flakeRoot + cp -r ${flakeDotNix}/flake.nix /flakeRoot + chown -R user2 /flakeRoot/subdir + """.strip()) + + # Evaluating `/flakeRoot#foo` should work even if we're not `user1` since + # we've specified the exact path + machine.succeed("su user1 -c 'nix eval /flakeRoot\#foo'") + machine.succeed("su user2 -c 'nix eval /flakeRoot\#foo'") + # But when we have to resort to searching upwards in the tree, then Nix + # should error out if we're not `user1` since the `flake.nix` isn't owned + # by us + machine.succeed("su user1 -c 'nix eval /flakeRoot/subdir\#foo'") + inSubdirStdout = machine.fail( + "su user2 -c 'nix eval /flakeRoot/subdir\#foo' 2>&1" + ) + print(inSubdirStdout) + assert "owned by us" in inSubdirStdout + ''; +} +