nix-files/modules/programs/sane-sandboxed

204 lines
4.4 KiB
Plaintext

#!@runtimeShell@
test -n "$SANE_SANDBOX_DEBUG" && set -x
cliArgs=()
name=
firejailProfile=
rootPaths=()
homePaths=()
net=
dns=()
method=
firejailFlags=()
bwrapFlags=()
debug() {
[ -n "$SANE_SANDBOX_DEBUG" ] && printf "[debug] %s" "$1" >&2
}
loadProfileByPath() {
_profArgs="$(cat $1)"
parseArgs $_profArgs
}
tryLoadProfileByName() {
if [ -z "$name" ]; then
name="$1"
fi
_profileDirs=(@profileDirs@)
for _profileDir in "${_profileDirs[@]}"; do
_profile="$_profileDir/$1.profile"
debug "try profile at path: '$_profile'"
if [ -f "$_profile" ]; then
loadProfileByPath "$_profile"
break
fi
done
if [ -z "$firejailProfile" ]; then
_fjProfileDirs=(@firejailProfileDirs@)
for _fjProfileDir in "${_fjProfileDirs[@]}"; do
_fjProfile="$_fjProfileDir/$1.profile"
debug "try firejail profile at path: '$_fjProfile'"
if [ -f "$_fjProfile" ]; then
firejailProfile="$_fjProfile"
fi
done
fi
}
## parse CLI args into the variables declared above
## args not intended for this helper are put into $parseArgsExtra
parseArgs() {
parseArgsExtra=()
while [ "$#" -ne 0 ]; do
_arg="$1"
shift
case "$_arg" in
(--)
# rest of args are for the CLI
parseArgsExtra+=$@
break
;;
(--sane-sandbox-debug)
SANE_SANDBOX_DEBUG=1
set -x
;;
(--sane-sandbox-replace-cli)
# keep the sandbox flags, but clear any earlier CLI args.
# this lets the user do things like `mpv --sane-sandbox-replace-cli sh` to enter a shell
# with the sandbox that `mpv` would see.
parseArgsExtra=()
;;
(--sane-sandbox-disable)
SANE_SANDBOX_DISABLE=1
;;
(--sane-sandbox-method)
method="$1"
shift
;;
(--sane-sandbox-dns)
# N.B.: these named temporary variables ensure that `set -x` causes $1 to be printed
_dns="$1"
dns+=("$_dns")
shift
;;
(--sane-sandbox-firejail-arg)
_fjFlag="$1"
firejailFlags+=("$_fjFlag")
shift
;;
(--sane-sandbox-bwrap-arg)
_bwrapFlag="$1"
bwrapFlags+=("$_bwrapFlag")
shift
;;
(--sane-sandbox-net)
net="$1"
shift
;;
(--sane-sandbox-home-path)
_path="$1"
homePaths+=("$_path")
shift
;;
(--sane-sandbox-path)
_path="$1"
rootPaths+=("$_path")
shift
;;
(--sane-sandbox-profile)
tryLoadProfileByName "$1"
shift
;;
(*)
parseArgsExtra+=("$_arg")
;;
esac
done
}
## FIREJAIL BACKEND
firejailIngestRootPath() {
firejailFlags+=("--noblacklist=$1" "--whitelist=$1")
}
firejailIngestHomePath() {
firejailFlags+=("--noblacklist="'${HOME}/'"$1" "--whitelist="'${HOME}/'"$1")
}
firejailIngestNet() {
firejailFlags+=("--net=$1")
}
firejailIngestDns() {
firejailFlags+=("--dns=$1")
}
firejailIngestName() {
firejailFlags+=("--join-or-start=$1")
}
firejailExec() {
if [ -n "$firejailProfile" ]; then
firejailFlags+=("--profile=$firejailProfile")
fi
PATH="$PATH:@firejail@/bin" exec firejail "${firejailFlags[@]}" -- "${cliArgs[@]}"
}
## BUBBLEWRAP BACKEND
bwrapIngestRootPath() {
# N.B.: use --dev-bind-try instead of --dev-bind for platform-specific paths like /run/opengl-driver-32
# which don't exist on aarch64, as the -try variant will gracefully fail (i.e. not bind it).
bwrapFlags+=("--dev-bind-try" "$1" "$1")
}
bwrapIngestHomePath() {
bwrapFlags+=("--dev-bind" "$HOME/$1" "$HOME/$1")
}
bwrapIngestName() {
echo "bwrap naming/labeling not yet implemented"
}
# WIP
bwrapExec() {
PATH="$PATH:@bubblewrap@/bin" exec bwrap --dev /dev --proc /proc "${bwrapFlags[@]}" -- "${cliArgs[@]}"
}
## BACKEND HANDOFF
parseArgs "$@"
cliArgs+=("${parseArgsExtra[@]}")
test -n "$SANE_SANDBOX_DISABLE" && exec "${cliArgs[@]}"
### convert generic args into sandbox-specific args
# order matters: for firejail, early args override the later --profile args
for _path in "${rootPaths[@]}"; do
"$method"IngestRootPath "$_path"
done
for _path in "${homePaths[@]}"; do
"$method"IngestHomePath "$_path"
done
if [ -n "$net" ]; then
"$method"IngestNet "$net"
fi
for _addr in "${dns[@]}"; do
"$method"IngestDns "$_addr"
done
if [ -n "$name" ]; then
"$method"IngestName "$name"
fi
"$method"Exec
echo "sandbox glue failed for method='$method'"
exit 1