libstore/build: pathContentsGood is physical path aware now
`pathContentsGood` is used to assess the validity of a path as part of derivation goals *in repair mode*. When repair is used with a diverted store, i.e. a store where fsPath(toRealPath(s)) != fsPath(s) for s a store path, this result in utterly broken behavior because it will attempt to assess the goodness of the *logical* store locations, most of the time: /nix/store/... So, if you are repairing your system using a live NixOS ISO. Your ISO contains a `/nix/store` (assumed to be good) and you repair your system which is rooted at /mnt and contains its own /nix/store, that is, a Nix store at /mnt/nix/store. Performing the following operation `nix-store --verify --repair --store /mnt` will assess the contents goodness of the ISO's Nix store. To avoid this, we assess the path existence of the *physical path*, aka the result of `store.toRealPath` applied to a *logical* store path string representation and we verify the hash of the *physical path*. The error messages are not taken care of in this CL as those are purely cosmetic and helps the user understand what is going on. Fixes #892. Change-Id: Ib9e0153cb5683edcf37f1963ebf065ceba5e5dfb Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
@@ -389,10 +389,11 @@ try {
|
||||
printInfo("checking path '%s'...", store.toRealPath(store.printStorePath(path)));
|
||||
auto info = TRY_AWAIT(store.queryPathInfo(path));
|
||||
bool res;
|
||||
if (!pathExists(store.printStorePath(path)))
|
||||
if (!pathExists(store.toRealPath(store.printStorePath(path)))) {
|
||||
res = false;
|
||||
else {
|
||||
HashResult current = hashPath(info->narHash.type, store.printStorePath(path));
|
||||
} else {
|
||||
HashResult current =
|
||||
hashPath(info->narHash.type, store.toRealPath(store.printStorePath(path)));
|
||||
Hash nullHash(HashType::SHA256);
|
||||
res = info->narHash == nullHash || info->narHash == current.first;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ functional_tests_scripts = [
|
||||
'nix-build.sh',
|
||||
'gc-concurrent.sh',
|
||||
'repair.sh',
|
||||
'repair-chroot.sh',
|
||||
'fixed.sh',
|
||||
'export-graph.sh',
|
||||
'timeout.sh',
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
source common.sh
|
||||
|
||||
if [[ $(uname) == Darwin ]]; then skipTest "Darwin does not have diverted stores"; fi
|
||||
needLocalStore "--repair needs a local store"
|
||||
|
||||
clearStore
|
||||
|
||||
path=$(nix-build dependencies.nix -o $TEST_ROOT/result)
|
||||
path2=$(nix-store -qR $path | grep input-2)
|
||||
path2_basename=$(basename $path2)
|
||||
|
||||
# Corrupt a path in a *chroot* store and check whether nix-build --repair can fix it.
|
||||
extra_chroot_store_path="$TEST_ROOT/extra-chroot-store"
|
||||
# Required because otherwise storeDir=/build/... in the sandbox.
|
||||
special_sandbox_build_dir="/build-tmp"
|
||||
chroot_path=$(nix-build dependencies.nix -o $TEST_ROOT/chroot-result --sandbox-build-dir "$special_sandbox_build_dir" --store "$extra_chroot_store_path" --extra-sandbox-paths /nix/store)
|
||||
chroot_path2="$extra_chroot_store_path/nix/store/$path2_basename"
|
||||
|
||||
[ -d $chroot_path2 ] || fail "chroot path $chroot_path2 does not exist"
|
||||
|
||||
nix-store --verify --check-contents --sandbox-build-dir "$special_sandbox_build_dir" -v --store "$extra_chroot_store_path" |& grepQuiet "$extra_chroot_store_path" || fail "$extra_chroot_store_path does not occur in the store verification, the chroot store parameter is ignored."
|
||||
chroot_hash=$(nix-hash $path2)
|
||||
|
||||
chmod u+w $chroot_path2
|
||||
touch $chroot_path2/bad
|
||||
|
||||
! nix-store --verify --check-contents -v --store "$extra_chroot_store_path" --sandbox-build-dir "$special_sandbox_build_dir"
|
||||
|
||||
# The path can be repaired by rebuilding the derivation.
|
||||
nix-store --verify --check-contents --repair --store "$extra_chroot_store_path" --extra-sandbox-paths /nix/store --sandbox-build-dir "$special_sandbox_build_dir"
|
||||
|
||||
! [ -e $chroot_path2/bad ]
|
||||
! [ -w $chroot_path2 ]
|
||||
|
||||
# NOTE: verify path must be given the *LOGICAL* path here. And not the physical path. Confusing? I know.
|
||||
nix-store --verify-path $path2 --store "$extra_chroot_store_path"
|
||||
Reference in New Issue
Block a user