Skip to content

Commit

Permalink
Added try_clone to RulsetCreated. This enables the sharing of a paren…
Browse files Browse the repository at this point in the history
…t ruleset that can be passed to multiple/threads without the

need to reconstruct the a ruleset.

Signed-off-by: Mickaël Salaün <mic@digikod.net>
  • Loading branch information
int5-grey committed Mar 21, 2024
1 parent 89797a0 commit 18ce04d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ fn compat_state_update_2() {
}

#[cfg_attr(test, derive(Debug, PartialEq))]
#[derive(Clone)]
#[derive(Copy, Clone)]
pub(crate) struct Compatibility {
abi: ABI,
pub(crate) level: Option<CompatLevel>,
Expand Down
20 changes: 20 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,4 +343,24 @@ mod tests {
false,
);
}

#[test]
fn ruleset_created_try_clone() {
check_ruleset_support(
ABI::V1,
Some(ABI::V1),
move |ruleset: Ruleset| -> _ {
Ok(ruleset
.handle_access(AccessFs::Execute)?
.create()?
.add_rule(PathBeneath::new(
PathFd::new("/usr").unwrap(),
AccessFs::Execute,
))?
.try_clone()?
.restrict_self()?)
},
false,
);
}
}
30 changes: 30 additions & 0 deletions src/ruleset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,36 @@ impl RulesetCreated {
};
Ok(body()?)
}

/// Creates a copy of this object and duplicates the file descriptor with
/// CLOEXEC set. The `RulesetCreated` object that is produced is intended
/// to be a readonly copy of the original object, however this
/// is not currently supported by the landlock kernel module. The intention
/// behind this method is to provide a way to keep a parent ruleset intact so
/// it can be applied to any number of new processes or threads without
/// creating the object over and over.
///
/// Any modification of the underlying ruleset changes will alter both
/// the new RulesetCreated and the original.
///
/// On error, returns [`std::io::Error`].
pub fn try_clone(&self) -> Result<Self, std::io::Error> {
let mut dup_fd = -1;

if self.fd != -1 {
dup_fd = unsafe { libc::fcntl(self.fd, libc::F_DUPFD_CLOEXEC, 0) };
if dup_fd == -1 {
return Err(Error::last_os_error());
}
}

Ok(RulesetCreated {
fd: dup_fd,
no_new_privs: self.no_new_privs,
requested_handled_fs: self.requested_handled_fs,
compat: self.compat,
})
}
}

impl Drop for RulesetCreated {
Expand Down

0 comments on commit 18ce04d

Please sign in to comment.