sane-sandboxed: use local
where applicable
This commit is contained in:
parent
016df3ff74
commit
980fe6b33c
|
@ -154,39 +154,39 @@ relativeTo() {
|
|||
# chomps trailing slashes.
|
||||
# does not resolve symlinks, nor check for existence of any component of the path.
|
||||
normPath() {
|
||||
_npOut="$1"
|
||||
_npUnparsed="$2"
|
||||
_npComps=()
|
||||
while [ -n "$_npUnparsed" ]; do
|
||||
local npOut="$1"
|
||||
local npUnparsed="$2"
|
||||
local npComps=()
|
||||
while [ -n "$npUnparsed" ]; do
|
||||
# chomp leading `/`
|
||||
_npUnparsed="${_npUnparsed:1}"
|
||||
npUnparsed="${npUnparsed:1}"
|
||||
# split into <first></re/st/...>
|
||||
# in the case of `//`, or more, _npThisComp is empty,
|
||||
# and we push nothing to _npComps,
|
||||
# in the case of `//`, or more, npThisComp is empty,
|
||||
# and we push nothing to npComps,
|
||||
# but we're guaranteed to make progress.
|
||||
_npThisComp="${_npUnparsed%%/*}"
|
||||
_npThisLen="${#_npThisComp}"
|
||||
_npUnparsed="${_npUnparsed:$_npThisLen}"
|
||||
if [ "$_npThisComp" = ".." ]; then
|
||||
npThisComp="${npUnparsed%%/*}"
|
||||
npThisLen="${#npThisComp}"
|
||||
npUnparsed="${npUnparsed:$npThisLen}"
|
||||
if [ "$npThisComp" = ".." ]; then
|
||||
# "go up" path component => delete the leaf dir (if any)
|
||||
if [ ${#_npComps[@]} -ne 0 ]; then
|
||||
unset _npComps[-1]
|
||||
if [ ${#npComps[@]} -ne 0 ]; then
|
||||
unset npComps[-1]
|
||||
fi
|
||||
elif [ "$_npThisComp" != "." ] && [ -n "$_npThisComp" ]; then
|
||||
elif [ "$npThisComp" != "." ] && [ -n "$npThisComp" ]; then
|
||||
# normal, non-empty path component => append it
|
||||
_npComps+=("$_npThisComp")
|
||||
npComps+=("$npThisComp")
|
||||
fi
|
||||
done
|
||||
|
||||
# join the components
|
||||
if [ ${#_npComps[@]} -eq 0 ]; then
|
||||
declare -g "$_npOut"="/"
|
||||
if [ ${#npComps[@]} -eq 0 ]; then
|
||||
declare -g "$npOut"="/"
|
||||
else
|
||||
_npJoined=
|
||||
for _npComp in "${_npComps[@]}"; do
|
||||
_npJoined="$_npJoined/$_npComp"
|
||||
local npJoined=
|
||||
for npComp in "${npComps[@]}"; do
|
||||
npJoined="$npJoined/$npComp"
|
||||
done
|
||||
declare -g "$_npOut"="$_npJoined"
|
||||
declare -g "$npOut"="$npJoined"
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -263,21 +263,21 @@ loadProfileByPath() {
|
|||
}
|
||||
|
||||
tryLoadProfileByName() {
|
||||
_profile="$1"
|
||||
if [ "${_profile:0:1}" = "/" ]; then
|
||||
local 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"
|
||||
loadProfileByPath "$profile"
|
||||
else
|
||||
profilesNamed+=("$_profile")
|
||||
profilesNamed+=("$profile")
|
||||
|
||||
for _profileDir in "${profileDirs[@]}"; do
|
||||
_profilePath="$_profileDir/$_profile.profile"
|
||||
debug "try profile at path: '$_profilePath'"
|
||||
if [ -f "$_profilePath" ]; then
|
||||
loadProfileByPath "$_profilePath"
|
||||
for profileDir in "${profileDirs[@]}"; do
|
||||
local profilePath="$profileDir/$profile.profile"
|
||||
debug "try profile at path: '$profilePath'"
|
||||
if [ -f "$profilePath" ]; then
|
||||
loadProfileByPath "$profilePath"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
@ -291,55 +291,54 @@ initDefaultProfileDirs() {
|
|||
}
|
||||
|
||||
# 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;
|
||||
# adds an entry to `paths` and evals `true` on success;
|
||||
# evals `false` if the path couldn't be added, for any reason.
|
||||
cliPathArgs=()
|
||||
tryPath() {
|
||||
_path="$1"
|
||||
_how="$2"
|
||||
local path="$1"
|
||||
local how="$2"
|
||||
|
||||
if [ "$_how" = "existing" ]; then
|
||||
if [ "$how" = "existing" ]; then
|
||||
# the caller wants to access either a file, or a directory (possibly a symlink to such a thing)
|
||||
if [ -e "$_path" ]; then
|
||||
cliPathArgs+=("$(relativeTo "$PWD" "$_path")")
|
||||
if [ -e "$path" ]; then
|
||||
paths+=("$(relativeTo "$PWD" "$path")")
|
||||
true
|
||||
fi
|
||||
false
|
||||
elif [ "$_how" = "existingFile" ]; then
|
||||
elif [ "$how" = "existingFile" ]; then
|
||||
# the caller wants to access a file, and explicitly *not* a directory (though it could be a symlink *to a file*)
|
||||
if [ -f "$_path" ]; then
|
||||
cliPathArgs+=("$(relativeTo "$PWD" "$_path")")
|
||||
if [ -f "$path" ]; then
|
||||
paths+=("$(relativeTo "$PWD" "$path")")
|
||||
true
|
||||
fi
|
||||
false
|
||||
elif [ "$_how" = "parent" ]; then
|
||||
elif [ "$how" = "parent" ]; then
|
||||
# the caller wants access to the entire directory containing this directory regardless of the file's existence.
|
||||
parent _tryPathParent "$_path"
|
||||
parent _tryPathParent "$path"
|
||||
tryPath "$_tryPathParent" "existing"
|
||||
elif [ "$_how" = "existingOrParent" ]; then
|
||||
elif [ "$how" = "existingOrParent" ]; then
|
||||
# the caller wants access to the path, or write access to the parent directory so it may create the path if it doesn't exist.
|
||||
tryPath "$_path" "existing" || tryPath "$_path" "parent"
|
||||
elif [ "$_how" = "existingFileOrParent" ]; then
|
||||
tryPath "$path" "existing" || tryPath "$path" "parent"
|
||||
elif [ "$how" = "existingFileOrParent" ]; then
|
||||
# the caller wants access to the file, or write access to the parent directory so it may create the file if it doesn't exist.
|
||||
tryPath "$_path" "existingFile" || tryPath "$_path" "parent"
|
||||
tryPath "$path" "existingFile" || tryPath "$path" "parent"
|
||||
fi
|
||||
}
|
||||
|
||||
# if the argument looks path-like, then add it to cliPathArgs.
|
||||
# if the argument looks path-like, then add it to paths.
|
||||
# this function ingests absolute, relative, or file:///-type URIs.
|
||||
# but it converts any such path into an absolute path before adding it to cliPathArgs.
|
||||
# but it converts any such path into an absolute path before adding it to paths.
|
||||
tryArgAsPath() {
|
||||
_arg="$1"
|
||||
_how="$2"
|
||||
local arg="$1"
|
||||
local how="$2"
|
||||
_path=
|
||||
if [ "${_arg:0:1}" = "/" ]; then
|
||||
if [ "${arg:0:1}" = "/" ]; then
|
||||
# absolute path
|
||||
_path="$_arg"
|
||||
elif [ "${_arg:0:8}" = "file:///" ]; then
|
||||
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
|
||||
urldecode _path "${_arg:7}"
|
||||
urldecode _path "${arg:7}"
|
||||
elif [ "${_path:0:1}" = "-" ]; then
|
||||
# 99% chance it's a CLI argument. if not, use `./-<...>`
|
||||
return
|
||||
|
@ -348,7 +347,7 @@ tryArgAsPath() {
|
|||
_path="$PWD/$_arg"
|
||||
fi
|
||||
|
||||
tryPath "$_path" "$_how"
|
||||
tryPath "$_path" "$how"
|
||||
}
|
||||
|
||||
|
||||
|
@ -358,9 +357,9 @@ tryArgAsPath() {
|
|||
parseArgsExtra=()
|
||||
parseArgs() {
|
||||
while [ "$#" -ne 0 ]; do
|
||||
_arg="$1"
|
||||
local arg="$1"
|
||||
shift
|
||||
case "$_arg" in
|
||||
case "$arg" in
|
||||
(--)
|
||||
# rest of args are for the CLI, and not for us.
|
||||
# consider two cases:
|
||||
|
@ -410,9 +409,9 @@ parseArgs() {
|
|||
shift
|
||||
;;
|
||||
(--sane-sandbox-cap)
|
||||
_cap="$1"
|
||||
local cap="$1"
|
||||
shift
|
||||
capabilities+=("$_cap")
|
||||
capabilities+=("$cap")
|
||||
;;
|
||||
(--sane-sandbox-portal)
|
||||
# instruct glib/gtk apps to perform actions such as opening external files via dbus calls to org.freedesktop.portal.*.
|
||||
|
@ -427,41 +426,40 @@ parseArgs() {
|
|||
;;
|
||||
(--sane-sandbox-dns)
|
||||
# N.B.: these named temporary variables ensure that "set -x" causes $1 to be printed
|
||||
_dns="$1"
|
||||
local dns="$1"
|
||||
shift
|
||||
dns+=("$_dns")
|
||||
dns+=("$dns")
|
||||
;;
|
||||
(--sane-sandbox-firejail-arg)
|
||||
_fjFlag="$1"
|
||||
local fjFlag="$1"
|
||||
shift
|
||||
firejailFlags+=("$_fjFlag")
|
||||
firejailFlags+=("$fjFlag")
|
||||
;;
|
||||
(--sane-sandbox-bwrap-arg)
|
||||
_bwrapFlag="$1"
|
||||
local bwrapFlag="$1"
|
||||
shift
|
||||
bwrapFlags+=("$_bwrapFlag")
|
||||
bwrapFlags+=("$bwrapFlag")
|
||||
;;
|
||||
(--sane-sandbox-net)
|
||||
net="$1"
|
||||
shift
|
||||
;;
|
||||
(--sane-sandbox-keep-namespace)
|
||||
_namespace="$1"
|
||||
local namespace="$1"
|
||||
shift
|
||||
if [ "$_namespace" = all ]; then
|
||||
if [ "$namespace" = all ]; then
|
||||
keepNamespace+=("cgroup" "ipc" "pid" "uts")
|
||||
else
|
||||
keepNamespace+=("$_namespace")
|
||||
keepNamespace+=("$namespace")
|
||||
fi
|
||||
;;
|
||||
(--sane-sandbox-path)
|
||||
_path="$1"
|
||||
local path="$1"
|
||||
shift
|
||||
paths+=("$_path")
|
||||
paths+=("$(relativeTo "$PWD" "$path")")
|
||||
;;
|
||||
(--sane-sandbox-add-pwd)
|
||||
_path="$PWD"
|
||||
paths+=("$_path")
|
||||
paths+=("$PWD")
|
||||
;;
|
||||
(--sane-sandbox-profile)
|
||||
# load the profile *immediately*, inline.
|
||||
|
@ -472,12 +470,12 @@ parseArgs() {
|
|||
(--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"
|
||||
local dir="$1"
|
||||
shift
|
||||
profileDirs=("$_dir" "${profileDirs[@]}")
|
||||
profileDirs=("$dir" "${profileDirs[@]}")
|
||||
;;
|
||||
(*)
|
||||
parseArgsExtra+=("$_arg")
|
||||
parseArgsExtra+=("$arg")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
@ -511,12 +509,12 @@ firejailIngestProfile() {
|
|||
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"
|
||||
local fjProfileDirs=(@firejailProfileDirs@)
|
||||
for fjProfileDir in "${fjProfileDirs[@]}"; do
|
||||
local fjProfile="$fjProfileDir/$1.profile"
|
||||
debug "try firejail profile at path: '$fjProfile'"
|
||||
if [ -f "$fjProfile" ]; then
|
||||
firejailProfile="$fjProfile"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
@ -564,8 +562,8 @@ bwrapIngestPath() {
|
|||
# may be possible to place ever mount in a subdir, and mount the super dir?
|
||||
# or maybe configure remote mounts to somehow never hang.
|
||||
# test -r "$1" && bwrapFlags+=("--dev-bind-try" "$1" "$1")
|
||||
if [ -L "$1" ]; then
|
||||
local target="$(readlink "$1")"
|
||||
if [ -n "$target" ]; then
|
||||
bwrapFlags+=("--symlink" "$target" "$1")
|
||||
else
|
||||
bwrapFlags+=("--dev-bind-try" "$1" "$1")
|
||||
|
@ -783,13 +781,8 @@ noneGetCli() {
|
|||
# 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")
|
||||
for arg in "${cliArgs[@]:1}"; do
|
||||
tryArgAsPath "$arg" "$autodetect"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
@ -800,16 +793,14 @@ maybeAutodetectPaths() {
|
|||
# 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.
|
||||
local normPaths=()
|
||||
for path in "${paths[@]}"; do
|
||||
normPath _canonPath "$path"
|
||||
normPaths+=("$_canonPath")
|
||||
paths+=("$_canonPath")
|
||||
done
|
||||
paths=("${normPaths[@]}")
|
||||
}
|
||||
expandLink() {
|
||||
if [ -L "$1" ]; then
|
||||
local target="$(readlink "$1")"
|
||||
if [ -n "$target" ]; then
|
||||
# make absolute
|
||||
target="$(relativeTo "$(dirname "$1")" "$target")"
|
||||
# add + expand the symlink further, but take care to avoid infinite recursion
|
||||
|
@ -822,32 +813,32 @@ expandLink() {
|
|||
}
|
||||
### expand `paths` until it contains no symlinks whose target isn't also in `paths`
|
||||
expandLinks() {
|
||||
for _path in "${paths[@]}"; do
|
||||
expandLink "$_path"
|
||||
for path in "${paths[@]}"; do
|
||||
expandLink "$path"
|
||||
done
|
||||
}
|
||||
removeSubpaths() {
|
||||
# remove subpaths, but the result might include duplicates.
|
||||
local toplevelPaths=()
|
||||
for _path in "${paths[@]}"; do
|
||||
for path in "${paths[@]}"; do
|
||||
local isSubpath=
|
||||
for _other in "${paths[@]}"; do
|
||||
if [[ "$_path" =~ ^$_other/.* ]] || [ "$_other" = "/" ] && [ "$_path" != "/" ]; then
|
||||
# N.B.: $_path lacks a trailing slash, so this never matches self.
|
||||
# UNLESS $_path or $_other is exactly `/`, which we special-case.
|
||||
for other in "${paths[@]}"; do
|
||||
if [[ "$path" =~ ^$other/.* ]] || [ "$other" = "/" ] && [ "$path" != "/" ]; then
|
||||
# N.B.: $path lacks a trailing slash, so this never matches self.
|
||||
# UNLESS $path or $other is exactly `/`, which we special-case.
|
||||
isSubpath=1
|
||||
fi
|
||||
done
|
||||
if [ -z "$isSubpath" ]; then
|
||||
toplevelPaths+=("$_path")
|
||||
toplevelPaths+=("$path")
|
||||
fi
|
||||
done
|
||||
|
||||
# remove duplicated paths.
|
||||
local canonicalizedPaths=()
|
||||
for _path in "${toplevelPaths[@]}"; do
|
||||
if ! $(contains "$_path" "${canonicalizedPaths[@]}"); then
|
||||
canonicalizedPaths+=("$_path")
|
||||
for path in "${toplevelPaths[@]}"; do
|
||||
if ! $(contains "$path" "${canonicalizedPaths[@]}"); then
|
||||
canonicalizedPaths+=("$path")
|
||||
fi
|
||||
done
|
||||
paths=("${canonicalizedPaths[@]}")
|
||||
|
@ -873,28 +864,28 @@ parseArgsAndEnvironment() {
|
|||
### convert generic args into sandbox-specific args
|
||||
# order matters: for firejail, early args override the later --profile args
|
||||
ingestForBackend() {
|
||||
for _path in "${paths[@]}"; do
|
||||
"$method"IngestPath "$_path"
|
||||
for path in "${paths[@]}"; do
|
||||
"$method"IngestPath "$path"
|
||||
done
|
||||
|
||||
for _cap in "${capabilities[@]}"; do
|
||||
"$method"IngestCapability "$_cap"
|
||||
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"
|
||||
for addr in "${dns[@]}"; do
|
||||
"$method"IngestDns "$addr"
|
||||
done
|
||||
|
||||
for _ns in "${keepNamespace[@]}"; do
|
||||
"$method"IngestKeepNamespace "$_ns"
|
||||
for ns in "${keepNamespace[@]}"; do
|
||||
"$method"IngestKeepNamespace "$ns"
|
||||
done
|
||||
|
||||
for _prof in "${profilesNamed[@]}"; do
|
||||
"$method"IngestProfile "$_prof"
|
||||
for prof in "${profilesNamed[@]}"; do
|
||||
"$method"IngestProfile "$prof"
|
||||
done
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user