Freigaben einbinden: Mount im Namensraum des Wirts

Eine Freigabe wurde nie eingebunden -- "mount error(1): Operation not
permitted". Gemessen: mit denselben Optionen und Zugangsdaten gelingt die
Einbindung aus einer normalen Root-Shell sofort. Ursache ist der eigene
Mount-Namensraum des Dienstes (ProtectSystem, ProtectHome, PrivateTmp,
ReadWritePaths); darin laesst sich kein neues Dateisystem einbinden.

Nachgebaut und belegt: derselbe Aufruf scheitert in einem transienten Unit mit
dieser Haertung und gelingt, sobald er ueber nsenter im Namensraum des Wirts
laeuft. Von dort wird der Mount in den Namensraum des Dienstes weitergegeben,
die Anwendung sieht ihn also -- geprueft, inklusive Lesbarkeit fuer den
Dienstbenutzer.

mount-cifs und umount laufen deshalb ueber nsenter. Ohne nsenter im System
bleibt das Verhalten unveraendert. Die Haertung des Dienstes bleibt vollstaendig
erhalten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 21:20:52 +02:00
co-authored by Claude Opus 5
parent 6ac2ed0a62
commit a19206322b
+20 -4
View File
@@ -258,8 +258,19 @@ case "$verb" in
# Kommandozeile (Prozessliste) und nie ueber die Umgebung # Kommandozeile (Prozessliste) und nie ueber die Umgebung
# (/proc/<pid>/environ). # (/proc/<pid>/environ).
read_stdin_limited > "$creds" read_stdin_limited > "$creds"
mkdir -p "$target" # Der aufrufende Dienst laeuft in einem eigenen Mount-Namensraum
if mount -t cifs "$share" "$target" \ # (ProtectSystem, PrivateTmp, ReadWritePaths). Ein Einbinden *darin*
# scheitert mit "mount error(1): Operation not permitted" -- gemessen: mit
# denselben Optionen und denselben Zugangsdaten gelingt es aus einer
# normalen Root-Shell sofort. Deshalb wird im Namensraum des Wirts
# eingebunden; von dort wird der Mount in den Namensraum des Dienstes
# weitergegeben (er haengt als "slave" darunter), die Anwendung sieht ihn
# also. Die Zugangsdatei unter /run ist ueber die Grenze lesbar, /run ist
# nicht privatisiert.
im_wirt=(nsenter --mount=/proc/1/ns/mnt --)
command -v nsenter >/dev/null 2>&1 || im_wirt=()
"${im_wirt[@]}" mkdir -p "$target"
if "${im_wirt[@]}" mount -t cifs "$share" "$target" \
-o "credentials=$creds,uid=$(id -u tesm 2>/dev/null || echo 0),gid=$(id -g tesm 2>/dev/null || echo 0),file_mode=0640,dir_mode=0750,vers=3.1.1,seal" -o "credentials=$creds,uid=$(id -u tesm 2>/dev/null || echo 0),gid=$(id -g tesm 2>/dev/null || echo 0),file_mode=0640,dir_mode=0750,vers=3.1.1,seal"
then then
shred -u "$creds" 2>/dev/null || rm -f "$creds" shred -u "$creds" 2>/dev/null || rm -f "$creds"
@@ -271,8 +282,13 @@ case "$verb" in
umount) umount)
check_mount_target "${1:?Ziel fehlt}" check_mount_target "${1:?Ziel fehlt}"
umount -l "$1" || true # Gegenstueck zu mount-cifs: der Mount liegt im Namensraum des Wirts, also
rmdir "$1" 2>/dev/null || true # muss er auch dort geloest werden. Ein umount im Dienst-Namensraum wuerde
# ihn nur dort ausblenden und die Freigabe bliebe eingebunden.
im_wirt=(nsenter --mount=/proc/1/ns/mnt --)
command -v nsenter >/dev/null 2>&1 || im_wirt=()
"${im_wirt[@]}" umount -l "$1" || true
"${im_wirt[@]}" rmdir "$1" 2>/dev/null || true
;; ;;
apt-install) apt-install)