Propagation is a direction
Every mount in Linux carries propagation state—shared, slave, private, unbindable, or the effective shared-and-slave combination—and that state answers a directional question: when a mount appears under a mirrored copy of this subtree somewhere else, does it show up here, and do mounts made here show up there. shared propagates among a peer group. slave receives from an upstream group and never sends back to it. A mount that is both receives from its upstream group while forwarding events to its own peers and slaves. private does neither. unbindable is private plus a refusal to be bind-mounted at all. The semantics date to the 2005 shared-subtrees work and have not changed since.
The mistake is treating those labels as a one-bit switch—“propagation on or off”—when it is really two separate trust decisions. Host-to-container: should mounts made on the host appear inside the container? Container-to-host: should mounts made inside the container leak back out? Those have different answers in almost every real deployment, and slave exists precisely because they do: a container root that receives the host’s mounts while its own mounts stay contained.
That is the concrete case I argued on lxc-users, in a thread about read-only roots. A container’s root filesystem might reasonably default to a one-way slave—narrow, receive-only—but globally preventing all container-to-host propagation would remove legitimate implementer choices. There are setups that want a container to publish mounts to the host on purpose. The direction, the specific mount, the distribution’s default, and the trust domain are four separate decisions, and a blanket shared-or-private rule collapses them into one, hiding the boundary that matters.
You cannot recover this reliably from the commands that originally built the mounts. Propagation is inherited and remounted at several layers. On a host where systemd starts directly as the system manager, its current setup code tries to mark / recursively shared; it deliberately leaves propagation to a container manager when already inside a container, and a host can override or fail that setup. Namespace tools may then make their copy private or slave, and a single mount --make-rslave three layers down changes an entire subtree. Reconstructing the state from a presumed boot default is guesswork. Reading it is not: /proc/self/mountinfo carries the actual per-mount flags, which is its own note—read mountinfo first.
The propagation types and directional split remain in use. The slave-root pattern is one policy, not the runtime policy: Docker bind mounts default to rprivate, while Kubernetes nominally maps its None, HostToContainer, and Bidirectional modes to rprivate, rslave, and rshared. Its documented CRI boundary allows None to become rslave when rprivate is not applicable; cri-dockerd is the named example. The primitive survived; the selected direction still varies by runtime, mount type, and configuration.