4.2.3 Mount Admission

A stratafs mount is configured entirely at mount time. This section covers what the caller must be entitled to, the conditions a configuration has to satisfy, and the order in which those conditions are evaluated.

4.2.3.1 Entitlement #

Establishing a mount with no create stratum takes no privilege of its own. The filesystem type carries FS_USERNS_MOUNT, so an unprivileged mount in a user namespace is permitted; what the caller needs is only the access that resolving the stratum paths already requires, which falls out of the resolution itself.

A stack that carries create is different. Copy-up is authorised by the outer handle and deliberately requires no add-entry right on the create stratum (§4.6.2), so the mount configuration carries authority to materialise names in a real directory outside the mount. The caller establishing such a stack must be operating in the initial user namespace and hold CAP_SYS_ADMIN there; anything else fails with EPERM.

The test is made in get_tree, before the tree is built and therefore before any stratum path is resolved, and it is stricter than requiring the capability alone: the credential's own user namespace must be the initial one, not merely a namespace in which the capability resolves. This is the closure the KACS copy-up context depends on. The check is made once, when the immutable stack is established, rather than at each copy-up, so descriptor delegation cannot reintroduce authorisation against the acting task, and no reconfiguration can re-supply the strata list.

There is no explicit per-stratum entitlement check in the mount path. Both halves come out of the ordinary machinery: traverse rights are enforced by the path walk, which runs under the mounting caller's credentials, and the right to read a stratum directory's attributes is enforced by using the security-checking vfs_getattr rather than its unchecked variant, which reaches KACS's getattr hook and demands FILE_READ_ATTRIBUTES.

One seam is worth recording: the path walk uses the credentials captured on the filesystem context, while vfs_getattr runs outside that override and so uses the acting task's. For a mount established the ordinary way the two are the same task. For one established with fsopen and fsconfig from different tasks they need not be.

Nothing re-checks entitlement if a stratum directory later appears. That is sound because every access through the mount is checked against the providing object in any case (§4.6.1), so a caller who mounts a stratum they cannot read still cannot read it.

4.2.3.2 Validity #

ConditionError
The stratum stack is emptyEINVAL
The stack exceeds 16 strataEINVAL
More than one stratum carries createEINVAL
A stratum carries both create and roEINVAL
The same directory appears as more than one stratumEINVAL
A malformed strata= value (§4.2.2)EINVAL
A create-bearing stack from outside the initial user namespace, or without CAP_SYS_ADMIN thereEPERM
A stratum's path names something other than a directoryENOTDIR
A stratum's directory is absent and the stratum does not carry amENOENT
The composed stack reaches the kernel's maximum stacking depthELOOP
A stratum lies within the mount point, or within another stratafs mount whose strata include this mount pointELOOP
Sixteen consecutive collisions allocating a mount cookieEAGAIN

Two strata are the same directory when they resolve to the same directory object, not merely when their paths are equal as strings: the comparison is on resolved inodes, so two paths reaching one directory through different symbolic links or bind mounts are caught. Absent strata are skipped and never compared.

4.2.3.3 Evaluation order #

The conditions that depend on nothing but the option string are decided first, during parsing and stack-wide validation, and are reported whatever the caller's access. The EPERM admission test comes next, in get_tree, still before any path is touched. Only then are the strata resolved.

The purpose of that ordering is to stop the validity conditions being an oracle: a caller with no right to traverse a directory should not be able to name it as a stratum and learn from the errno whether it exists and whether it is a directory.

For a single stratum, that holds. The path walk runs under the caller's credentials, so a path the caller cannot resolve returns EACCES from the walk itself, before the type test or the duplicate test is reached, and the EACCES is propagated unchanged.

Across the stack it does not. The strata are checked in one loop — resolve, stat, type-test, compare against earlier strata — so stratum 0 is fully judged before stratum 1 is resolved at all. A caller who names a readable stratum first and an unreadable one second learns the first stratum's ENOTDIR or ENOENT rather than the EACCES they would have been given had the whole stack been checked for entitlement first. This is tracked as a defect; the disclosure is bounded to paths the caller could resolve, but the specified ordering is stack-wide.

The mount-point loop condition is evaluated in a different call entirely, after the tree has been built, and so always follows every entitlement check.

4.2.3.4 Loops #

A stratum inside the mount point is detected directly. The indirect case — a stratum inside another stratafs mount whose own strata include this mount point — is detected by recursing into any stratum whose superblock carries the stratafs magic, bounded by a visited- superblock set and by the kernel's maximum stacking depth. This runs through a Peios-added super_operations hook, validate_mountpoint, wired into the new-mount, bind and move-mount paths by the patch series; it is not an upstream interface.

That check cannot bind after the fact: a mount established within a stratum, or a bind mount of this mount into one of its own strata, can create a cycle later. Resolution is guarded separately, and differently — not by a depth counter but by a per-task, per-superblock re-entrancy list. A task that is already resolving in a superblock and re-enters it gets ELOOP immediately, so a cycle spanning any number of stratafs mounts terminates the moment it returns to one it is already inside.

4.2.3.5 Immutability and mount identity #

The stack is fixed for the life of the mount; changing one is expressed by unmounting and mounting again (§4.2.2).

Two stratafs mounts may name the same directory as a stratum. Each resolves independently and neither is aware of the other; where both have a create stratum in common they mutate the same objects, with the same result as any two writers of one directory. There is no registry of stratum paths to make them aware of each other.

There is a registry of mounts, but it exists for a different purpose. Each mount draws a random non-zero cookie and inserts itself into a global table, retrying up to sixteen times on collision; a second random non-zero cookie is drawn once per boot. The pair identifies which live mount owns a staging entry, so that a mount sharing a create stratum can distinguish another mount's copy-up in flight from an orphan left by a crash (§4.5.2).

A mount succeeds even when no stratum root is present at all — a stack whose only strata are absent am strata is legal. The root inode is constructed with no provider, and reports mode S_IFDIR with no permission bits.

Edit this page