627 lines
19 KiB
Plaintext
627 lines
19 KiB
Plaintext
#!@runtimeShell@
|
|
|
|
profileDirs=()
|
|
isDebug=
|
|
isDisable=
|
|
|
|
cliArgs=()
|
|
cliPathArgs=()
|
|
autodetect=
|
|
profilesNamed=()
|
|
paths=()
|
|
capabilities=()
|
|
net=
|
|
keepPidspace=
|
|
dns=()
|
|
method=
|
|
extraEnv=()
|
|
|
|
# backend-specific state:
|
|
firejailFlags=()
|
|
bwrapUnshareNet=(--unshare-net)
|
|
bwrapUnsharePid=(--unshare-pid)
|
|
bwrapFlags=()
|
|
landlockPaths=
|
|
capshCapsArg=
|
|
|
|
enableDebug() {
|
|
isDebug=1
|
|
set -x
|
|
}
|
|
|
|
debug() {
|
|
[ -n "$isDebug" ] && printf "[debug] %s" "$1" >&2
|
|
}
|
|
|
|
# `locate <bin-name> </path/to/default>` => print the full path to `<bin-name>` if it's on PATH, else print `</path/to/default>`
|
|
locate() {
|
|
command -v "$1" || echo "$2"
|
|
}
|
|
|
|
loadProfileByPath() {
|
|
# profile format is simply a list of arguments one would pass to this sane-sandboxed script itself,
|
|
# with one argument per line
|
|
readarray -t _profArgs < <(cat "$1")
|
|
parseArgs "${_profArgs[@]}"
|
|
}
|
|
|
|
tryLoadProfileByName() {
|
|
_profile="$1"
|
|
if [ "${_profile:0:1}" = "/" ]; then
|
|
# absolute path to profile.
|
|
# consider it an error if it doesn't exist.
|
|
# in general, prefer to use `--sane-sandbox-profile-dir` and specify the profile by name.
|
|
# doing so maximizes compatibility with anything else that uses the name, like firejail.
|
|
loadProfileByPath "$_profile"
|
|
else
|
|
profilesNamed+=("$_profile")
|
|
|
|
for _profileDir in "${profileDirs[@]}"; do
|
|
_profilePath="$_profileDir/$_profile.profile"
|
|
debug "try profile at path: '$_profilePath'"
|
|
if [ -f "$_profilePath" ]; then
|
|
loadProfileByPath "$_profilePath"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
initDefaultProfileDirs() {
|
|
for d in ${XDG_DATA_DIRS//:/ }; do
|
|
profileDirs+=("$d/sane-sandboxed/profiles")
|
|
done
|
|
}
|
|
|
|
# convert e.g. `file:///Local%20Users/foo.mp3` to `file:///Local Users/foo.mp3`
|
|
urldecode() {
|
|
# source: <https://stackoverflow.com/q/6250698>
|
|
: "${*//+/ }"
|
|
echo -e "${_//%/\\x}"
|
|
}
|
|
|
|
# return the path to this file or directory's parent, even if the input doesn't exist.
|
|
parent() {
|
|
realpath --logical --no-symlinks --canonicalize-missing "$1/.."
|
|
}
|
|
|
|
# subroutine of `tryArgAsPath` for after the arg has been converted into a valid (but possibly not existing) path.
|
|
# adds an entry to `cliPathArgs` and evals `true` on success;
|
|
# evals `false` if the path couldn't be added, for any reason.
|
|
tryPath() {
|
|
_path="$1"
|
|
_how="$2"
|
|
|
|
if [ "$_how" = "existing" ]; then
|
|
if [ -e "$_path" ]; then
|
|
cliPathArgs+=("$_path")
|
|
true
|
|
fi
|
|
false
|
|
elif [ "$_how" = "parent" ]; then
|
|
# the caller wants access to the entire directory containing this directory regardless of the file's existence.
|
|
tryPath "$(parent "$_path")" "existing"
|
|
elif [ "$_how" = "existingFileOrParent" ]; then
|
|
# the caller wants access to the file, or write access to the directory so it may create the file if it doesn't exist.
|
|
tryPath "$_path" "existing" || tryPath "$_path" "parent"
|
|
fi
|
|
}
|
|
|
|
# if the argument looks path-like, then add it to cliPathArgs.
|
|
# this function ingests absolute, relative, or file:///-type URIs.
|
|
# but it converts any such path into an absolute path before adding it to cliPathArgs.
|
|
tryArgAsPath() {
|
|
_arg="$1"
|
|
_how="$2"
|
|
_path=
|
|
if [ "${_arg:0:1}" = "/" ]; then
|
|
# absolute path
|
|
_path="$_arg"
|
|
elif [ "${_arg:0:8}" = "file:///" ]; then
|
|
# URI to an absolute path which is presumably on this vfs
|
|
# commonly found when xdg-open/mimeo passes a path on to an application
|
|
# if URIs to relative paths exist, this implementation doesn't support them
|
|
_path="/$(urldecode "${_arg:8}")"
|
|
elif [ "${_path:0:1}" = "-" ]; then
|
|
# 99% chance it's a CLI argument. if not, use `./-<...>`
|
|
return
|
|
else
|
|
# assume relative path
|
|
_path="$(pwd)/$_arg"
|
|
fi
|
|
|
|
tryPath "$_path" "$_how"
|
|
}
|
|
|
|
# remove duplicate //, reduce '.' and '..' (naively).
|
|
# chomps trailing slashes.
|
|
# does not resolve symlinks, nor check for existence of any component of the path.
|
|
normPath() {
|
|
realpath --logical --no-symlinks --canonicalize-missing "$1"
|
|
}
|
|
|
|
ensureTrailingSlash() {
|
|
if [ "${1:-1}" = "/" ]; then
|
|
printf "%s" "$1"
|
|
else
|
|
printf "%s/" "$1"
|
|
fi
|
|
}
|
|
|
|
## parse CLI args into the variables declared above
|
|
## args not intended for this helper are put into $parseArgsExtra
|
|
parseArgsExtra=()
|
|
parseArgs() {
|
|
while [ "$#" -ne 0 ]; do
|
|
_arg="$1"
|
|
shift
|
|
case "$_arg" in
|
|
(--)
|
|
# rest of args are for the CLI, and not for us.
|
|
# consider two cases:
|
|
# - sane-sandboxed --sane-sandbox-flag1 -- /nix/store/.../mpv --arg0 arg1
|
|
# - sane-sandboxed /nix/store/.../mpv --arg0 -- arg1
|
|
# in the first case, we swallow the -- and treat the rest as CLI args.
|
|
# in the second case, the -- is *probably* intended for the application.
|
|
# but it could be meant for us. do the most conservative thing here
|
|
# and stop our own parsing, and also forward the -- to the wrapped binary.
|
|
#
|
|
# this mode of argument parsing is clearly ambiguous, it's probably worth reducing our own API in the future
|
|
if [ -n "$parseArgsExtra" ]; then
|
|
parseArgsExtra+=("--")
|
|
fi
|
|
parseArgsExtra+=("$@")
|
|
break
|
|
;;
|
|
(--sane-sandbox-debug)
|
|
enableDebug
|
|
;;
|
|
(--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)
|
|
isDisable=1
|
|
;;
|
|
(--sane-sandbox-method)
|
|
method="$1"
|
|
shift
|
|
;;
|
|
(--sane-sandbox-autodetect)
|
|
# autodetect: crawl the CLI program's args & bind any which look like paths into the sandbox.
|
|
# this is handy for e.g. media players or document viewers.
|
|
# it's best combined with some two-tiered thing.
|
|
# e.g. first drop to the broadest path set of interest (Music,Videos,tmp, ...), then drop via autodetect.
|
|
autodetect="$1"
|
|
shift
|
|
;;
|
|
(--sane-sandbox-cap)
|
|
_cap="$1"
|
|
shift
|
|
capabilities+=("$_cap")
|
|
;;
|
|
(--sane-sandbox-portal)
|
|
# instruct glib/gtk apps to perform actions such as opening external files via dbus calls to org.freedesktop.portal.*.
|
|
# note that GIO_USE_PORTALS primarily acts as a *fallback*: apps only open files via the portal if they don't know how to themelves.
|
|
# this switch is typically accompanied by removing all MIME associations from the app's view, then.
|
|
# GTK_USE_PORTALS is the old name, beginning to be phased out as of 2023-10-02
|
|
extraEnv+=("GIO_USE_PORTALS=1" "GTK_USE_PORTAL=1" "NIXOS_XDG_OPEN_USE_PORTAL=1")
|
|
;;
|
|
(--sane-sandbox-dns)
|
|
# N.B.: these named temporary variables ensure that "set -x" causes $1 to be printed
|
|
_dns="$1"
|
|
shift
|
|
dns+=("$_dns")
|
|
;;
|
|
(--sane-sandbox-firejail-arg)
|
|
_fjFlag="$1"
|
|
shift
|
|
firejailFlags+=("$_fjFlag")
|
|
;;
|
|
(--sane-sandbox-bwrap-arg)
|
|
_bwrapFlag="$1"
|
|
shift
|
|
bwrapFlags+=("$_bwrapFlag")
|
|
;;
|
|
(--sane-sandbox-net)
|
|
net="$1"
|
|
shift
|
|
;;
|
|
(--sane-sandbox-keep-pidspace)
|
|
keepPidspace=1
|
|
;;
|
|
(--sane-sandbox-path)
|
|
_path="$1"
|
|
shift
|
|
paths+=("$_path")
|
|
;;
|
|
(--sane-sandbox-add-pwd)
|
|
_path="$(pwd)"
|
|
paths+=("$_path")
|
|
;;
|
|
(--sane-sandbox-profile)
|
|
# load the profile *immediately*, inline.
|
|
# this way, user arguments which come later on the CLI can override any profile config, v.s. if profile loading were defered.
|
|
tryLoadProfileByName "$1"
|
|
shift
|
|
;;
|
|
(--sane-sandbox-profile-dir)
|
|
# add another directory in which to search for profiles,
|
|
# and give it *greater* precedence than the existing search directories (i.e. override the default profile)
|
|
_dir="$1"
|
|
shift
|
|
profileDirs=("$_dir" "${profileDirs[@]}")
|
|
;;
|
|
(*)
|
|
parseArgsExtra+=("$_arg")
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
|
|
## FIREJAIL BACKEND
|
|
|
|
firejailName=
|
|
firejailProfile=
|
|
|
|
firejailSetup() {
|
|
debug "firejailSetup: noop"
|
|
}
|
|
firejailIngestPath() {
|
|
# XXX: firejail flat-out refuses to whitelist certain root paths
|
|
# this exception list is non-exhaustive
|
|
[ "$1" != "/bin" ] && [ "$1" != "/etc" ] && firejailFlags+=("--noblacklist=$1" "--whitelist=$1")
|
|
}
|
|
firejailIngestNet() {
|
|
firejailFlags+=("--net=$1")
|
|
}
|
|
firejailIngestDns() {
|
|
firejailFlags+=("--dns=$1")
|
|
}
|
|
firejailIngestKeepPidspace() {
|
|
debug "firejailIngestKeepPidspace: noop"
|
|
}
|
|
firejailIngestProfile() {
|
|
if [ -z "$firejailName" ]; then
|
|
firejailName="$1"
|
|
fi
|
|
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
|
|
}
|
|
|
|
firejailExec() {
|
|
if [ -n "$firejailName" ]; then
|
|
firejailFlags+=("--join-or-start=$firejailName")
|
|
fi
|
|
if [ -n "$firejailProfile" ]; then
|
|
firejailFlags+=("--profile=$firejailProfile")
|
|
fi
|
|
_firejail="$(locate firejail @firejail@/bin/firejail)"
|
|
exec \
|
|
"$_firejail" "${firejailFlags[@]}" -- \
|
|
env "${extraEnv[@]}" "${cliArgs[@]}"
|
|
}
|
|
|
|
|
|
## BUBBLEWRAP BACKEND
|
|
|
|
bwrapSetup() {
|
|
debug "bwrapSetup: noop"
|
|
}
|
|
bwrapIngestPath() {
|
|
# 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).
|
|
# N.B.: `test -r` for paths like /mnt/servo/media, which may otherwise break bwrap when offline with
|
|
# "bwrap: Can't get type of source /mnt/...: Input/output error"
|
|
# HOWEVER, paths such as `/run/secrets` are not readable, so don't do that (or, try `test -e` if this becomes a problem again).
|
|
# `-try` version of binding is still desireable for user files.
|
|
# although it'd be nice if all program directories could be required to exist, some things are scoped poorly.
|
|
# e.g. ~/.local/share/historic.json for wike's history. i don't want to give it all of ~/.local/share, and i don't want it to fail if its history file doesn't exist.
|
|
# test -r "$1" && bwrapFlags+=("--dev-bind-try" "$1" "$1")
|
|
bwrapFlags+=("--dev-bind-try" "$1" "$1")
|
|
}
|
|
bwrapIngestNet() {
|
|
debug "bwrapIngestNet: enabling full net access for '$1' because don't know how to restrict it more narrowly"
|
|
bwrapUnshareNet=()
|
|
}
|
|
bwrapIngestKeepPidspace() {
|
|
bwrapUnsharePid=()
|
|
}
|
|
bwrapIngestProfile() {
|
|
debug "bwrapIngestProfile: stubbed"
|
|
}
|
|
bwrapIngestCapability() {
|
|
bwrapFlags+=("--cap-add" "cap_$1")
|
|
}
|
|
# WIP
|
|
|
|
bwrapExec() {
|
|
# --unshare-all implies the following:
|
|
# --unshare-pid: mean that the /proc mount does not expose /proc/$PID/ for every other process on the machine.
|
|
# --unshare-net creates a new net namespace with only the loopback interface.
|
|
# if `bwrapFlags` contains --share-net, thiss is canceled and the program sees an unsandboxed network.
|
|
# --unshare-ipc
|
|
# --unshare-cgroup
|
|
# --unshare-uts
|
|
# --unshare-user (implicit to every non-suid call to bwrap)
|
|
_bwrap="$(locate bwrap @bubblewrap@/bin/bwrap)"
|
|
exec \
|
|
"$_bwrap" --unshare-cgroup --unshare-ipc --unshare-user --unshare-uts "${bwrapUnshareNet[@]}" "${bwrapUnsharePid[@]}" --dev /dev --proc /proc --tmpfs /tmp "${bwrapFlags[@]}" -- \
|
|
env "${extraEnv[@]}" "${cliArgs[@]}"
|
|
}
|
|
|
|
|
|
## LANDLOCK BACKEND
|
|
landlockSetup() {
|
|
# other sandboxing methods would create fake /dev, /proc, /tmp filesystems
|
|
# but landlock can't do that. so bind a minimal number of assumed-to-exist files.
|
|
# note that most applications actually do start without these, but maybe produce weird errors during their lifetime.
|
|
# typical failure mode:
|
|
# - /tmp: application can't perform its task
|
|
# - /dev/{null,random,urandom,zero}: application warns but works around it
|
|
paths+=(\
|
|
/dev/null
|
|
/dev/random
|
|
/dev/urandom
|
|
/dev/zero
|
|
/tmp
|
|
)
|
|
# /dev/{stderr,stdin,stdout} are links to /proc/self/fd/N
|
|
# and /proc/self is a link to /proc/<N>.
|
|
# there seems to be an issue, observed with wireshark, in binding these.
|
|
# maybe i bound the symlinks but not the actual data being pointed to.
|
|
# if you want to bind /dev/std*, then also bind all of /proc.
|
|
# /proc/self
|
|
# "/proc/$$"
|
|
# /dev/stderr
|
|
# /dev/stdin
|
|
# /dev/stdout
|
|
}
|
|
landlockIngestPath() {
|
|
# TODO: escape colons
|
|
if [ -e "$1" ]; then
|
|
# landlock is fd-based and requires `open`ing the path;
|
|
# sandboxer will error if that part fails.
|
|
if [ -z "$landlockPaths" ]; then
|
|
# avoid leading :, which would otherwise cause a "no such file" error.
|
|
landlockPaths="$1"
|
|
else
|
|
landlockPaths="$landlockPaths:$1"
|
|
fi
|
|
fi
|
|
}
|
|
landlockIngestNet() {
|
|
debug "landlockIngestNet: '$1': stubbed (landlock network is always unrestricted)"
|
|
}
|
|
landlockIngestKeepPidspace() {
|
|
debug "landlockIngestKeepPidspace: noop"
|
|
}
|
|
landlockIngestProfile() {
|
|
debug "landlockIngestProfile: stubbed"
|
|
}
|
|
landlockIngestCapability() {
|
|
capshonlyIngestCapability "$1"
|
|
}
|
|
landlockExec() {
|
|
# landlock sandboxer has no native support for capabilities (except that it sets nonewprivs),
|
|
# so trampoline through `capsh` as well, to drop privs.
|
|
# N.B: capsh passes its arg to bash (via /nix/store/.../bash), which means you have to `-c "my command"` to
|
|
# invoke the actual user command.
|
|
_sandboxer="$(locate sandboxer @landlockSandboxer@/bin/sandboxer)"
|
|
_capsh="$(locate capsh @libcap@/bin/capsh)"
|
|
LL_FS_RO= LL_FS_RW="$landlockPaths" exec \
|
|
"$_sandboxer" \
|
|
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="/usr/bin/env" -- "${extraEnv[@]}" "${cliArgs[@]}"
|
|
}
|
|
|
|
|
|
## CAPSH-ONLY BACKEND
|
|
# this backend exists because apps which are natively bwrap may complain about having ambient privileges.
|
|
# then, run them in a capsh sandbox, which ignores any path sandboxing and just lowers privs to what's needed.
|
|
|
|
capshonlySetup() {
|
|
debug "capshonlySetup: noop"
|
|
}
|
|
capshonlyIngestPath() {
|
|
debug "capshonlyIngestPath: stubbed"
|
|
}
|
|
capshonlyIngestNet() {
|
|
debug "capshonlyIngestNet: '$1': stubbed (capsh network is always unrestricted)"
|
|
}
|
|
capshonlyIngestKeepPidspace() {
|
|
debug "capshonlyIngestKeepPidspace: noop"
|
|
}
|
|
capshonlyIngestProfile() {
|
|
debug "capshonlyIngestProfile: stubbed"
|
|
}
|
|
capshonlyIngestCapability() {
|
|
# N.B. `capsh` parsing of `--caps=X` arg is idiosyncratic:
|
|
# - valid: `capsh --caps=CAP_FOO,CAP_BAR=eip -- <cmd>`
|
|
# - valid: `capsh --caps= -- <cmd>`
|
|
# - invalid: `capsh --caps=CAP_FOO,CAP_BAR -- <cmd>`
|
|
# - invalid: `capsh --caps==eip -- <cmd>`
|
|
if [ -z "$capshCapsArg" ]; then
|
|
capshCapsArg="cap_$1=eip"
|
|
else
|
|
capshCapsArg="cap_$1,$capshCapsArg"
|
|
fi
|
|
}
|
|
|
|
capshonlyExec() {
|
|
_capsh="$(locate capsh @libcap@/bin/capsh)"
|
|
exec \
|
|
"$_capsh" "--caps=$capshCapsArg" --no-new-privs --shell="/usr/bin/env" -- "${extraEnv[@]}" "${cliArgs[@]}"
|
|
}
|
|
|
|
|
|
## NONE BACKEND
|
|
# this backend exists only to allow benchmarking
|
|
noneSetup() {
|
|
:
|
|
}
|
|
noneIngestPath() {
|
|
:
|
|
}
|
|
noneIngestNet() {
|
|
:
|
|
}
|
|
noneIngestKeepPidspace() {
|
|
:
|
|
}
|
|
noneIngestProfile() {
|
|
:
|
|
}
|
|
noneIngestCapability() {
|
|
:
|
|
}
|
|
noneExec() {
|
|
exec "${cliArgs[@]}"
|
|
}
|
|
|
|
|
|
## ARGUMENT POST-PROCESSING
|
|
|
|
### autodetect: if one of the CLI args looks like a path, that could be an input or output file
|
|
# so allow access to it.
|
|
maybeAutodetectPaths() {
|
|
if [ -n "$autodetect" ]; then
|
|
for _arg in "${cliArgs[@]:1}"; do
|
|
tryArgAsPath "$_arg" "$autodetect"
|
|
done
|
|
for _path in "${cliPathArgs[@]}"; do
|
|
# TODO: might want to also mount the directory *above* this file,
|
|
# to access e.g. adjacent album art in the media's folder.
|
|
paths+=("$_path")
|
|
done
|
|
fi
|
|
}
|
|
|
|
### path sorting: if the app has access both to /FOO and /FOO/BAR, some backends get confused.
|
|
# notably bwrap, --bind /FOO /FOO followed by --bind /FOO/BAR /FOO/BAR results in /FOO being accessible but /FOO/BAR *not*.
|
|
# so reduce the paths to the minimal set which includes those requested.
|
|
# for more sophisticated (i.e. complex) backends like firejail, this may break subpaths which were blacklisted earlier.
|
|
canonicalizePaths() {
|
|
# remove '//' and simplify '.', '..' paths, into canonical absolute logical paths.
|
|
_normPaths=()
|
|
for _path in "${paths[@]}"; do
|
|
_normPaths+=("$(normPath "$_path")")
|
|
done
|
|
|
|
# remove subpaths, but the result might include duplicates.
|
|
_toplevelPaths=()
|
|
for _path in "${_normPaths[@]}"; do
|
|
_isSubpath=
|
|
for _other in "${_normPaths[@]}"; do
|
|
if [[ "$_path" =~ ^$_other/.* ]]; then
|
|
# N.B.: $_path lacks a trailing slash, so this never matches self.
|
|
_isSubpath=1
|
|
fi
|
|
done
|
|
if [ -z "$_isSubpath" ]; then
|
|
_toplevelPaths+=("$_path")
|
|
fi
|
|
done
|
|
|
|
# remove duplicated paths.
|
|
canonicalizedPaths=()
|
|
for _path in "${_toplevelPaths[@]}"; do
|
|
_isAlreadyListed=
|
|
for _other in "${canonicalizedPaths[@]}"; do
|
|
if [ "$_path" = "$_other" ]; then
|
|
_isAlreadyListed=1
|
|
fi
|
|
done
|
|
if [ -z "$_isAlreadyListed" ]; then
|
|
canonicalizedPaths+=("$_path")
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
## TOPLEVEL ADAPTERS
|
|
# - convert CLI args/env into internal structures
|
|
# - convert internal structures into backend-specific structures
|
|
|
|
### parse arguments, with consideration of any which may be injected via the environment
|
|
parseArgsAndEnvironment() {
|
|
if [ -n "$SANE_SANDBOX_DEBUG" ]; then
|
|
enableDebug
|
|
fi
|
|
if [ -n "$SANE_SANDBOX_DISABLE" ]; then
|
|
isDisable=1
|
|
fi
|
|
|
|
test -n "$SANE_SANDBOX_PREPEND" && parseArgs $SANE_SANDBOX_PREPEND
|
|
parseArgs "$@"
|
|
cliArgs+=("${parseArgsExtra[@]}")
|
|
test -n "$SANE_SANDBOX_APPEND" && parseArgs $SANE_SANDBOX_APPEND
|
|
}
|
|
|
|
### convert generic args into sandbox-specific args
|
|
# order matters: for firejail, early args override the later --profile args
|
|
ingestForBackend() {
|
|
for _path in "${canonicalizedPaths[@]}"; do
|
|
"$method"IngestPath "$_path"
|
|
done
|
|
|
|
for _cap in "${capabilities[@]}"; do
|
|
"$method"IngestCapability "$_cap"
|
|
done
|
|
|
|
if [ -n "$net" ]; then
|
|
"$method"IngestNet "$net"
|
|
fi
|
|
|
|
for _addr in "${dns[@]}"; do
|
|
"$method"IngestDns "$_addr"
|
|
done
|
|
|
|
if [ -n "$keepPidspace" ]; then
|
|
"$method"IngestKeepPidspace
|
|
fi
|
|
|
|
for _prof in "${profilesNamed[@]}"; do
|
|
"$method"IngestProfile "$_prof"
|
|
done
|
|
}
|
|
|
|
|
|
## TOPLEVEL EXECUTION
|
|
# no code evaluated before this point should be dependent on user args / environment.
|
|
|
|
initDefaultProfileDirs
|
|
parseArgsAndEnvironment "$@"
|
|
|
|
# variables meant to be inherited
|
|
# N.B.: SANE_SANDBOX_DEBUG FREQUENTLY BREAKS APPLICATIONS WHICH PARSE STDOUT
|
|
# example is wireshark parsing stdout of dumpcap;
|
|
# in such a case invoke the app with --sane-sandbox-debug instead of the env var.
|
|
export SANE_SANDBOX_DEBUG="$SANE_SANDBOX_DEBUG"
|
|
export SANE_SANDBOX_DISABLE="$SANE_SANDBOX_DISABLE"
|
|
export SANE_SANDBOX_PREPEND="$SANE_SANDBOX_PREPEND"
|
|
export SANE_SANDBOX_APPEND="$SANE_SANDBOX_APPEND"
|
|
|
|
test -n "$isDisable" && exec "${cliArgs[@]}"
|
|
|
|
# method-specific setup could add additional paths that need binding, so do that before canonicalization
|
|
"$method"Setup
|
|
maybeAutodetectPaths
|
|
canonicalizePaths
|
|
|
|
ingestForBackend
|
|
"$method"Exec
|
|
|
|
echo "sandbox glue failed for method='$method'"
|
|
exit 1
|