sane-sandboxed: tweak symlink caching to allow /run/current-system to be bind-mounted instead of symlinked
This commit is contained in:
parent
660ba94c7c
commit
bd3e06982b
|
@ -117,7 +117,11 @@ let
|
|||
"${builtins.unsafeDiscardStringContext config.environment.binsh}" = "bash";
|
||||
"/usr/bin/env" = config.environment.usrbinenv;
|
||||
"${builtins.unsafeDiscardStringContext config.environment.usrbinenv}" = "coreutils";
|
||||
|
||||
# "/run/current-system" = "${config.system.build.toplevel}";
|
||||
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
||||
# mount it as if it were a directory instead.
|
||||
"/run/current-system" = "";
|
||||
} // lib.optionalAttrs config.hardware.opengl.enable {
|
||||
"/run/opengl-driver" = let
|
||||
gl = config.hardware.opengl;
|
||||
|
|
|
@ -274,6 +274,30 @@ contains() {
|
|||
return 1
|
||||
}
|
||||
|
||||
# `readlinkOnce outVar path`: writes the link target to outVar
|
||||
# or sets outVar="" if path isn't a link.
|
||||
# unlink `derefOnce`, this only acts if the leaf of `path` is a symlink,
|
||||
# not if it's an ordinary entry within a symlinked directory.
|
||||
readlinkOnce() {
|
||||
local outVar="$1"
|
||||
local path="$2"
|
||||
local linkTarget=
|
||||
if [ -v "linkCache["$path"]" ]; then
|
||||
linkTarget="${linkCache["$path"]}"
|
||||
elif [ -L "$path" ]; then
|
||||
# path is a link, but not in the cache
|
||||
linkTarget="$(readlink "$path")"
|
||||
# insert it into the cache, in case we traverse it again
|
||||
linkCache["$path"]="$linkTarget"
|
||||
else
|
||||
# remember for later that this path doesn't represent a link.
|
||||
# empty target is used to indicate a non-symlink (i.e. ordinary file/directory).
|
||||
# i think a symlink can *technically* point to "" (via `symlink` syscall), but `ln -s` doesn't allow it
|
||||
linkCache["$path"]=
|
||||
fi
|
||||
declare -g "$outVar"="$linkTarget"
|
||||
}
|
||||
|
||||
# `derefOnce outVar path`: walks from `/` to `path` and derefs the first symlink it encounters.
|
||||
# the dereferenced equivalent of `path` is written to `outVar`.
|
||||
# the dereferenced path may yet contain more unresolved symlinks.
|
||||
|
@ -281,7 +305,6 @@ contains() {
|
|||
derefOnce() {
|
||||
local outVar="$1"
|
||||
local source="$2"
|
||||
local flag="$3"
|
||||
local target=
|
||||
|
||||
local walked=
|
||||
|
@ -289,13 +312,7 @@ derefOnce() {
|
|||
while [ -n "$_unwalked" ]; do
|
||||
splitHead _head _unwalked "$_unwalked"
|
||||
walked="$walked$_head"
|
||||
local linkTarget="${linkCache["$walked"]}"
|
||||
if [ -z "$linkTarget" ] && [ -L "$walked" ]; then
|
||||
# path is a link, but not in the cache
|
||||
linkTarget="$(readlink "$walked")"
|
||||
# insert it into the cache, in case we traverse it again
|
||||
linkCache["$walked"]="$linkTarget"
|
||||
fi
|
||||
readlinkOnce linkTarget "$walked"
|
||||
if [ -n "$linkTarget" ]; then
|
||||
target="$linkTarget$_unwalked"
|
||||
break
|
||||
|
@ -303,7 +320,7 @@ derefOnce() {
|
|||
done
|
||||
|
||||
# make absolute
|
||||
if [ "$flag" != '--no-canon' ] && [ -n "$target" ]; then
|
||||
if [ -n "$target" ]; then
|
||||
if [ "${target:0:1}" != "/" ]; then
|
||||
# `walked` is a relative link.
|
||||
# then, the link is relative to the parent directory of `walked`
|
||||
|
@ -637,11 +654,12 @@ 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
|
||||
# N.B.: test specifically whether this path is a link, not whether it's a non-symlink under a symlink'd dir.
|
||||
# this way, the filetype of this path is *always* the same both inside and outside the sandbox.
|
||||
derefOnce _target "$1" '--no-canon'
|
||||
bwrapFlags+=("--symlink" "$_target" "$1")
|
||||
|
||||
# N.B.: test specifically whether this path is a link, not whether it's a non-symlink under a symlink'd dir.
|
||||
# this way, the filetype of this path is *always* the same both inside and outside the sandbox.
|
||||
readlinkOnce linkTarget "$1"
|
||||
if [ -n "$linkTarget" ]; then
|
||||
bwrapFlags+=("--symlink" "$linkTarget" "$1")
|
||||
else
|
||||
bwrapFlags+=("--dev-bind-try" "$1" "$1")
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue
Block a user