diff options
Diffstat (limited to 'oxish')
| -rw-r--r-- | oxish/src/authentication.rs | 14 | ||||
| -rw-r--r-- | oxish/src/server.rs | 3 |
2 files changed, 17 insertions, 0 deletions
diff --git a/oxish/src/authentication.rs b/oxish/src/authentication.rs index 8e0613c..4eaa504 100644 --- a/oxish/src/authentication.rs +++ b/oxish/src/authentication.rs @@ -266,6 +266,7 @@ impl DefaultStore { /// Construct a new [`DefaultStore`] from the current process's effective UID #[expect(clippy::new_ret_no_self)] pub fn new(provider: &dyn CryptoProvider) -> Result<Box<dyn UserStore>, Error> { + // SAFETY: `geteuid()` takes no arguments, cannot fail and has no preconditions. Ok(match unsafe { libc::geteuid() } { 0 => Box::new(SystemStore) as Box<dyn UserStore>, uid => { @@ -372,6 +373,7 @@ impl User { /// Upper bound on the buffer used to hold the passwd entry const MAX_BUF_LEN: usize = 1_048_576; + // SAFETY: `sysconf()` only reads its integer argument and has no other preconditions. let buf_len = match unsafe { sysconf(_SC_GETPW_R_SIZE_MAX) } { -1 => 1024, n => (n as usize).clamp(1024, MAX_BUF_LEN), @@ -385,6 +387,8 @@ impl User { }; let mut buf = vec![0u8; buf_len]; + // SAFETY: `passwd` is a plain C struct of integers and pointers, for which + // all-zeros (including null pointers) is a valid bit pattern. let mut pwd = unsafe { core::mem::zeroed() }; let mut result = core::ptr::null_mut(); @@ -394,6 +398,9 @@ impl User { let ret = loop { let ret = match (&by, &c_name) { (UserLookup::Name(_), Some(c_name)) => unsafe { + // SAFETY: `c_name` is a valid null-terminated C string, `pwd` and `result` are + // valid for writes, and the buffer pointer and length describe the live + // allocation in `buf`. getpwnam_r( c_name.as_ptr(), &mut pwd, @@ -403,6 +410,8 @@ impl User { ) }, (UserLookup::Id(id), _) => unsafe { + // SAFETY: `pwd` and `result` are valid for writes, and the buffer pointer + // and length describe the live allocation in `buf`. getpwuid_r( *id, &mut pwd, @@ -426,6 +435,8 @@ impl User { let name = match by { UserLookup::Name(name) => name, UserLookup::Id(_) => match (ret, result.is_null()) { + // SAFETY: `ret` is 0 and `result` is non-null, so the `pwd.pw_name` points to a + // null-terminated C string stored in `buf`, which is still alive. (0, false) => Username::try_from(unsafe { CStr::from_ptr(pwd.pw_name) })?, _ => Username::nobody(), }, @@ -476,8 +487,11 @@ impl User { )); // An empty `pw_shell` means the system default shell. + // SAFETY: `shell` is a valid pointer to a null-terminated C string, + // per the same reasoning as for `home_dir` above. let shell = match unsafe { CStr::from_ptr(shell) }.to_bytes() { b"" => PathBuf::from(OsStr::from_bytes( + // SAFETY: `DEFAULT_SHELL` points to a static null-terminated C string literal. unsafe { CStr::from_ptr(Self::DEFAULT_SHELL) }.to_bytes(), )), bytes => PathBuf::from(OsStr::from_bytes(bytes)), diff --git a/oxish/src/server.rs b/oxish/src/server.rs index 8d76a7d..2a0a472 100644 --- a/oxish/src/server.rs +++ b/oxish/src/server.rs @@ -243,6 +243,9 @@ impl Server { let mut groups = vec![0; count as usize]; loop { #[allow(trivial_numeric_casts)] // platform dependent + // SAFETY: `name` is a valid null-terminated C string, and `groups` and `count` + // describe a live allocation with capacity for `count` entries; `count` is valid + // for writes. let ret = unsafe { libc::getgrouplist( name.as_ptr(), |
