sane-sandboxed: expand symlinks before binding them into the sandbox
This commit is contained in:
parent
89135d08cb
commit
d148b19767
|
@ -135,6 +135,19 @@ usage() {
|
|||
|
||||
## UTILITIES/BOILERPLATE
|
||||
|
||||
# `relativeTo base-dir path`
|
||||
# if `path` is absolute, returns `path`
|
||||
# otherwise, joins `path` onto `base-dir`
|
||||
relativeTo() {
|
||||
local base="$1"
|
||||
local path="$2"
|
||||
if [ "${path:0:1}" == "/" ]; then
|
||||
echo "$path"
|
||||
else
|
||||
echo "$base/$path"
|
||||
fi
|
||||
}
|
||||
|
||||
# `normPath outVar "$path"`
|
||||
# remove duplicate //, reduce '.' and '..' (naively).
|
||||
# expects a full path as input
|
||||
|
@ -226,6 +239,19 @@ urldecode() {
|
|||
declare -g "$outVar"="$(echo -e "${i//%/\\x}")"
|
||||
}
|
||||
|
||||
# `contains needle ${haystack[0]} ${haystack[1]} ...`
|
||||
# evals `true` if the first argument is equal to any of the other args
|
||||
contains() {
|
||||
local needle="$1"
|
||||
shift
|
||||
for item in "$@"; do
|
||||
if [ "$needle" = "$item" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
## HELPERS
|
||||
|
||||
|
@ -769,41 +795,57 @@ 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.
|
||||
_normPaths=()
|
||||
for _path in "${paths[@]}"; do
|
||||
normPath _canonPath "$_path"
|
||||
_normPaths+=("$_canonPath")
|
||||
local normPaths=()
|
||||
for path in "${paths[@]}"; do
|
||||
normPath _canonPath "$path"
|
||||
normPaths+=("$_canonPath")
|
||||
done
|
||||
|
||||
paths=("${normPaths[@]}")
|
||||
}
|
||||
expandLink() {
|
||||
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
|
||||
normPath _canonTarget "$target"
|
||||
if ! $(contains "$_canonTarget" "${paths[@]}"); then
|
||||
paths+=("$_canonTarget")
|
||||
expandLink "$_canonTarget"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
### expand `paths` until it contains no symlinks whose target isn't also in `paths`
|
||||
expandLinks() {
|
||||
for _path in "${paths[@]}"; do
|
||||
expandLink "$_path"
|
||||
done
|
||||
}
|
||||
removeSubpaths() {
|
||||
# remove subpaths, but the result might include duplicates.
|
||||
_toplevelPaths=()
|
||||
for _path in "${_normPaths[@]}"; do
|
||||
_isSubpath=
|
||||
for _other in "${_normPaths[@]}"; do
|
||||
local toplevelPaths=()
|
||||
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.
|
||||
_isSubpath=1
|
||||
isSubpath=1
|
||||
fi
|
||||
done
|
||||
if [ -z "$_isSubpath" ]; then
|
||||
_toplevelPaths+=("$_path")
|
||||
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
|
||||
local canonicalizedPaths=()
|
||||
for _path in "${toplevelPaths[@]}"; do
|
||||
if ! $(contains "$_path" "${canonicalizedPaths[@]}"); then
|
||||
canonicalizedPaths+=("$_path")
|
||||
fi
|
||||
done
|
||||
paths=("${canonicalizedPaths[@]}")
|
||||
}
|
||||
|
||||
|
||||
|
@ -826,7 +868,7 @@ parseArgsAndEnvironment() {
|
|||
### convert generic args into sandbox-specific args
|
||||
# order matters: for firejail, early args override the later --profile args
|
||||
ingestForBackend() {
|
||||
for _path in "${canonicalizedPaths[@]}"; do
|
||||
for _path in "${paths[@]}"; do
|
||||
"$method"IngestPath "$_path"
|
||||
done
|
||||
|
||||
|
@ -872,6 +914,8 @@ if [ -z "$isDisable" ]; then
|
|||
"$method"Setup
|
||||
maybeAutodetectPaths
|
||||
canonicalizePaths
|
||||
expandLinks
|
||||
removeSubpaths
|
||||
|
||||
ingestForBackend
|
||||
"$method"GetCli
|
||||
|
|
Loading…
Reference in New Issue
Block a user