Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pkgs/test/security/abifix-noop.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Check that evaluating all the packages, with the abi patching mechanism
# with no fixes is effectively a no-op.

with import ./lib.nix;

assert builtins.trace "Found ${builtins.toString (builtins.length pkgsDrvs)} packages." true;
assert builtins.length pkgsDrvs == builtins.length abifixDrvs;
assert lib.all lib.id (zipPkgs pkgsDrvs abifixDrvs);
true
201 changes: 201 additions & 0 deletions pkgs/test/security/check-quickfix.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
let
testDrv = stdenv: name: rec {
inherit name;
buildInputs = [ ];
buildCommand = ''
mkdir -p $out
touch $out/installed
echo ${name} >> $out/installed
touch $out/dependency
echo $out >> $out/dependency
'';

meta = with stdenv.lib; {
homepage = https://nixos.org/;
description = "Test case";
longDescription = "Test case";
license = licenses.mit;
maintainers = [ maintainers.pierron ];
platforms = platforms.all;
};
};

testDrvWithDep = stdenv: name: dep:
let drv = testDrv stdenv name; in drv // {
buildInputs = [ dep ];
buildCommand = drv.buildCommand + ''
cat ${dep}/installed >> $out/installed
cat ${dep}/dependency >> $out/dependency
'';
};

testPkg = stdenv: name:
stdenv.mkDerivation (testDrv stdenv name);

testPkgWithDep = stdenv: name: dep:
stdenv.mkDerivation (testDrvWithDep stdenv name dep);

pkgTestDead = { stdenv, name ? "dead-1.0.0" }:
testPkg stdenv name;
pkgTestBeef = { stdenv, name ? "beef-1.0.0", test-dead }:
testPkgWithDep stdenv name test-dead;
pkgTestAte = { stdenv, name ? "ate-1.0.0", test-beef }:
testPkgWithDep stdenv name test-beef;
pkgTestBad = { stdenv, name ? "bad-1.0.0", test-ate }:
testPkgWithDep stdenv name test-ate;
pkgTestFood = { stdenv, name ? "food-1.0.0", test-bad }:
testPkgWithDep stdenv name test-bad;

originalPackages = {
adapters = import ../../../pkgs/stdenv/adapters.nix;
builders = import ../../../pkgs/build-support/trivial-builders.nix;
stdenv = import ../../../pkgs/top-level/stdenv.nix;
all = import ../../../pkgs/top-level/all-packages.nix;
aliases = import ../../../pkgs/top-level/aliases.nix;
};

defaultPackages = originalPackages // {
all = top: self: pkgs: originalPackages.all top self pkgs // (
let callPackage = top.lib.callPackageWith pkgs; in {
test-dead = callPackage pkgTestDead { };
test-beef = callPackage pkgTestBeef { };
test-ate = callPackage pkgTestAte { };
test-bad = callPackage pkgTestBad { };
test-food = callPackage pkgTestFood { };
});
};

# Only change the foo package which is used explicitly by bar, and
# indirectly by baz.
quickfixPackages = originalPackages // {
all = top: self: pkgs: originalPackages.all top self pkgs // (
let callPackage = top.lib.callPackageWith pkgs; in {
test-dead = callPackage pkgTestDead { };
test-beef = callPackage pkgTestBeef { name = "beef-1.0.2"; };
test-ate = callPackage pkgTestAte { };
test-bad = callPackage pkgTestBad { name = "bad-1.0.51"; };
test-food = callPackage pkgTestFood { };
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This testcase is incomplete. You don't test that package that depends on test-food or test-ate isn't recompiled.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danbst, Note that test-bad is recompiled with the patched version of test-ate, and not the recompiled version of test-ate. This is verified by the line 148, which checks that the dependency names inherited from test-ate is beef-1.0.0 instead of beef-1.0.2.

I guess, for testing what you suggest we should copy the dependency file from the latest added hash of the installed file, and check that the names are the original one, and not the patched one.

With this method, recompiled package depending on test-food / test-ate would get the renamed version of test-bad / test-beef, and non recompiled package depending on test-food / test-ate would get the original version of test-bad / test-beef.

Note, the way the current patching mechanism is made also guarantee that adding the above test should work, because it only works on one package at a time, thus by recursion inference, all should work out of the box.

};

withoutFix = import ../../../. {
inherit defaultPackages;
quickfixPackages = null;
};

withFix = import ../../../. {
inherit defaultPackages quickfixPackages;
};
in

withoutFix.stdenv.mkDerivation {
name = "check-quickfix";
buildInputs = [];
buildCommand = ''
length() {
local arg="$1";
echo ''${#arg};
}
set -x;

: Check that fixes are correctly applies.
test ${withoutFix.test-dead} = ${withFix.test-dead}
test \! ${withoutFix.test-beef} = ${withFix.test-beef} # recompiled
test \! ${withoutFix.test-ate } = ${withFix.test-ate } # patched
test \! ${withoutFix.test-bad } = ${withFix.test-bad } # recompiled & patched
test \! ${withoutFix.test-food} = ${withFix.test-food} # patched

: Check output paths have identical length.
test $(length ${withoutFix.test-dead}) -eq $(length ${withFix.test-dead})
test $(length ${withoutFix.test-beef}) -eq $(length ${withFix.test-beef})
test $(length ${withoutFix.test-ate }) -eq $(length ${withFix.test-ate })
test $(length ${withoutFix.test-bad }) -eq $(length ${withFix.test-bad }) # renamed
test $(length ${withoutFix.test-food}) -eq $(length ${withFix.test-food})

: Check compiled packages names.
grep -q "dead-1.0.0" ${withoutFix.test-dead}/installed
grep -q "beef-1.0.0" ${withoutFix.test-beef}/installed
grep -q "ate-1.0.0" ${withoutFix.test-ate }/installed
grep -q "bad-1.0.0" ${withoutFix.test-bad }/installed
grep -q "food-1.0.0" ${withoutFix.test-food}/installed

grep -q "dead-1.0.0" ${withoutFix.test-beef}/installed
grep -q "beef-1.0.0" ${withoutFix.test-ate }/installed
grep -q "ate-1.0.0" ${withoutFix.test-bad }/installed
grep -q "bad-1.0.0" ${withoutFix.test-food}/installed

grep -q "dead-1.0.0" ${withoutFix.test-ate }/installed
grep -q "beef-1.0.0" ${withoutFix.test-bad }/installed
grep -q "ate-1.0.0" ${withoutFix.test-food}/installed

grep -q "dead-1.0.0" ${withoutFix.test-bad }/installed
grep -q "beef-1.0.0" ${withoutFix.test-food}/installed

grep -q "dead-1.0.0" ${withoutFix.test-food}/installed

grep -q "dead-1.0.0" ${withFix.test-dead}/installed
grep -q "beef-1.0.2" ${withFix.test-beef}/installed
grep -q "ate-1.0.0" ${withFix.test-ate }/installed
grep -q "bad-1.0.51" ${withFix.test-bad }/installed # not renamed
grep -q "food-1.0.0" ${withFix.test-food}/installed

grep -q "dead-1.0.0" ${withFix.test-beef}/installed
grep -q "beef-1.0.0" ${withFix.test-ate }/installed # not updated
grep -q "ate-1.0.0" ${withFix.test-bad }/installed
grep -q "bad-1.0.0" ${withFix.test-food}/installed # not updated

grep -q "dead-1.0.0" ${withFix.test-ate }/installed
grep -q "beef-1.0.0" ${withFix.test-bad }/installed # not updated
grep -q "ate-1.0.0" ${withFix.test-food}/installed

grep -q "dead-1.0.0" ${withFix.test-bad }/installed
grep -q "beef-1.0.0" ${withFix.test-food}/installed # not updated

grep -q "dead-1.0.0" ${withFix.test-food}/installed

: Check dependencies hashes.
grep -q ${withoutFix.test-dead} ${withoutFix.test-dead}/dependency
grep -q ${withoutFix.test-beef} ${withoutFix.test-beef}/dependency
grep -q ${withoutFix.test-ate } ${withoutFix.test-ate }/dependency
grep -q ${withoutFix.test-bad } ${withoutFix.test-bad }/dependency
grep -q ${withoutFix.test-food} ${withoutFix.test-food}/dependency

grep -q ${withoutFix.test-dead} ${withoutFix.test-beef}/dependency
grep -q ${withoutFix.test-beef} ${withoutFix.test-ate }/dependency
grep -q ${withoutFix.test-ate } ${withoutFix.test-bad }/dependency
grep -q ${withoutFix.test-bad } ${withoutFix.test-food}/dependency

grep -q ${withoutFix.test-dead} ${withoutFix.test-ate }/dependency
grep -q ${withoutFix.test-beef} ${withoutFix.test-bad }/dependency
grep -q ${withoutFix.test-ate } ${withoutFix.test-food}/dependency

grep -q ${withoutFix.test-dead} ${withoutFix.test-bad }/dependency
grep -q ${withoutFix.test-beef} ${withoutFix.test-food}/dependency

grep -q ${withoutFix.test-dead} ${withoutFix.test-food}/dependency

grep -q ${withFix.test-dead} ${withFix.test-dead}/dependency
grep -q ${withFix.test-beef} ${withFix.test-beef}/dependency # recompiled
grep -q ${withFix.test-ate } ${withFix.test-ate }/dependency
grep -q ${withFix.test-bad } ${withFix.test-bad }/dependency # recompiled
grep -q ${withFix.test-food} ${withFix.test-food}/dependency

grep -q ${withFix.test-dead} ${withFix.test-beef}/dependency
grep -q ${withFix.test-beef} ${withFix.test-ate }/dependency # patched
grep -q ${withFix.test-ate } ${withFix.test-bad }/dependency
grep -q ${withFix.test-bad } ${withFix.test-food}/dependency # patched

grep -q ${withFix.test-dead} ${withFix.test-ate }/dependency
grep -q ${withFix.test-beef} ${withFix.test-bad }/dependency # patched
grep -q ${withFix.test-ate } ${withFix.test-food}/dependency

grep -q ${withFix.test-dead} ${withFix.test-bad }/dependency
grep -q ${withFix.test-beef} ${withFix.test-food}/dependency # patched

grep -q ${withFix.test-dead} ${withFix.test-food}/dependency

mkdir -p $out
echo success > $out/result
set +x
'';
}
36 changes: 36 additions & 0 deletions pkgs/test/security/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{ nixpkgs, pkgs }:

with pkgs;

let
nixCommand = name: command:
runCommand name { buildInputs = [ nix ]; } ''
datadir="${nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
export NIX_BUILD_HOOK=
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_DB_DIR=$TEST_ROOT/db
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_STORE_DIR=$TEST_ROOT/store
export PAGER=cat
cacheDir=$TEST_ROOT/binary-cache
nix-store --init

cd ${nixpkgs}/pkgs/test/security
${command}
touch $out
'';
in

{
check-quickfix = import ./check-quickfix.nix;
onefix-noop = nixCommand "onefix-noop" ''
nix-instantiate --timeout 60 ./onefix-noop.nix --eval-only
'';
abifix-noop = nixCommand "abifix-noop" ''
nix-instantiate --timeout 60 ./abifix-noop.nix --eval-only
'';
}
82 changes: 82 additions & 0 deletions pkgs/test/security/lib.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
let
lib = import ../../../lib;
in

with lib;

rec {
inherit lib;

originalPackages = {
adapters = import ../../../pkgs/stdenv/adapters.nix;
builders = import ../../../pkgs/build-support/trivial-builders.nix;
stdenv = import ../../../pkgs/top-level/stdenv.nix;
all = import ../../../pkgs/top-level/all-packages.nix;
aliases = import ../../../pkgs/top-level/aliases.nix;
};

pkgs = import ../../../. {
defaultPackages = originalPackages;
quickfixPackages = null;
doPatchWithDependencies = false;
} // { recurseForDerivations = true; };

onefix = import ../../../. {
defaultPackages = originalPackages;
quickfixPackages = originalPackages;
doPatchWithDependencies = false;
} // { recurseForDerivations = true; };

abifix = import ../../../. {
defaultPackages = originalPackages;
quickfixPackages = originalPackages;
doPatchWithDependencies = true;
} // { recurseForDerivations = true; };

# This is the same as the `collectWithPath` function of Nixpkgs's library,
# except that it uses `tryEval` to ignore invalid evaluations, such as
# broken and unfree packages.
#
# Example:
# maybeCollectWithPath (x: x ? outPath)
# { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
# => [ { path = ["a"]; value = { outPath = "a/"; }; }
# { path = ["b"]; value = { outPath = "b/"; }; }
# ]
#
maybeCollectWithPath = pred: attrs: with lib;
let
collectInternal = path: attrs:
# assert __trace (["maybeCollectWithPath::"] ++ path) true;
addErrorContext "while collecting derivations under ${concatStringsSep "." path}:" (
if pred attrs then
[ { path = concatStringsSep "." path; value = attrs; } ]
else if isAttrs attrs && attrs.recurseForDerivations or false then
concatMap (name: maybeCollectInternal (path ++ [name]) attrs.${name})
(attrNames attrs)
else
[]);

maybeCollectInternal = path: attrs:
# Some evaluation of isAttrs might raise an assertion while
# evaluating Nixpkgs, tryEval is used to work-around this issue.
let res = builtins.tryEval (collectInternal path attrs); in
if res.success then res.value
else [];

in
maybeCollectInternal [] attrs;

# Collect all derivations.
collectDerivations = with lib; pkgs:
maybeCollectWithPath (drv: isDerivation drv && drv.outPath != "") pkgs;

pkgsDrvs = collectDerivations pkgs;
onefixDrvs = collectDerivations onefix;
abifixDrvs = collectDerivations abifix;

# Zip all packages collected so far, and verify that they are equal.
zipPkgs =
lib.zipListsWith
(p: o: p.path == o.path && p.value.outPath == o.value.outPath);
}
6 changes: 6 additions & 0 deletions pkgs/test/security/onefix-noop.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
with import ./lib.nix;

assert builtins.trace "Found ${builtins.toString (builtins.length pkgsDrvs)} packages." true;
assert builtins.length pkgsDrvs == builtins.length onefixDrvs;
assert lib.all lib.id (zipPkgs pkgsDrvs onefixDrvs);
true
Loading