simple_nas/app/share_jail.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/sh
# Sandbox launcher for the public share worker. Runs inside a fresh mount
# namespace (the parent starts it with `unshare --mount --propagation private`).
# It blinds the process to the sensitive trees and files, then drops to an
# unprivileged uid with only the capabilities uploads need, and execs the
# worker. If any step fails the process exits non-zero and app.py falls back to
# running the site in the main process.
#
# /data stays LIVE (the real directory), so the worker's atomic writes
# (counters, lock snapshot) and the admin's edits (link rotation, account
# changes) are seen by both sides - a per-file bind mount would break both,
# because renaming onto a mount point fails and a replaced file gets a new
# inode the bind would not follow. The secret files in /data are masked
# individually instead. The mask lists MUST match sharesandbox.JAIL_MASK_*.
set -eu
# 1. hide the sensitive trees entirely (HA config, SSL, other add-ons, backups).
for d in /config /ssl /addon_configs /backup; do
if [ -d "$d" ]; then
mount -t tmpfs -o mode=0000 tmpfs "$d"
fi
done
# 2. mask the secret files/dirs inside the otherwise-live /data.
EMPTY_FILE=/run/nasjail_empty
: > "$EMPTY_FILE"
chmod 0000 "$EMPTY_FILE"
for f in admin_auth.json options.json; do
if [ -e "/data/$f" ]; then
mount --bind "$EMPTY_FILE" "/data/$f"
fi
done
# Created first if missing: the admin may add the first backup job while the
# worker runs, and a directory made after this point would not be masked.
for d in samba remote_backup; do
[ -d "/data/$d" ] || mkdir -m 0700 "/data/$d"
mount -t tmpfs -o mode=0000 tmpfs "/data/$d"
done
# 3. drop privileges and exec the worker. nobody keeps only the file caps an
# upload needs (write into a share folder, hand the file to its Samba owner);
# SYS_ADMIN, SYS_RAWIO and the rest are gone, and no-new-privs pins that.
exec setpriv \
--reuid nobody --regid nobody --init-groups \
--no-new-privs \
--inh-caps -all,+chown,+dac_override,+fowner \
--ambient-caps -all,+chown,+dac_override,+fowner \
--bounding-set -all,+chown,+dac_override,+fowner \
python3 /app/share_worker.py