unshare -m and mount propagation
1. User-ns, mount-ns and mount propagation.
When you create mount-ns in user-ns (or both at once), kernel automatically breaks mount propagation from guest to host (in other words, forcibly downgrade "shared" mounts to "slave"), due to obvious security consideration (if your mount in user-ns guest will propagate back to host, it will be disaster).
E.g. try
unshare -r -m --prop unchanged findmnt -no TARGET,PROPAGATION|head -1
or
unshare -r unshare --prop unchanged findmnt -no TARGET,PROPAGATION|head -1
(both will show "/ private,slave", even though unshare(1) have not tried to change propagation flags).
Note that once propagation is broken, you cannot go back. E.g.
unshare -r -m --propagation shared -- findmnt -no TARGET,PROPAGATION|head -1
or (basically same)
unshare -r -m --propagation unchanged sh -c 'mount --make-rshared /;
findmnt -no TARGET,PROPAGATION|head -1'
will results in "/ shared,slave"; that is, propagation from guest to host is disabled, but propagation within guest is enabled.
2. Long-lived mount-ns and dangers of --propagation private (default in recent util-linux).
--propagation private breaks unmount propagation from "host" to "guest", so if you mount e.g. removable media in host, unshare mount namespace and spawn long-lived process, then umount your media in host namespace, it still remains mounted in guest namespace, and keep device busy:
mount /media/cdrom unshare -rm --prop private sleep inf & pid=$! eject /media/cdrom # oops, still locked grep /media/cdrom /proc/self/mounts (empty) sudo nsenter -t $pid -m grep /media/cdrom /proc/self/mounts # ... as it is still mounted there
If device locks mounted media (e.g. cdrom), this can be confusing to user ("why eject does not work? I umounted it, fuser/lsof shows nothing???").
If device does not lock mounted media, and user forcibly ejects media (e.g. cardreader or usb drive), this can result in data loss (filesystem is not properly umounted, there can be unsynced data in cache).
--propagation slave does not have this problem (when host unmount /cdrom, it is also unmounted in guest):
mount /media/cdrom
unshare -rm --prop slave sleep inf &
pid=$!
umount /media/cdrom # or eject /media/cdrom
sudo nsenter -t $pid -m grep /media/cdrom /proc/self/mounts
(empty)
Also, once you (completely) broke propagation by --propagation private [as implied by default in current util-linux], you cannot go back. E.g.
unshare -rm sh -c 'findmnt -no TARGET,PROPAGATION|head -1; mount --make-rslave /; findmnt -no TARGET,PROPAGATION|head -1'
/ private
/ private
I think this issue should be at least documented. And, maybe, default --propagation should be changed to slave.
=====================================================================
P.S. I'd like to note that this thing has some abuse potential. Above scenarios suggest *accidental* case when `unshare -rm --prop private \
sleep inf &` can trigger data loss. But someone can *intentionally* try to choose moment when it triggers most disruption to other users (and root) work. This also affects fs/devices they cannot access (and thus cannot normally block by chdir or opening file; besides, chdir or open file is visible in lsof/fuser, stray sleep-in-namespace is not).
(Of course, this possible abuse is *not* a util-linux problem [and cannot be solved within util-linux]; this is a *kernel* problem)
P.P.S. as I dig into user-ns, I'm more and more happy our debian overlords disabled unprivileged userns by default. And lately I feel they should've disabled it completely :-| It's a way too prone to abuse.
Karel Zak
maintainerQuoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.
The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users who have no clue about --propagation.
So, I don't think we want to change any default to corrupt scripts where is no explicitly specified --propagation.
Karel
Signature · 2 lines
Karel Zak <[email protected]> http://karelzak.blogspot.com
Quoted 8 lines · Karel Zak
Quoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
Quoted 7 lines
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users who have no clue about --propagation.
So, I don't think we want to change any default to corrupt scripts where is no explicitly specified --propagation.
By you already broke scripts that expected old a-la '--propagation unchanged' behavior.
E.g. one my script did
unshare -m sh -c 'mount --make-rslave /; ...'
Now I must check for util-linux version and either use --propagation option, or mount --make-rslave (you cannot revert back from private to slave).
(And as I said, 'private' breaks umount propagation and thus very bad for long-running namespaces).
Karel Zak
maintainerQuoted 15 lines · Yuriy M. Kaminskiy
Quoted 13 lines · Karel Zak
Quoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users who have no clue about --propagation.
Quoted 5 lines
Quoted 2 lines
So, I don't think we want to change any default to corrupt scripts where is no explicitly specified --propagation.
By you already broke scripts that expected old a-la '--propagation unchanged' behavior.
Only if your system uses something else that kernel default 'private' and you depend on this non-default setting. (IMHO relatively small groups of users)
The old "--propagation unchanged" makes unshare useless on some mainstream distros where default is 'shared'.
Anyway, we will not change any default now.
Karel
Signature · 2 lines
Karel Zak <[email protected]> http://karelzak.blogspot.com
Quoted 7 lines · Karel Zak
Quoted 6 lines · Yuriy M. Kaminskiy
Quoted 4 lines · Karel Zak
Quoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users
Opposite. It does not change anything for older systems, but breaks things for new systems.
Quoted 1 line
Quoted 1 line
Quoted 1 line
who have no clue about --propagation.
And it is *especially* harmful for users that are not aware about --propagation. As private (new 2.27+ default) break umount propagation, and results in nasty surprises (up to data loss).
Quoted 9 lines
Quoted 5 lines
Quoted 2 lines
So, I don't think we want to change any default to corrupt scripts where is no explicitly specified --propagation.
By you already broke scripts that expected old a-la '--propagation unchanged' behavior.
Only if your system uses something else that kernel default 'private' and you depend on this non-default setting. (IMHO relatively small groups of users)
All systemd systems use shared. Which is not "small group of users".
Quoted 2 lines
The old "--propagation unchanged" makes unshare useless on some mainstream distros where default is 'shared'.
No, it is not. --propagation does not do *anything* that cannot be done without it. On pre-2.27 util-linux,
unshare -m sh -c 'mount --make-rprivate /; ...'
does exactly same as unshare -m [--propagation=private] ... in 2.27+.
Reverse is not true! With 2.27 you *must* use new [backward-incompatible] options to revert to sane behavior [which is *slave*, not *private*].
Quoted 1 line
Anyway, we will not change any default now.
Karel Zak
maintainerQuoted 16 lines · Yuriy M. Kaminskiy
Quoted 7 lines · Karel Zak
Quoted 6 lines · Yuriy M. Kaminskiy
Quoted 4 lines · Karel Zak
Quoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users
Quoted 8 lines
Opposite. It does not change anything for older systems, but breaks things for new systems.
Quoted 1 line
Quoted 1 line
Quoted 1 line
who have no clue about --propagation.
And it is *especially* harmful for users that are not aware about --propagation. As private (new 2.27+ default) break umount propagation, and results in nasty surprises (up to data loss).
Well, you see only umount propagation...
The problem is that the original implementation (try emulate by "--propagation unchanged") makes "unshare --mount" useless at all on systems with shared root fs.
The very old (since year 2009) and very common use-case is:
# unshare --mount # mount /dev/foo /mnt
and user expects that /mnt will be visible *only* in the session (namespace). This is the way how many users use unshare for years.
Unfortunately, after systemd installation it does not work anymore and /mnt is visible everywhere. For users it's regression and it has been reported many many times.
You can blame systemd, but the problem is that unshare(1) was not robust enough. So we have forced unshare to use "private" by default to keep the *original behavior* independently on root fs propagation flag.
Karel
Signature · 2 lines
Karel Zak <[email protected]> http://karelzak.blogspot.com
Quoted 20 lines · Karel Zak
Quoted 19 lines · Yuriy M. Kaminskiy
Quoted 7 lines · Karel Zak
Quoted 6 lines · Yuriy M. Kaminskiy
Quoted 4 lines · Karel Zak
Quoted 2 lines · Yuriy M. Kaminskiy
I think this issue should be at least documented. And, maybe, default
--propagationshould be changed toslave.Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
The reason why we use 'private' is that it's the kernel default for years and it's what has been expected by users for long time before we introduced --propagation and any unshare(1) default.
The current --propagation default unifies things and makes unshare(1) portable to distributions where root fs is mounted as 'shared' (e.g. systemd distros) and all this in backwardly compatible way for users
Opposite. It does not change anything for older systems, but breaks things for new systems.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
who have no clue about --propagation.
And it is *especially* harmful for users that are not aware about --propagation. As private (new 2.27+ default) break umount propagation, and results in nasty surprises (up to data loss).
Well, you see only umount propagation...
Because *breaking* it causes real problems?
Quoted 7 lines
The problem is that the original implementation (try emulate by "--propagation unchanged") makes "unshare --mount" useless at all on systems with shared root fs.
The very old (since year 2009) and very common use-case is:
# unshare --mount
mount --make-rslave / # or --make-rprivate or whatever
Quoted 1 line
# mount /dev/foo /mnt
And? I've posted how this could be solved *without* changing anything in unshare.
Quoted 11 lines
and user expects that /mnt will be visible *only* in the session (namespace). This is the way how many users use unshare for years.
Unfortunately, after systemd installation it does not work anymore and /mnt is visible everywhere. For users it's regression and it has been reported many many times.
You can blame systemd, but the problem is that unshare(1) was not robust enough. So we have forced unshare to use "private" by default to keep the *original behavior* independently on root fs propagation flag.
You can have same effect with *slave* as default, with exception that host->guest mount/unmount propagation still works.
When kernel have to get rid of shared propagation (in userns), it downgrades shared mounts to *slave*, not to *private*.
When systemd itself downgrades shared propagation (for running service in new mount namespace; Protect*/Private*/etc), it also downgrades *shared* propagation to *slave*, not to *private*.
P.S. For sure, *any* of propagation variants have some or other drawbacks and corner cases; however, without special care about removable media (and alike), *private* has higher chance to beat you in a nasty way.