sandboxing: fix checkSandboxed
to handle packages with multiple outputs
This commit is contained in:
parent
e3e86a43a9
commit
f875db916d
|
@ -39,7 +39,8 @@ let
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
makeSandboxArgs = pkgs.callPackage ./make-sandbox-args.nix { };
|
makeSandboxArgs = pkgs.callPackage ./make-sandbox-args.nix { };
|
||||||
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sanebox = config.sane.programs.sanebox.package; };
|
# makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sanebox = config.sane.programs.sanebox.package; };
|
||||||
|
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { };
|
||||||
|
|
||||||
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);
|
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);
|
||||||
|
|
||||||
|
|
|
@ -229,43 +229,54 @@ let
|
||||||
priority = ((prevAttrs.meta or {}).priority or 0) - 1;
|
priority = ((prevAttrs.meta or {}).priority or 0) - 1;
|
||||||
};
|
};
|
||||||
passthru = (prevAttrs.passthru or {}) // extraPassthru // {
|
passthru = (prevAttrs.passthru or {}) // extraPassthru // {
|
||||||
checkSandboxed = runCommandLocal "${pkgName}-check-sandboxed" {} ''
|
checkSandboxed = runCommandLocal "${pkgName}-check-sandboxed" {
|
||||||
|
nativeBuildInputs = [ sanebox ];
|
||||||
|
buildInputs = builtins.map (out: finalAttrs.finalPackage."${out}") (finalAttrs.outputs or [ "out" ]);
|
||||||
|
} ''
|
||||||
set -e
|
set -e
|
||||||
# invoke each binary in a way only the sandbox wrapper will recognize,
|
# invoke each binary in a way only the sandbox wrapper will recognize,
|
||||||
# ensuring that every binary has in fact been wrapped.
|
# ensuring that every binary has in fact been wrapped.
|
||||||
_numExec=0
|
_numExec=0
|
||||||
_checkExecutable() {
|
_checkExecutable() {
|
||||||
echo "checking if $1 is sandboxed"
|
local dir="$1"
|
||||||
PATH="${finalAttrs.finalPackage}/bin:${sanebox}/bin:$PATH" \
|
local binname="$2"
|
||||||
SANEBOX_DISABLE=1 \
|
echo "checking if $dir/$binname is sandboxed"
|
||||||
"$1" --sanebox-replace-cli echo "printing for test" \
|
# 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.
|
||||||
|
"$dir/$binname" --sanebox-replace-cli echo "printing for test" \
|
||||||
| grep "printing for test"
|
| grep "printing for test"
|
||||||
_numExec=$(( $_numExec + 1 ))
|
_numExec=$(( $_numExec + 1 ))
|
||||||
}
|
}
|
||||||
_checkDir() {
|
_checkDir() {
|
||||||
for b in $(ls "$1"); do
|
local dir="$1"
|
||||||
if [ -d "$1/$b" ]; then
|
for b in $(ls "$dir"); do
|
||||||
|
if [ -d "$dir/$b" ]; then
|
||||||
if [ "$b" != .sandboxed ]; then
|
if [ "$b" != .sandboxed ]; then
|
||||||
_checkDir "$1/$b"
|
_checkDir "$dir/$b"
|
||||||
fi
|
fi
|
||||||
elif [ -x "$1/$b" ]; then
|
elif [ -x "$dir/$b" ]; then
|
||||||
_checkExecutable "$1/$b"
|
_checkExecutable "$dir" "$b"
|
||||||
else
|
else
|
||||||
test -n "$CHECK_DIR_NON_BIN"
|
test -n "$CHECK_DIR_NON_BIN"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for outDir in $buildInputs; do
|
||||||
|
echo "starting crawl from package output: $outDir"
|
||||||
# *everything* in the bin dir should be a wrapped executable
|
# *everything* in the bin dir should be a wrapped executable
|
||||||
if [ -e "${finalAttrs.finalPackage}/bin" ]; then
|
if [ -e "$outDir/bin" ]; then
|
||||||
_checkDir "${finalAttrs.finalPackage}/bin"
|
echo "checking toplevel dir at $outDir/bin"
|
||||||
|
_checkDir "$outDir/bin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# the libexec dir is 90% wrapped executables, but sometimes also .so/.la objects.
|
# the libexec dir is 90% wrapped executables, but sometimes also .so/.la objects.
|
||||||
# note that this directory isn't flat
|
# note that this directory isn't flat
|
||||||
if [ -e "${finalAttrs.finalPackage}/libexec" ]; then
|
if [ -e "$outDir/libexec" ]; then
|
||||||
CHECK_DIR_NON_BIN=1 _checkDir "${finalAttrs.finalPackage}/libexec"
|
echo "checking toplevel dir at $outDir/libexec"
|
||||||
|
CHECK_DIR_NON_BIN=1 _checkDir "$outDir/libexec"
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
echo "successfully tested $_numExec binaries"
|
echo "successfully tested $_numExec binaries"
|
||||||
test "$_numExec" -ne 0
|
test "$_numExec" -ne 0
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{ lib, stdenv
|
{ lib, stdenv
|
||||||
, bash
|
, bash
|
||||||
, bubblewrap
|
, bubblewrap
|
||||||
|
, coreutils
|
||||||
, passt
|
, passt
|
||||||
, landlock-sandboxer
|
, landlock-sandboxer
|
||||||
, libcap
|
, libcap
|
||||||
|
@ -24,7 +25,8 @@ stdenv.mkDerivation {
|
||||||
--replace-fail '@bwrap@' '${lib.getExe bubblewrap}' \
|
--replace-fail '@bwrap@' '${lib.getExe bubblewrap}' \
|
||||||
--replace-fail '@landlockSandboxer@' '${lib.getExe landlock-sandboxer}' \
|
--replace-fail '@landlockSandboxer@' '${lib.getExe landlock-sandboxer}' \
|
||||||
--replace-fail '@capsh@' '${lib.getExe' libcap "capsh"}' \
|
--replace-fail '@capsh@' '${lib.getExe' libcap "capsh"}' \
|
||||||
--replace-fail '@pasta@' '${lib.getExe' passt "pasta"}'
|
--replace-fail '@pasta@' '${lib.getExe' passt "pasta"}' \
|
||||||
|
--replace-fail '@env@' '${lib.getExe' coreutils "env"}'
|
||||||
runHook postBuild
|
runHook postBuild
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -36,6 +38,16 @@ stdenv.mkDerivation {
|
||||||
runHook postInstall
|
runHook postInstall
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
runtimeDeps = [
|
||||||
|
bubblewrap
|
||||||
|
coreutils
|
||||||
|
landlock-sandboxer
|
||||||
|
libcap
|
||||||
|
passt
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = ''
|
description = ''
|
||||||
helper program to run some other program in a sandbox.
|
helper program to run some other program in a sandbox.
|
||||||
|
|
|
@ -6,6 +6,7 @@ BWRAP_FALLBACK='@bwrap@'
|
||||||
LANDLOCK_SANDBOXER_FALLBACK='@landlockSandboxer@'
|
LANDLOCK_SANDBOXER_FALLBACK='@landlockSandboxer@'
|
||||||
CAPSH_FALLBACK='@capsh@'
|
CAPSH_FALLBACK='@capsh@'
|
||||||
PASTA_FALLBACK='@pasta@'
|
PASTA_FALLBACK='@pasta@'
|
||||||
|
ENV_FALLBACK='@env@'
|
||||||
|
|
||||||
|
|
||||||
## EARLY DEBUG HOOKS
|
## EARLY DEBUG HOOKS
|
||||||
|
@ -254,13 +255,17 @@ parent() {
|
||||||
|
|
||||||
# `locate outVar <bin-name> </path/to/default>` => if `<bin-name>` is on PATH, then return that, else </path/to/default>
|
# `locate outVar <bin-name> </path/to/default>` => if `<bin-name>` is on PATH, then return that, else </path/to/default>
|
||||||
locate() {
|
locate() {
|
||||||
# N.B.: explicitly avoid returning the output of `command -v`, for optimization.
|
local outVar="$1"
|
||||||
# unlike other bash builtins, `x="$(command -v y)"` forks, whereas just `command -v y` does not.
|
local bin="$2"
|
||||||
if command -v "$2" > /dev/null; then
|
local loc="$3"
|
||||||
declare -g "$1"="$2"
|
# N.B.: `bin=$(command -v $bin)` would make more sense, but it forks.
|
||||||
else
|
for dir in ${PATH//:/ }; do
|
||||||
declare -g "$1"="$3"
|
if [ -e "$dir/$bin" ]; then
|
||||||
|
loc="$dir/$bin"
|
||||||
|
break
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
declare -g "$outVar"="$loc"
|
||||||
}
|
}
|
||||||
|
|
||||||
# `urldecode outVar <uri>`
|
# `urldecode outVar <uri>`
|
||||||
|
@ -680,6 +685,7 @@ bwrapGetCli() {
|
||||||
# --unshare-uts
|
# --unshare-uts
|
||||||
# --unshare-user (implicit to every non-suid call to bwrap)
|
# --unshare-user (implicit to every non-suid call to bwrap)
|
||||||
locate _bwrap "bwrap" "$BWRAP_FALLBACK"
|
locate _bwrap "bwrap" "$BWRAP_FALLBACK"
|
||||||
|
locate _env "env" "$ENV_FALLBACK"
|
||||||
if [ -n "$bwrapUsePasta" ]; then
|
if [ -n "$bwrapUsePasta" ]; then
|
||||||
# pasta drops us into an environment where we're root, but some apps complain if run as root.
|
# pasta drops us into an environment where we're root, but some apps complain if run as root.
|
||||||
# TODO: this really belongs on the `pastaonlyGetCli` side.
|
# TODO: this really belongs on the `pastaonlyGetCli` side.
|
||||||
|
@ -697,7 +703,7 @@ bwrapGetCli() {
|
||||||
"${bwrapUnshareUts[@]}"
|
"${bwrapUnshareUts[@]}"
|
||||||
"${bwrapVirtualizeDev[@]}" "${bwrapVirtualizeProc[@]}" "${bwrapVirtualizeTmp[@]}"
|
"${bwrapVirtualizeDev[@]}" "${bwrapVirtualizeProc[@]}" "${bwrapVirtualizeTmp[@]}"
|
||||||
"${bwrapFlags[@]}" --
|
"${bwrapFlags[@]}" --
|
||||||
env "${portalEnv[@]}" "${cliArgs[@]}"
|
"$_env" "${portalEnv[@]}" "${cliArgs[@]}"
|
||||||
)
|
)
|
||||||
if [ -n "$bwrapUsePasta" ]; then
|
if [ -n "$bwrapUsePasta" ]; then
|
||||||
pastaonlyGetCli
|
pastaonlyGetCli
|
||||||
|
@ -769,9 +775,10 @@ landlockGetCli() {
|
||||||
# invoke the actual user command.
|
# invoke the actual user command.
|
||||||
locate _sandboxer "sandboxer" "$LANDLOCK_SANDBOXER_FALLBACK"
|
locate _sandboxer "sandboxer" "$LANDLOCK_SANDBOXER_FALLBACK"
|
||||||
locate _capsh "capsh" "$CAPSH_FALLBACK"
|
locate _capsh "capsh" "$CAPSH_FALLBACK"
|
||||||
cliArgs=(env LL_FS_RO= LL_FS_RW="$landlockPaths"
|
locate _env "env" "$ENV_FALLBACK"
|
||||||
|
cliArgs=("$_env" LL_FS_RO= LL_FS_RW="$landlockPaths"
|
||||||
"$_sandboxer"
|
"$_sandboxer"
|
||||||
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="/usr/bin/env" -- "${portalEnv[@]}" "${cliArgs[@]}"
|
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="$_env" -- "${portalEnv[@]}" "${cliArgs[@]}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,8 +830,9 @@ capshonlyIngestCapability() {
|
||||||
|
|
||||||
capshonlyGetCli() {
|
capshonlyGetCli() {
|
||||||
locate _capsh "capsh" "$CAPSH_FALLBACK"
|
locate _capsh "capsh" "$CAPSH_FALLBACK"
|
||||||
|
locate _env "env" "$ENV_FALLBACK"
|
||||||
cliArgs=(
|
cliArgs=(
|
||||||
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="/usr/bin/env" -- "${portalEnv[@]}" "${cliArgs[@]}"
|
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="$_env" -- "${portalEnv[@]}" "${cliArgs[@]}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,6 +919,12 @@ noneGetCli() {
|
||||||
## ARGUMENT POST-PROCESSING
|
## ARGUMENT POST-PROCESSING
|
||||||
|
|
||||||
loadLinkCache() {
|
loadLinkCache() {
|
||||||
|
if ! [ -e /etc/sanebox/symlink-cache ]; then
|
||||||
|
# don't error if the link cache is inaccessible.
|
||||||
|
# this can happen during nix builds e.g.
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
# readarray -t: reads some file into an array; each line becomes one element
|
# readarray -t: reads some file into an array; each line becomes one element
|
||||||
readarray -t _linkCacheArray < /etc/sanebox/symlink-cache
|
readarray -t _linkCacheArray < /etc/sanebox/symlink-cache
|
||||||
for link in "${_linkCacheArray[@]}"; do
|
for link in "${_linkCacheArray[@]}"; do
|
||||||
|
|
Loading…
Reference in New Issue
Block a user