if (!mnt_context_target_fd_required(cxt))
return 0;
+
+ DBG_OBJ(CXT, cxt, ul_debug("reopen target fd"));
+
mnt_context_close_target_fd(cxt);
if (mnt_context_get_target_fd(cxt) < 0)
return -errno;
+
+ /* verify the mount landed on the expected target;
+ * cxt->fs->id is set from fd_tree in hook_create_mount() */
+ if (cxt->fs && cxt->fs->id > 0) {
+ int id = 0;
+
+ if (mnt_id_from_fd(cxt->fd_target, NULL, &id) == 0
+ && id != cxt->fs->id) {
+ const char *tgt = mnt_fs_get_target(cxt->fs);
+
+ DBG_OBJ(CXT, cxt, ul_debug(
+ "target mount ID mismatch (expected %d, got %d), umounting",
+ cxt->fs->id, id));
+ if (tgt)
+ umount2(tgt, MNT_DETACH);
+ mnt_context_close_target_fd(cxt);
+ return -EPERM;
+ }
+ DBG_OBJ(CXT, cxt, ul_debug("target mount ID verified (%d)", id));
+ }
+
return 0;
}
if (cxt->fd_target < 0) {
const char *target = mnt_fs_get_target(cxt->fs);
- if (target)
+ if (target) {
cxt->fd_target = ul_open_no_symlinks(target,
O_PATH | O_CLOEXEC, 0);
+ DBG_OBJ(CXT, cxt, ul_debug("open target fd=%d [%s]",
+ cxt->fd_target, target));
+ }
}
return cxt->fd_target;
}
The *user* mount option is accepted if no username is specified. If used in the format *user=someone*, the option is silently ignored and visible only for external mount helpers (/sbin/mount.<type>) for compatibility with some network filesystems.
+WARNING: When using the legacy *mount*(2) syscall (on older kernels without the new mount API), the mount target path is resolved by the kernel at syscall time. This means there is an inherent time-of-check-to-time-of-use (TOCTOU) window between the permission verification and the actual mount operation. If an ancestor directory of the mount target is writable by the unprivileged user, a path component could be swapped to redirect the mount to an unintended location. The new mount API (available since Linux 5.2) eliminates this issue by using file-descriptor-based target resolution. Administrators should ensure that mount target paths for *user* mounts do not traverse directories writable by unprivileged users.
+
=== Bind mount operation
Remount part of the file hierarchy somewhere else. The call is: