2024-01-23 01:23:14 +00:00
|
|
|
{ lib
|
2024-06-01 13:24:41 +00:00
|
|
|
, stdenv
|
2024-02-06 05:01:30 +00:00
|
|
|
, buildPackages
|
2024-06-01 13:24:41 +00:00
|
|
|
, file
|
|
|
|
, gnugrep
|
2024-02-27 22:26:56 +00:00
|
|
|
, runCommandLocal
|
2024-01-23 01:23:14 +00:00
|
|
|
, runtimeShell
|
2024-05-15 01:41:40 +00:00
|
|
|
, sanebox
|
2024-01-29 11:42:47 +00:00
|
|
|
, symlinkJoin
|
2024-01-28 07:45:08 +00:00
|
|
|
, writeShellScriptBin
|
2024-01-23 08:01:23 +00:00
|
|
|
, writeTextFile
|
2024-01-23 01:23:14 +00:00
|
|
|
}:
|
2024-01-27 14:26:41 +00:00
|
|
|
let
|
2024-05-15 01:41:40 +00:00
|
|
|
fakeSaneSandboxed = writeShellScriptBin "sanebox" ''
|
|
|
|
# behave like the real sanebox with SANEBOX_DISABLE=1,
|
|
|
|
# but in a manner which avoids taking a dependency on the real sanebox.
|
|
|
|
# the primary use for this is to allow a package's `check` phase to work even when sanebox isn't available.
|
2024-01-28 07:45:08 +00:00
|
|
|
_origArgs=($@)
|
2024-01-29 09:56:30 +00:00
|
|
|
|
|
|
|
# throw away all arguments until we find the path to the binary which is being sandboxed
|
|
|
|
while [ "$#" -gt 0 ] && ! [[ "$1" =~ /\.sandboxed/ ]]; do
|
2024-01-28 07:45:08 +00:00
|
|
|
shift
|
|
|
|
done
|
|
|
|
if [ "$#" -eq 0 ]; then
|
2024-05-15 01:41:40 +00:00
|
|
|
>&2 echo "sanebox (mock): failed to parse args: ''${_origArgs[*]}"
|
2024-01-28 07:45:08 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2024-01-29 09:56:30 +00:00
|
|
|
|
2024-05-15 01:41:40 +00:00
|
|
|
if [ -z "$SANEBOX_DISABLE" ]; then
|
|
|
|
>&2 echo "sanebox (mock): not called with SANEBOX_DISABLE=1; unsure how to sandbox: ''${_origArgs[*]}"
|
2024-01-28 07:45:08 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
2024-01-29 09:56:30 +00:00
|
|
|
# assume that every argument after the binary name is an argument for the binary and not for the sandboxer.
|
2024-01-28 07:45:08 +00:00
|
|
|
exec "$@"
|
|
|
|
'';
|
2024-01-27 12:23:25 +00:00
|
|
|
|
2024-03-02 07:11:28 +00:00
|
|
|
makeHookable = pkg: pkg.overrideAttrs (drv: lib.optionalAttrs (drv ? buildCommand && !lib.hasInfix "postFixup" drv.buildCommand) {
|
|
|
|
buildCommand = drv.buildCommand + ''
|
|
|
|
runHook postFixup
|
|
|
|
'';
|
|
|
|
});
|
2024-01-23 01:23:14 +00:00
|
|
|
|
2024-01-29 11:42:47 +00:00
|
|
|
# take an existing package, which may have a `bin/` folder as well as `share/` etc,
|
|
|
|
# and patch the `bin/` items in-place
|
2024-05-15 01:41:40 +00:00
|
|
|
sandboxBinariesInPlace = sanebox': extraSandboxArgsStr: pkgName: pkg: pkg.overrideAttrs (unwrapped: {
|
2024-01-28 07:45:08 +00:00
|
|
|
# disable the sandbox and inject a minimal fake sandboxer which understands that flag,
|
|
|
|
# in order to support packages which invoke sandboxed apps in their check phase.
|
|
|
|
# note that it's not just for packages which invoke their *own* binaries in check phase,
|
|
|
|
# but also packages which invoke OTHER PACKAGES' sandboxed binaries.
|
2024-01-28 08:58:13 +00:00
|
|
|
# hence, put the fake sandbox in nativeBuildInputs instead of nativeCheckInputs.
|
2024-01-28 07:45:08 +00:00
|
|
|
env = (unwrapped.env or {}) // {
|
2024-05-15 01:41:40 +00:00
|
|
|
SANEBOX_DISABLE = 1;
|
2024-01-28 07:45:08 +00:00
|
|
|
};
|
2024-03-13 04:49:02 +00:00
|
|
|
# TODO: handle multi-output packages; until then, squash lib into the main output, particularly for `libexec`.
|
|
|
|
# (this line here only affects `inplace` style wrapping)
|
|
|
|
outputs = lib.remove "lib" (unwrapped.outputs or [ "out" ]);
|
2024-01-28 07:45:08 +00:00
|
|
|
nativeBuildInputs = (unwrapped.nativeBuildInputs or []) ++ [
|
|
|
|
fakeSaneSandboxed
|
|
|
|
];
|
2024-01-28 08:58:13 +00:00
|
|
|
disallowedReferences = (unwrapped.disallowedReferences or []) ++ [
|
2024-05-15 01:41:40 +00:00
|
|
|
# the fake sandbox gates itself behind SANEBOX_DISABLE, so if it did end up deployed
|
2024-01-28 08:58:13 +00:00
|
|
|
# then it wouldn't permit anything not already permitted. but it would still be annoying.
|
|
|
|
fakeSaneSandboxed
|
|
|
|
];
|
2024-01-28 07:45:08 +00:00
|
|
|
|
2024-01-23 01:23:14 +00:00
|
|
|
postFixup = (unwrapped.postFixup or "") + ''
|
2024-01-23 08:01:23 +00:00
|
|
|
sandboxWrap() {
|
2024-02-28 17:35:40 +00:00
|
|
|
local _dir="$1"
|
|
|
|
local _name="$2"
|
2024-01-23 08:01:23 +00:00
|
|
|
|
2024-01-29 09:56:30 +00:00
|
|
|
# N.B.: unlike `makeWrapper`, we place the unwrapped binary in a subdirectory and *preserve its name*.
|
|
|
|
# the upside of this is that for applications which read "$0" to decide what to do (e.g. busybox, git)
|
|
|
|
# they work as expected without any special hacks.
|
|
|
|
# if desired, makeWrapper-style naming could be achieved by leveraging `exec -a <original_name>`.
|
2024-02-16 03:15:45 +00:00
|
|
|
mkdir -p "$_dir/.sandboxed"
|
|
|
|
if [[ "$(readlink $_dir/$_name)" =~ ^\.\./ ]]; then
|
2024-02-02 22:38:36 +00:00
|
|
|
# relative links which ascend a directory (into a non-bin/ directory)
|
|
|
|
# won't point to the right place if we naively move them
|
2024-02-16 03:15:45 +00:00
|
|
|
ln -s "../$(readlink $_dir/$_name)" "$_dir/.sandboxed/$_name"
|
|
|
|
rm "$_dir/$_name"
|
2024-02-02 22:38:36 +00:00
|
|
|
else
|
2024-02-16 03:15:45 +00:00
|
|
|
mv "$_dir/$_name" "$_dir/.sandboxed/"
|
2024-02-02 22:38:36 +00:00
|
|
|
fi
|
2024-04-15 19:56:33 +00:00
|
|
|
echo '#!${runtimeShell}' > "$_dir/$_name"
|
2024-05-15 08:58:30 +00:00
|
|
|
echo 'exec ${sanebox'}' ${extraSandboxArgsStr} "$_dir/.sandboxed/$_name" '"$@"' >> "$_dir/$_name"
|
2024-02-16 03:15:45 +00:00
|
|
|
chmod +x "$_dir/$_name"
|
2024-01-23 01:23:14 +00:00
|
|
|
}
|
|
|
|
|
2024-02-16 03:15:45 +00:00
|
|
|
crawlAndWrap() {
|
2024-02-28 17:35:40 +00:00
|
|
|
local _dir="$1"
|
2024-02-16 03:15:45 +00:00
|
|
|
for _p in $(ls "$_dir/"); do
|
2024-02-28 16:17:48 +00:00
|
|
|
if [ -x "$_dir/$_p" ] && ! [ -d "$_dir/$_p" ]; then
|
2024-02-16 03:15:45 +00:00
|
|
|
sandboxWrap "$_dir" "$_p"
|
|
|
|
elif [ -d "$_dir/$_p" ]; then
|
|
|
|
crawlAndWrap "$_dir/$_p"
|
|
|
|
fi
|
|
|
|
# ignore all non-binaries
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2024-05-31 23:25:09 +00:00
|
|
|
for output in $outputs; do
|
|
|
|
local outdir=''${!output}
|
|
|
|
echo "scanning output '$output' at $outdir for binaries to sandbox"
|
|
|
|
if [ -e "$outdir/bin" ]; then
|
|
|
|
crawlAndWrap "$outdir/bin"
|
|
|
|
fi
|
|
|
|
if [ -e "$outdir/libexec" ]; then
|
|
|
|
crawlAndWrap "$outdir/libexec"
|
|
|
|
fi
|
|
|
|
done
|
2024-01-23 01:23:14 +00:00
|
|
|
'';
|
2024-01-29 11:42:47 +00:00
|
|
|
});
|
|
|
|
|
2024-02-17 03:32:49 +00:00
|
|
|
# there are certain `meta` fields we care to preserve from the original package (priority),
|
|
|
|
# and others we *can't* preserve (outputsToInstall).
|
|
|
|
extractMeta = pkg: if (pkg ? meta) && (pkg.meta ? priority) then {
|
|
|
|
inherit (pkg.meta) priority;
|
|
|
|
} else {};
|
|
|
|
|
2024-01-29 11:42:47 +00:00
|
|
|
# helper used for `wrapperType == "wrappedDerivation"` which simply symlinks all a package's binaries into a new derivation
|
2024-02-27 22:26:56 +00:00
|
|
|
symlinkBinaries = pkgName: package: (runCommandLocal "${pkgName}-bin-only" {} ''
|
2024-02-16 03:15:45 +00:00
|
|
|
set -e
|
|
|
|
if [ -e "${package}/bin" ]; then
|
|
|
|
mkdir -p "$out/bin"
|
|
|
|
${buildPackages.xorg.lndir}/bin/lndir "${package}/bin" "$out/bin"
|
|
|
|
fi
|
2024-05-28 13:35:17 +00:00
|
|
|
if [ "$(readlink ${package}/sbin)" == "bin" ]; then
|
|
|
|
# weird packages like wpa_supplicant depend on a sbin/ -> bin symlink in their service files
|
|
|
|
ln -s bin "$out/sbin"
|
|
|
|
fi
|
2024-02-16 03:15:45 +00:00
|
|
|
if [ -e "${package}/libexec" ]; then
|
|
|
|
mkdir -p "$out/libexec"
|
|
|
|
${buildPackages.xorg.lndir}/bin/lndir "${package}/libexec" "$out/libexec"
|
|
|
|
fi
|
2024-01-29 11:42:47 +00:00
|
|
|
# allow downstream wrapping to hook this (and thereby actually wrap the binaries)
|
|
|
|
runHook postFixup
|
2024-02-17 03:32:49 +00:00
|
|
|
'').overrideAttrs (_: {
|
|
|
|
# specifically, preserve meta.priority
|
|
|
|
meta = extractMeta package;
|
|
|
|
});
|
2024-01-23 10:44:13 +00:00
|
|
|
|
2024-05-28 13:35:17 +00:00
|
|
|
# helper used for `wrapperType == "wrappedDerivation"` which ensures that any copied/symlinked share/ files (like .desktop) files
|
2024-02-06 05:01:30 +00:00
|
|
|
# don't point to the unwrapped binaries.
|
2024-01-29 11:42:47 +00:00
|
|
|
# other important files it preserves:
|
|
|
|
# - share/applications
|
|
|
|
# - share/dbus-1 (frequently a source of leaked references!)
|
|
|
|
# - share/icons
|
|
|
|
# - share/man
|
|
|
|
# - share/mime
|
2024-05-28 13:35:17 +00:00
|
|
|
# - {etc,lib,share}/systemd
|
2024-02-06 19:55:55 +00:00
|
|
|
fixHardcodedRefs = unsandboxed: sandboxedBin: unsandboxedNonBin: unsandboxedNonBin.overrideAttrs (prevAttrs: {
|
2024-02-06 05:01:30 +00:00
|
|
|
postInstall = (prevAttrs.postInstall or "") + ''
|
|
|
|
trySubstitute() {
|
2024-02-28 17:35:40 +00:00
|
|
|
local _outPath="$1"
|
|
|
|
local _pattern="$2"
|
|
|
|
local _from=$(printf "$_pattern" "${unsandboxed}")
|
|
|
|
local _to=$(printf "$_pattern" "${sandboxedBin}")
|
2024-02-06 19:55:55 +00:00
|
|
|
printf "applying known substitutions to %s\n" "$_outPath"
|
|
|
|
# for closure efficiency, we only want to rewrite stuff which actually needs changing,
|
|
|
|
# and allow unchanged stuff to remain as symlinks.
|
|
|
|
# `substitute` can't rewrite symlinks, so instead do the substitution to a temp output
|
|
|
|
# with `--replace-fail` and only recreate the output symlink as a file if the substitution succeeds (i.e. if it matched).
|
|
|
|
if substitute "$_outPath" ./substituteResult --replace-fail "$_from" "$_to"; then
|
|
|
|
mv ./substituteResult "$_outPath"
|
|
|
|
fi
|
2024-02-06 05:01:30 +00:00
|
|
|
}
|
|
|
|
# fixup a few files i understand well enough
|
2024-02-28 17:35:40 +00:00
|
|
|
for d in \
|
|
|
|
$out/etc/xdg/autostart/*.desktop \
|
|
|
|
$out/share/applications/*.desktop \
|
2024-05-28 13:35:17 +00:00
|
|
|
$out/share/dbus-1/{services,system-services}/*.service \
|
|
|
|
$out/{etc,lib,share}/systemd/{system,user}/*.service \
|
2024-02-28 17:35:40 +00:00
|
|
|
; do
|
2024-05-29 12:18:09 +00:00
|
|
|
# Exec: dbus and desktop files
|
|
|
|
# ExecStart,ExecReload: systemd service files
|
|
|
|
for key in Exec ExecStart ExecReload; do
|
|
|
|
for binLoc in bin libexec sbin; do
|
|
|
|
trySubstitute "$d" "$key=%s/$binLoc/"
|
|
|
|
done
|
|
|
|
done
|
2024-02-06 05:01:30 +00:00
|
|
|
done
|
|
|
|
'';
|
2024-02-06 19:55:55 +00:00
|
|
|
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 "/dev/null" unsandboxedNonBin;
|
2024-02-27 22:26:56 +00:00
|
|
|
in runCommandLocal "${sandboxedNonBin.name}-check-sandboxed"
|
2024-02-06 19:55:55 +00:00
|
|
|
{ disallowedReferences = [ unsandboxed ]; }
|
|
|
|
''
|
|
|
|
# dereference every symlink, ensuring that whatever data is behind it does not reference non-sandboxed binaries.
|
|
|
|
# the dereference *can* fail, in case it's a relative symlink that refers to a part of the non-binaries we don't patch.
|
|
|
|
# in such case, this could lead to weird brokenness (e.g. no icons/images), so failing is reasonable.
|
|
|
|
cp -R --dereference "${sandboxedNonBin}" "$out" # IF YOUR BUILD FAILS HERE, TRY SANDBOXING WITH "inplace"
|
|
|
|
''
|
|
|
|
;
|
|
|
|
};
|
2024-02-06 05:01:30 +00:00
|
|
|
});
|
|
|
|
|
2024-02-06 19:55:55 +00:00
|
|
|
# symlink the non-binary files from the unsandboxed package,
|
2024-02-06 05:01:30 +00:00
|
|
|
# patch them to use the sandboxed binaries,
|
|
|
|
# and add some passthru metadata to enforce no lingering references to the unsandboxed binaries.
|
2024-02-17 03:32:49 +00:00
|
|
|
sandboxNonBinaries = pkgName: unsandboxed: sandboxedBin: let
|
2024-02-27 22:26:56 +00:00
|
|
|
sandboxedWithoutFixedRefs = (runCommandLocal "${pkgName}-sandboxed-non-binary" {} ''
|
2024-02-06 19:55:55 +00:00
|
|
|
set -e
|
2024-02-06 05:01:30 +00:00
|
|
|
mkdir "$out"
|
2024-02-27 22:25:17 +00:00
|
|
|
# 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"
|
|
|
|
${buildPackages.xorg.lndir}/bin/lndir "${unsandboxed}/$dir" "$out/$dir"
|
|
|
|
fi
|
|
|
|
done
|
2024-02-06 05:01:30 +00:00
|
|
|
runHook postInstall
|
2024-02-17 03:32:49 +00:00
|
|
|
'').overrideAttrs (_: {
|
|
|
|
# specifically for meta.priority, though it shouldn't actually matter here.
|
|
|
|
meta = extractMeta unsandboxed;
|
|
|
|
});
|
|
|
|
in fixHardcodedRefs unsandboxed sandboxedBin sandboxedWithoutFixedRefs;
|
2024-01-29 11:42:47 +00:00
|
|
|
|
|
|
|
# take the nearly-final sandboxed package, with binaries and and else, and
|
2024-02-12 11:52:33 +00:00
|
|
|
# populate passthru attributes the caller expects, like `checkSandboxed`.
|
|
|
|
fixupMetaAndPassthru = pkgName: pkg: extraPassthru: pkg.overrideAttrs (finalAttrs: prevAttrs: let
|
2024-02-06 19:55:55 +00:00
|
|
|
nonBin = (prevAttrs.passthru or {}).sandboxedNonBin or {};
|
2024-01-29 11:42:47 +00:00
|
|
|
in {
|
2024-02-06 05:01:30 +00:00
|
|
|
meta = (prevAttrs.meta or {}) // {
|
2024-01-23 01:23:14 +00:00
|
|
|
# take precedence over non-sandboxed versions of the same binary.
|
2024-02-06 05:01:30 +00:00
|
|
|
priority = ((prevAttrs.meta or {}).priority or 0) - 1;
|
2024-01-23 01:23:14 +00:00
|
|
|
};
|
2024-02-06 05:01:30 +00:00
|
|
|
passthru = (prevAttrs.passthru or {}) // extraPassthru // {
|
2024-05-31 23:53:42 +00:00
|
|
|
checkSandboxed = runCommandLocal "${pkgName}-check-sandboxed" {
|
2024-06-01 13:24:41 +00:00
|
|
|
nativeBuildInputs = [ file gnugrep sanebox ];
|
2024-05-31 23:53:42 +00:00
|
|
|
buildInputs = builtins.map (out: finalAttrs.finalPackage."${out}") (finalAttrs.outputs or [ "out" ]);
|
|
|
|
} ''
|
2024-02-06 19:55:55 +00:00
|
|
|
set -e
|
2024-01-23 10:44:13 +00:00
|
|
|
# invoke each binary in a way only the sandbox wrapper will recognize,
|
|
|
|
# ensuring that every binary has in fact been wrapped.
|
|
|
|
_numExec=0
|
2024-02-16 03:15:45 +00:00
|
|
|
_checkExecutable() {
|
2024-05-31 23:53:42 +00:00
|
|
|
local dir="$1"
|
|
|
|
local binname="$2"
|
|
|
|
echo "checking if $dir/$binname is sandboxed"
|
|
|
|
# XXX: call by full path because some binaries (e.g. util-linux) would otherwise
|
|
|
|
# be shadowed by things the nix builder implicitly puts on PATH.
|
2024-06-01 13:24:41 +00:00
|
|
|
# additionally, call via qemu and manually specify the interpreter *if the file has one*.
|
|
|
|
# if the file doesn't have an interpreter, assume it's directly invokable by qemu (hence, the intentional lack of quotes around `interpreter`)
|
|
|
|
set -x
|
|
|
|
local realbin="$(realpath $dir/$binname)"
|
|
|
|
local interpreter=$(file "$realbin" | grep --only-matching "a /nix/.* script" | cut -d" " -f2 || echo "")
|
|
|
|
${stdenv.hostPlatform.emulator buildPackages} $interpreter "$dir/$binname" --sanebox-replace-cli echo "printing for test" \
|
2024-01-23 11:19:52 +00:00
|
|
|
| grep "printing for test"
|
2024-01-23 10:44:13 +00:00
|
|
|
_numExec=$(( $_numExec + 1 ))
|
2024-02-16 03:15:45 +00:00
|
|
|
}
|
|
|
|
_checkDir() {
|
2024-05-31 23:53:42 +00:00
|
|
|
local dir="$1"
|
|
|
|
for b in $(ls "$dir"); do
|
|
|
|
if [ -d "$dir/$b" ]; then
|
2024-02-16 03:15:45 +00:00
|
|
|
if [ "$b" != .sandboxed ]; then
|
2024-05-31 23:53:42 +00:00
|
|
|
_checkDir "$dir/$b"
|
2024-02-16 03:15:45 +00:00
|
|
|
fi
|
2024-05-31 23:53:42 +00:00
|
|
|
elif [ -x "$dir/$b" ]; then
|
|
|
|
_checkExecutable "$dir" "$b"
|
2024-02-16 03:15:45 +00:00
|
|
|
else
|
|
|
|
test -n "$CHECK_DIR_NON_BIN"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2024-05-31 23:53:42 +00:00
|
|
|
for outDir in $buildInputs; do
|
|
|
|
echo "starting crawl from package output: $outDir"
|
|
|
|
# *everything* in the bin dir should be a wrapped executable
|
|
|
|
if [ -e "$outDir/bin" ]; then
|
|
|
|
echo "checking toplevel dir at $outDir/bin"
|
|
|
|
_checkDir "$outDir/bin"
|
|
|
|
fi
|
2024-02-16 03:15:45 +00:00
|
|
|
|
2024-05-31 23:53:42 +00:00
|
|
|
# the libexec dir is 90% wrapped executables, but sometimes also .so/.la objects.
|
|
|
|
# note that this directory isn't flat
|
|
|
|
if [ -e "$outDir/libexec" ]; then
|
|
|
|
echo "checking toplevel dir at $outDir/libexec"
|
|
|
|
CHECK_DIR_NON_BIN=1 _checkDir "$outDir/libexec"
|
|
|
|
fi
|
|
|
|
done
|
2024-01-23 10:44:13 +00:00
|
|
|
|
|
|
|
echo "successfully tested $_numExec binaries"
|
2024-02-06 19:55:55 +00:00
|
|
|
test "$_numExec" -ne 0
|
|
|
|
mkdir "$out"
|
2024-02-06 05:01:30 +00:00
|
|
|
# forward prevAttrs checkSandboxed, to guarantee correctness for the /share directory (`sandboxNonBinaries`).
|
2024-02-06 19:55:55 +00:00
|
|
|
ln -s ${nonBin.checkSandboxed or "/dev/null"} "$out/sandboxed-non-binaries"
|
2024-01-23 01:23:14 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
});
|
2024-01-29 11:42:47 +00:00
|
|
|
|
2024-04-15 19:56:33 +00:00
|
|
|
make-sandboxed = { pkgName, package, wrapperType, embedSandboxer ? false, extraSandboxerArgs ? [], passthru ? {} }@args:
|
2024-02-03 00:17:24 +00:00
|
|
|
let
|
2024-02-06 19:55:55 +00:00
|
|
|
unsandboxed = package;
|
2024-05-15 01:41:40 +00:00
|
|
|
sanebox' = if embedSandboxer then
|
2024-02-03 00:17:24 +00:00
|
|
|
# optionally hard-code the sandboxer. this forces rebuilds, but allows deep iteration w/o deploys.
|
2024-05-15 01:41:40 +00:00
|
|
|
lib.getExe sanebox
|
2024-02-03 00:17:24 +00:00
|
|
|
else
|
|
|
|
#v prefer to load by bin name to reduce rebuilds
|
2024-05-15 01:41:40 +00:00
|
|
|
sanebox.meta.mainProgram
|
2024-02-03 00:17:24 +00:00
|
|
|
;
|
2024-01-29 11:42:47 +00:00
|
|
|
|
2024-02-12 11:52:33 +00:00
|
|
|
extraSandboxerArgsStr = lib.escapeShellArgs extraSandboxerArgs;
|
2024-01-29 12:52:01 +00:00
|
|
|
|
2024-02-03 00:17:24 +00:00
|
|
|
# two ways i could wrap a package in a sandbox:
|
|
|
|
# 1. package.overrideAttrs, with `postFixup`.
|
|
|
|
# 2. pkgs.symlinkJoin, creating an entirely new package which calls into the inner binaries.
|
|
|
|
#
|
|
|
|
# here we switch between the options.
|
|
|
|
# regardless of which one is chosen here, all other options are exposed via `passthru`.
|
|
|
|
sandboxedBy = {
|
|
|
|
inplace = sandboxBinariesInPlace
|
2024-05-15 01:41:40 +00:00
|
|
|
sanebox'
|
2024-02-12 11:52:33 +00:00
|
|
|
extraSandboxerArgsStr
|
2024-01-29 11:42:47 +00:00
|
|
|
pkgName
|
2024-02-06 19:55:55 +00:00
|
|
|
(makeHookable unsandboxed);
|
2024-02-03 00:17:24 +00:00
|
|
|
|
|
|
|
wrappedDerivation = let
|
2024-02-06 19:55:55 +00:00
|
|
|
sandboxedBin = sandboxBinariesInPlace
|
2024-05-15 01:41:40 +00:00
|
|
|
sanebox'
|
2024-02-12 11:52:33 +00:00
|
|
|
extraSandboxerArgsStr
|
2024-02-03 00:17:24 +00:00
|
|
|
pkgName
|
2024-02-06 19:55:55 +00:00
|
|
|
(symlinkBinaries pkgName unsandboxed);
|
|
|
|
sandboxedNonBin = sandboxNonBinaries pkgName unsandboxed sandboxedBin;
|
2024-02-03 00:17:24 +00:00
|
|
|
in symlinkJoin {
|
|
|
|
name = "${pkgName}-sandboxed-all";
|
2024-02-06 19:55:55 +00:00
|
|
|
paths = [ sandboxedBin sandboxedNonBin ];
|
|
|
|
passthru = { inherit sandboxedBin sandboxedNonBin unsandboxed; };
|
2024-02-17 03:32:49 +00:00
|
|
|
# specifically, for priority
|
|
|
|
meta = extractMeta sandboxedBin;
|
2024-02-03 00:17:24 +00:00
|
|
|
};
|
2024-01-29 12:52:01 +00:00
|
|
|
};
|
2024-02-03 00:17:24 +00:00
|
|
|
packageWrapped = sandboxedBy."${wrapperType}";
|
|
|
|
in
|
2024-02-12 11:52:33 +00:00
|
|
|
fixupMetaAndPassthru pkgName packageWrapped (passthru // {
|
|
|
|
# allow the user to build this package, but sandboxed in a different manner.
|
|
|
|
# e.g. `<pkg>.sandboxedBy.inplace`.
|
2024-02-16 03:15:45 +00:00
|
|
|
# e.g. `<pkg>.sandboxedBy.wrappedDerivation.sandboxedNonBin`
|
2024-02-03 00:17:24 +00:00
|
|
|
inherit sandboxedBy;
|
2024-02-12 11:52:33 +00:00
|
|
|
})
|
2024-02-03 00:17:24 +00:00
|
|
|
;
|
|
|
|
in make-sandboxed
|