make-sandboxed: fix several edge-cases for e.g. brave, firefox, especially around handling of wrapped binaries
This commit is contained in:
@@ -156,7 +156,9 @@ let
|
||||
for item in "''${items[@]}"; do
|
||||
if [ "$item" != . ] && [ "$item" != .. ]; then
|
||||
local target="$_dir/$item"
|
||||
if [ -x "$target" ] && ! [ -d "$target" ]; then
|
||||
if [ -d "$target" ]; then
|
||||
crawlAndWrap "$output" "$target"
|
||||
elif [ -x "$target" ] && [[ "$item" != .* ]]; then
|
||||
# in the case of symlinks, deref until we find the real file, or the symlink points outside the package
|
||||
target=$(derefWhileInSameOutput "$output" "$target")
|
||||
target=$(findUnwrapped "$target")
|
||||
@@ -165,10 +167,8 @@ let
|
||||
local bin=$(basename "$target")
|
||||
sandboxWrap "$parent" "$bin"
|
||||
fi
|
||||
elif [ -d "$target" ]; then
|
||||
crawlAndWrap "$output" "$target"
|
||||
fi
|
||||
# ignore all non-binaries
|
||||
# ignore all non-binaries or "hidden" binaries (to avoid double-wrapping)
|
||||
fi
|
||||
done
|
||||
}
|
||||
@@ -196,15 +196,14 @@ let
|
||||
;
|
||||
|
||||
# helper used for `wrapperType == "wrappedDerivation"` which simply symlinks all a package's binaries into a new derivation
|
||||
symlinkBinaries = pkgName: package: (runCommandLocal "${pkgName}-bin-only" {
|
||||
symlinkDirs = suffix: symlinkRoots: pkgName: package: (runCommandLocal "${pkgName}-${suffix}" {
|
||||
env.symlinkRoots = lib.concatStringsSep " " symlinkRoots;
|
||||
nativeBuildInputs = [ gnused ];
|
||||
} ''
|
||||
set -e
|
||||
symlinkPath() {
|
||||
if [ -e "$out/$1" ]; then
|
||||
: # already linked. may happen when e.g. the package has bin/foo, and sbin -> bin.
|
||||
elif ! [ -x "${package}/$1" ]; then
|
||||
: # not a binary, nor a directory (-x) which could contain binaries
|
||||
elif [ -L "${package}/$1" ]; then
|
||||
local target=$(readlink "${package}/$1")
|
||||
if [[ "$target" =~ ^${package}/ ]]; then
|
||||
@@ -235,7 +234,7 @@ let
|
||||
mkdir -p "$out/$1"
|
||||
items=($(ls -a "${package}/$1"))
|
||||
for item in "''${items[@]}"; do
|
||||
if [ "$item" != . ] && [ "$item" != .. ]; then
|
||||
if [ "$item" != . ] && [ "$item" != .. ] && [[ "$item" != .* ]]; then
|
||||
symlinkPath "$1/$item"
|
||||
fi
|
||||
done
|
||||
@@ -244,16 +243,22 @@ let
|
||||
ln -s "${package}/$1" "$out/$1"
|
||||
fi
|
||||
}
|
||||
symlinkPath bin
|
||||
symlinkPath sbin
|
||||
symlinkPath libexec
|
||||
# allow downstream wrapping to hook this (and thereby actually wrap the binaries)
|
||||
mkdir -p "$out"
|
||||
_symlinkRoots=($symlinkRoots)
|
||||
for root in "''${_symlinkRoots[@]}"; do
|
||||
echo "crawling top-level directory for symlinking: $root"
|
||||
symlinkPath "$root"
|
||||
done
|
||||
# allow downstream wrapping to hook this (and thereby actually wrap binaries, etc)
|
||||
runHook postInstall
|
||||
runHook postFixup
|
||||
'').overrideAttrs (_: {
|
||||
# specifically, preserve meta.priority
|
||||
meta = extractMeta package;
|
||||
});
|
||||
|
||||
symlinkBinaries = symlinkDirs "bin-only" [ "bin" "sbin" "libexec" ];
|
||||
|
||||
# helper used for `wrapperType == "wrappedDerivation"` which ensures that any copied/symlinked share/ files (like .desktop) files
|
||||
# don't point to the unwrapped binaries.
|
||||
# other important files it preserves:
|
||||
@@ -281,12 +286,9 @@ let
|
||||
}
|
||||
|
||||
# remove any files which exist in sandoxedBin (makes it possible to sandbox /opt-style packages)
|
||||
# also remove any files which would be "hidden". mostly useful for /opt-style packages which contain nix-wrapped binaries.
|
||||
removeUnwanted() {
|
||||
local file_=$(basename "$1")
|
||||
if [[ "$file_" == .* ]]; then
|
||||
rm -r "$out/$1"
|
||||
elif [ -f "$out/$1" ] || [ -L "$out/$1" ]; then
|
||||
if [ -f "$out/$1" ] || [ -L "$out/$1" ]; then
|
||||
if [ -e "${sandboxedBin}/$1" ]; then
|
||||
rm "$out/$1"
|
||||
fi
|
||||
@@ -320,8 +322,6 @@ let
|
||||
passthru = (prevAttrs.passthru or {}) // {
|
||||
# check that sandboxedNonBin references only sandboxed binaries, and never the original unsandboxed binaries.
|
||||
# do this by dereferencing all sandboxedNonBin symlinks, and making `unsandboxed` a disallowedReference.
|
||||
# further, since the sandboxed binaries intentionally reference the unsandboxed binaries,
|
||||
# we have to patch those out as a way to whitelist them.
|
||||
checkSandboxed = let
|
||||
sandboxedNonBin = fixHardcodedRefs unsandboxed sandboxedBin unsandboxedNonBin;
|
||||
in runCommandLocal "${sandboxedNonBin.name}-check-sandboxed"
|
||||
@@ -342,25 +342,7 @@ let
|
||||
# patch them to use the sandboxed binaries,
|
||||
# and add some passthru metadata to enforce no lingering references to the unsandboxed binaries.
|
||||
sandboxNonBinaries = pkgName: unsandboxed: sandboxedBin: let
|
||||
sandboxedWithoutFixedRefs = (runCommandLocal "${pkgName}-sandboxed-non-binary" {
|
||||
nativeBuildInputs = [ xorg.lndir ];
|
||||
} ''
|
||||
set -e
|
||||
mkdir "$out"
|
||||
# link in a limited subset of the directories.
|
||||
# lib/ is the primary one to avoid, because of shared objects that would be unsandboxed if dlopen'd.
|
||||
# all other directories are safe-ish, because they won't end up on PATH or LDPATH.
|
||||
for dir in etc share; do
|
||||
if [ -e "${unsandboxed}/$dir" ]; then
|
||||
mkdir "$out/$dir"
|
||||
lndir "${unsandboxed}/$dir" "$out/$dir"
|
||||
fi
|
||||
done
|
||||
runHook postInstall
|
||||
'').overrideAttrs (_: {
|
||||
# specifically for meta.priority, though it shouldn't actually matter here.
|
||||
meta = extractMeta unsandboxed;
|
||||
});
|
||||
sandboxedWithoutFixedRefs = symlinkDirs "non-bin" [ "etc" "share" ] pkgName unsandboxed;
|
||||
in fixHardcodedRefs unsandboxed sandboxedBin sandboxedWithoutFixedRefs;
|
||||
|
||||
# take the nearly-final sandboxed package, with binaries and all else, and
|
||||
|
Reference in New Issue
Block a user