Skip to content

Clean fsopen a bit & add support for mount_setattr#1630

Open
livingsilver94 wants to merge 6 commits into
bytecodealliance:mainfrom
livingsilver94:mount_setattr
Open

Clean fsopen a bit & add support for mount_setattr#1630
livingsilver94 wants to merge 6 commits into
bytecodealliance:mainfrom
livingsilver94:mount_setattr

Conversation

@livingsilver94
Copy link
Copy Markdown

This is my attempt at supporting mount_setattr, taking into consideration the fact struct mount_attr is designed to be expandable, and that it currently borrows a user namespace's file descriptor. See discussions in PR #1002 for more details.

The idea is to have a MountAttr struct that is a thin wrapper around struct mount_attr, that also manages lifetimes. The
underlying type is not exposed: you can only set parameters via the constructor and setters.

While at it, I cleaned fsopen (and some related modules) a little. See the commit history.

Fixes #975.

Test plan

[package]
name = "test"
version = "1.0.0"
rust-version = "1.63"
edition = "2021"

[dependencies]
rustix = { path = "/your/local/fork/of/rustix", features = [
    "mount",
    "linux_latest", # Or "use-libc" to test the other backend.
    "fs",
] }
use std::os::fd::AsFd;

use rustix::fs::{open, Mode, OFlags};
use rustix::io;
use rustix::mount::{
    mount_setattr, MountAttr, MountAttrFlags, MountPropagationFlags, MountSetAttrFlags,
};

// To create a test mount point, run:
// $ mkdir /tmp/testpoint
// # mount -t tmpfs tmpfs /tmp/testpoint

fn main() -> io::Result<()> {
    let dirfd = open("/tmp", OFlags::RDONLY | OFlags::DIRECTORY, Mode::empty())?;

    // Uncomment to test set_param_flag.
    // mount_setattr will return EINVAL, because this won't be a user namespace fd.
    // let fd = open("/dev/null", OFlags::RDONLY, Mode::empty())?;

    let attr = MountAttr::new(
        MountAttrFlags::MOUNT_ATTR_RDONLY,
        MountAttrFlags::empty(),
        MountPropagationFlags::empty(),
    );

    // Uncomment to test set_param_flag.
    // let attr = attr.set_param_flag(rustix::mount::MountAttrParamFlags::IdMap(fd.as_fd()));

    // Uncommenting this line gives a compilation error when set_param_flag is called.
    // drop(fd);

    mount_setattr(dirfd, "testpoint", MountSetAttrFlags::AT_RECURSIVE, attr)?;

    println!("/tmp/testpoint is now mounted read-only");
    Ok(())
}

@livingsilver94 livingsilver94 marked this pull request as draft June 3, 2026 21:08
@livingsilver94
Copy link
Copy Markdown
Author

Converting to draft as the CI is returning errors I did not have on my system running Fedora + Rust 1.96.

MOUNT_ATTR_IDMAP requires an additional field (a file descriptor)
that is not possible to pass to fsmount(). In fact, MOUNT_ATTR_IDMAP
is supposed to be used in `struct mount_attr`, that defines the
`.userns_fd` field for such task. It is better to remove MOUNT_ATTR_IDMAP
from MountAttrFlags to not deceive users.

See https://man7.org/linux/man-pages/man2/fsmount.2.html
MOUNT_ATTR_SIZE_VER0 is the `sizeof` of the first version of
`struct mount_attr`, it's not supposed to be passed as a flag. Remove it
from FsMountAttrFlags.
@livingsilver94 livingsilver94 marked this pull request as ready for review June 3, 2026 21:31
@livingsilver94
Copy link
Copy Markdown
Author

Done. libc is not compatible with Rust 1.63 and it's making the CI fail, but this is outside of the scope of this PR unless you want me to fix that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add mount_setattr

1 participant