commit 40554cc7d568214ecd497018ab9df9c6d9c69354
parent 94ff58f83ddc9d5c28983bcdf195cd484c23615a
Author: Zack Newman <zack@philomathiclife.com>
Date: Tue, 25 Feb 2025 07:59:12 -0700
rust 2024
Diffstat:
3 files changed, 48 insertions(+), 26 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -3,24 +3,21 @@ authors = ["Zack Newman <zack@philomathiclife.com>"]
categories = ["development-tools::ffi", "external-ffi-bindings", "os"]
description = "FFI for pledge(2) and unveil(2) on OpenBSD."
documentation = "https://docs.rs/priv_sep/latest/priv_sep/"
-edition = "2021"
+edition = "2024"
keywords = ["ffi", "openbsd", "privsep", "security"]
license = "MIT OR Apache-2.0"
name = "priv_sep"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/priv_sep/"
-rust-version = "1.81.0"
-version = "2.1.0"
-
-[badges]
-maintenance = { status = "actively-developed" }
+rust-version = "1.85.0"
+version = "2.2.0"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[target.'cfg(target_os = "openbsd")'.dependencies]
-libc = { version = "0.2.158", default-features = false, features = ["std"], optional = true }
+libc = { version = "0.2.170", default-features = false, features = ["std"], optional = true }
### FEATURES #################################################################
diff --git a/README.md b/README.md
@@ -1,5 +1,9 @@
# `priv_sep`
+[<img alt="git" src="https://git.philomathiclife.com/badges/priv_sep.svg" height="20">](https://git.philomathiclife.com/priv_sep/log.html)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/priv_sep.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/priv_sep)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-priv_sep-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/priv_sep/latest/priv_sep/)
+
`priv_sep` is a library for privilege separation.
It is currently designed around [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) and
[`unveil(2)`](https://man.openbsd.org/amd64/unveil.2) for OpenBSD, but
@@ -20,12 +24,25 @@ Calls to `unveil(2)` are done via `Permissions::unveil` and `unveil_no_more`.
Any error returned from the underlying system call is propagated via `Error`.
+## Minimum Supported Rust Version (MSRV)
+
+This will frequently be updated to be the same as stable. Specifically, any time stable is updated and that
+update has "useful" features or compilation no longer succeeds (e.g., due to new compiler lints), then MSRV
+will be updated.
+
+MSRV changes will correspond to a SemVer minor version bump.
+
+## SemVer Policy
+
+* All on-by-default features of this library are covered by SemVer
+* MSRV is considered exempt from SemVer as noted above
+
## License
Licensed under either of
-* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0).
-* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT).
+* Apache License, Version 2.0 ([LICENSE-APACHE](https://www.apache.org/licenses/LICENSE-2.0))
+* MIT license ([LICENSE-MIT](https://opensource.org/licenses/MIT))
at your option.
@@ -34,6 +51,10 @@ at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you,
as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
+Before any PR is sent, `cargo clippy` and `cargo t` should be run for both `--no-default-features` and
+`--all-features`. Additionally `RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features` should be run to
+ensure documentation can be built.
+
### Status
This package will be actively maintained to stay in-sync with the latest version of OpenBSD; as a result,
diff --git a/src/lib.rs b/src/lib.rs
@@ -1,4 +1,8 @@
-//! # `priv_sep`
+//! [![git]](https://git.philomathiclife.com/priv_sep/log.html) [![crates-io]](https://crates.io/crates/priv_sep) [![docs-rs]](crate)
+//!
+//! [git]: https://git.philomathiclife.com/git_badge.svg
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! `priv_sep` is a library for privilege separation.
//! It is currently designed around [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) and
@@ -47,22 +51,26 @@
)]
#![expect(
clippy::blanket_clippy_restriction_lints,
- clippy::doc_markdown,
reason = "same reason as below"
)]
#![cfg_attr(docsrs, doc(cfg(feature = "openbsd")))]
#![cfg(feature = "openbsd")]
#![expect(
+ clippy::arbitrary_source_item_ordering,
clippy::exhaustive_enums,
clippy::implicit_return,
clippy::min_ident_chars,
clippy::missing_trait_methods,
clippy::ref_patterns,
- clippy::single_char_lifetime_names,
clippy::unseparated_literal_suffix,
reason = "noisy, opinionated, and likely doesn't prevent bugs or improve APIs"
)]
extern crate alloc;
+use Promise::{
+ Audio, Bpf, Chown, Cpath, Disklabel, Dns, Dpath, Drm, Error, Exec, Fattr, Flock, Getpw, Id,
+ Inet, Mcast, Pf, Proc, ProtExec, Ps, Recvfd, Route, Rpath, Sendfd, Settime, Stdio, Tape,
+ Tmppath, Tty, Unix, Unveil, Video, Vminfo, Vmm, Wpath, Wroute,
+};
use alloc::ffi::{CString, NulError};
use core::{
convert::AsRef,
@@ -72,12 +80,7 @@ use core::{
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not},
ptr,
};
-use std::{io, os::unix::ffi::OsStrExt, path::Path};
-use Promise::{
- Audio, Bpf, Chown, Cpath, Disklabel, Dns, Dpath, Drm, Error, Exec, Fattr, Flock, Getpw, Id,
- Inet, Mcast, Pf, Proc, ProtExec, Ps, Recvfd, Route, Rpath, Sendfd, Settime, Stdio, Tape,
- Tmppath, Tty, Unix, Unveil, Video, Vminfo, Vmm, Wpath, Wroute,
-};
+use std::{io, os::unix::ffi::OsStrExt as _, path::Path};
/// A `promise` to [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2).
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
@@ -267,7 +270,7 @@ pub struct Promises(u64);
/// `pledge_none`.
#[expect(unsafe_code, reason = "FFI requires unsafe code")]
fn pledge(promises: *const c_char) -> Result<(), io::Error> {
- extern "C" {
+ unsafe extern "C" {
fn pledge(promises: *const c_char, execpromises: *const c_char) -> c_int;
}
// SAFETY:
@@ -497,7 +500,7 @@ impl Promises {
/// assert!(proms.len() == 1 && proms.contains(Promise::Rpath));
/// ```
#[inline]
- pub fn remove(&mut self, promise: Promise) {
+ pub const fn remove(&mut self, promise: Promise) {
self.0 &= !promise.to_u64();
}
/// Same as [`Self::remove`] then [`Self::pledge`]; however this is "atomic" in that if an error occurs from `pledge`,
@@ -718,7 +721,7 @@ pub fn pledge_none() -> Result<(), io::Error> {
/// `unveil_no_more`.
#[expect(unsafe_code, reason = "FFI requires unsafe code")]
fn unveil(path: *const c_char, permissions: *const c_char) -> Result<(), io::Error> {
- extern "C" {
+ unsafe extern "C" {
fn unveil(path: *const c_char, permissions: *const c_char) -> c_int;
}
// SAFETY:
@@ -802,7 +805,7 @@ impl Permissions {
/// assert_eq!(perms, Permissions::READ);
/// ```
#[inline]
- pub fn enable(&mut self, permission: Permission) {
+ pub const fn enable(&mut self, permission: Permission) {
self.0 |= permission.to_u8();
}
/// Disables `permission` in `self`.
@@ -822,7 +825,7 @@ impl Permissions {
/// assert!(perms.is_enabled(Permission::Create) && perms.is_enabled(Permission::Read) && perms.is_enabled(Permission::Write) && !perms.is_enabled(Permission::Execute));
/// ```
#[inline]
- pub fn disable(&mut self, permission: Permission) {
+ pub const fn disable(&mut self, permission: Permission) {
self.0 &= !permission.to_u8();
}
/// Returns `true` iff `self` has `permission` enabled.
@@ -959,7 +962,7 @@ impl BitAnd<&Permissions> for &Permissions {
*self & *rhs
}
}
-impl<'a> BitAnd<Permissions> for &'a Permissions {
+impl BitAnd<Permissions> for &Permissions {
type Output = Permissions;
#[inline]
fn bitand(self, rhs: Permissions) -> Self::Output {
@@ -999,7 +1002,7 @@ impl BitOr<&Permissions> for &Permissions {
*self | *rhs
}
}
-impl<'a> BitOr<Permissions> for &'a Permissions {
+impl BitOr<Permissions> for &Permissions {
type Output = Permissions;
#[inline]
fn bitor(self, rhs: Permissions) -> Self::Output {
@@ -1039,7 +1042,7 @@ impl BitXor<&Permissions> for &Permissions {
*self ^ *rhs
}
}
-impl<'a> BitXor<Permissions> for &'a Permissions {
+impl BitXor<Permissions> for &Permissions {
type Output = Permissions;
#[inline]
fn bitxor(self, rhs: Permissions) -> Self::Output {
@@ -1147,6 +1150,7 @@ mod tests {
// This tests that a NULL `promise` does nothing.
assert!(crate::pledge_none().is_ok());
print!("");
+ assert!(Promises::ALL.pledge().is_ok());
// This tests that duplicates are ignored as well as the implementation of PartialEq.
let mut initial_promises = Promises::new([
Promise::Stdio,