Skip to content

Commit 41612f0

Browse files
linux_raw: mount: Add support for mount_attr()
1 parent 8fd066c commit 41612f0

3 files changed

Lines changed: 134 additions & 2 deletions

File tree

src/backend/linux_raw/conv.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,14 @@ impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for
483483
}
484484
}
485485

486+
#[cfg(feature = "mount")]
487+
impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountSetAttrFlags> for ArgReg<'a, Num> {
488+
#[inline]
489+
fn from(flags: crate::backend::mount::types::MountSetAttrFlags) -> Self {
490+
c_uint(flags.bits())
491+
}
492+
}
493+
486494
#[cfg(feature = "mount")]
487495
impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> {
488496
#[inline]

src/backend/linux_raw/mount/syscalls.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![allow(unsafe_code)]
77
#![allow(clippy::undocumented_unsafe_blocks)]
88

9-
use crate::backend::conv::{ret, ret_owned_fd, slice, zero};
9+
use crate::backend::conv::{pass_usize, ret, ret_owned_fd, slice, zero};
1010
use crate::fd::{BorrowedFd, OwnedFd};
1111
use crate::ffi::CStr;
1212
use crate::io;
@@ -235,3 +235,22 @@ pub(crate) fn fsconfig_create_excl(fs_fd: BorrowedFd<'_>) -> io::Result<()> {
235235
))
236236
}
237237
}
238+
239+
#[inline]
240+
pub(crate) fn mount_setattr(
241+
fs_fd: BorrowedFd<'_>,
242+
path: &CStr,
243+
flags: super::types::MountSetAttrFlags,
244+
attr: &super::types::MountAttr<'_>,
245+
) -> io::Result<()> {
246+
unsafe {
247+
ret(syscall_readonly!(
248+
__NR_mount_setattr,
249+
fs_fd,
250+
path,
251+
flags,
252+
&attr.raw as *const linux_raw_sys::general::mount_attr,
253+
pass_usize(core::mem::size_of_val(&attr.raw))
254+
))
255+
}
256+
}

src/backend/linux_raw/mount/types.rs

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
use crate::ffi;
1+
use core::marker::PhantomData;
2+
23
use bitflags::bitflags;
34

5+
use crate::{
6+
fd::{AsRawFd, BorrowedFd},
7+
ffi,
8+
};
9+
410
bitflags! {
511
/// `MS_*` constants for use with [`mount`].
612
///
@@ -280,6 +286,105 @@ bitflags! {
280286
}
281287
}
282288

289+
bitflags! {
290+
/// `AT_*` flags accepted by [`mount_setattr`].
291+
///
292+
/// [`mount_setattr`]: crate::mount::mount_setattr
293+
#[repr(transparent)]
294+
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
295+
pub struct MountSetAttrFlags: ffi::c_uint {
296+
/// `AT_EMPTY_PATH`
297+
const AT_EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH;
298+
299+
/// `AT_RECURSIVE`
300+
const AT_RECURSIVE = linux_raw_sys::general::AT_RECURSIVE;
301+
302+
/// `AT_SYMLINK_NOFOLLOW`
303+
const AT_SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW;
304+
305+
/// `AT_NO_AUTOMOUNT`
306+
const AT_NO_AUTOMOUNT = linux_raw_sys::general::AT_NO_AUTOMOUNT;
307+
}
308+
}
309+
310+
/// `MOUNT_ATTR_*` flags that also carry a parameter.
311+
#[cfg(linux_kernel)]
312+
pub enum MountAttrParamFlags<'a> {
313+
/// `MOUNT_ATTR_IDMAP`, which carries the descriptor of a user namespace.
314+
IdMap(BorrowedFd<'a>),
315+
}
316+
317+
#[cfg(linux_kernel)]
318+
impl<'a> MountAttrParamFlags<'a> {
319+
fn apply(self, attr: MountAttr<'a>, operation: MountAttrOperation) -> MountAttr<'a> {
320+
let mut raw = attr.raw;
321+
let flags = match operation {
322+
MountAttrOperation::Set => &mut raw.attr_set,
323+
MountAttrOperation::Clear => &mut raw.attr_clr,
324+
};
325+
326+
match self {
327+
Self::IdMap(userns_fd) => {
328+
*flags |= MountAttrFlags::from_bits_retain(
329+
linux_raw_sys::general::MOUNT_ATTR_IDMAP as u32,
330+
)
331+
.bits() as u64;
332+
raw.userns_fd = userns_fd.as_raw_fd() as u64;
333+
}
334+
}
335+
336+
MountAttr {
337+
raw,
338+
userns_fd: PhantomData::<BorrowedFd<'a>>,
339+
}
340+
}
341+
}
342+
343+
/// `struct mount_attr`
344+
#[cfg(linux_kernel)]
345+
#[derive(Clone)]
346+
#[doc(alias = "mount_attr")]
347+
pub struct MountAttr<'a> {
348+
pub(crate) raw: linux_raw_sys::general::mount_attr,
349+
userns_fd: PhantomData<BorrowedFd<'a>>,
350+
}
351+
352+
#[cfg(linux_kernel)]
353+
impl<'a> MountAttr<'a> {
354+
/// Create a `MountAttr` with the given simple fields.
355+
pub fn new(
356+
attr_set: MountAttrFlags,
357+
attr_clr: MountAttrFlags,
358+
propagation: MountPropagationFlags,
359+
) -> Self {
360+
Self {
361+
raw: linux_raw_sys::general::mount_attr {
362+
attr_set: attr_set.bits() as u64,
363+
attr_clr: attr_clr.bits() as u64,
364+
propagation: propagation.bits() as u64,
365+
userns_fd: 0,
366+
},
367+
userns_fd: PhantomData,
368+
}
369+
}
370+
371+
/// Set a parameterized flag.
372+
pub fn set_param_flag(self, param: MountAttrParamFlags<'a>) -> Self {
373+
param.apply(self, MountAttrOperation::Set)
374+
}
375+
376+
/// Clear a parameterized flag.
377+
pub fn clear_param_flag(self, param: MountAttrParamFlags<'a>) -> Self {
378+
param.apply(self, MountAttrOperation::Clear)
379+
}
380+
}
381+
382+
#[cfg(linux_kernel)]
383+
enum MountAttrOperation {
384+
Set,
385+
Clear,
386+
}
387+
283388
bitflags! {
284389
/// `MS_*` constants for use with [`mount_change`].
285390
///

0 commit comments

Comments
 (0)