Skip to content

Commit 2d64e32

Browse files
bors[bot]djkoloski
andauthored
Merge #1979
1979: Make `*::from_anything` methods unsafe r=rtzoeller a=djkoloski The called function must uphold some invariants about initializing data in order for the calls to `from_anything` to be sound. Co-authored-by: David Koloski <[email protected]>
2 parents 15d624a + 5c3907f commit 2d64e32

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

src/unistd.rs

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,7 +3631,12 @@ impl From<User> for libc::passwd {
36313631

36323632
#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
36333633
impl User {
3634-
fn from_anything<F>(f: F) -> Result<Option<Self>>
3634+
/// # Safety
3635+
///
3636+
/// If `f` writes to its `*mut *mut libc::passwd` parameter, then it must
3637+
/// also initialize the value pointed to by its `*mut libc::group`
3638+
/// parameter.
3639+
unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
36353640
where
36363641
F: Fn(
36373642
*mut libc::passwd,
@@ -3661,7 +3666,9 @@ impl User {
36613666
if res.is_null() {
36623667
return Ok(None);
36633668
} else {
3664-
let pwd = unsafe { pwd.assume_init() };
3669+
// SAFETY: `f` guarantees that `pwd` is initialized if `res`
3670+
// is not null.
3671+
let pwd = pwd.assume_init();
36653672
return Ok(Some(User::from(&pwd)));
36663673
}
36673674
} else if Errno::last() == Errno::ERANGE {
@@ -3687,9 +3694,13 @@ impl User {
36873694
/// assert_eq!(res.name, "root");
36883695
/// ```
36893696
pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
3690-
User::from_anything(|pwd, cbuf, cap, res| unsafe {
3691-
libc::getpwuid_r(uid.0, pwd, cbuf, cap, res)
3692-
})
3697+
// SAFETY: `getpwuid_r` will write to `res` if it initializes the value
3698+
// at `pwd`.
3699+
unsafe {
3700+
User::from_anything(|pwd, cbuf, cap, res| {
3701+
libc::getpwuid_r(uid.0, pwd, cbuf, cap, res)
3702+
})
3703+
}
36933704
}
36943705

36953706
/// Get a user by name.
@@ -3710,9 +3721,13 @@ impl User {
37103721
Ok(c_str) => c_str,
37113722
Err(_nul_error) => return Ok(None),
37123723
};
3713-
User::from_anything(|pwd, cbuf, cap, res| unsafe {
3714-
libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res)
3715-
})
3724+
// SAFETY: `getpwnam_r` will write to `res` if it initializes the value
3725+
// at `pwd`.
3726+
unsafe {
3727+
User::from_anything(|pwd, cbuf, cap, res| {
3728+
libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res)
3729+
})
3730+
}
37163731
}
37173732
}
37183733

@@ -3763,7 +3778,12 @@ impl Group {
37633778
ret
37643779
}
37653780

3766-
fn from_anything<F>(f: F) -> Result<Option<Self>>
3781+
/// # Safety
3782+
///
3783+
/// If `f` writes to its `*mut *mut libc::group` parameter, then it must
3784+
/// also initialize the value pointed to by its `*mut libc::group`
3785+
/// parameter.
3786+
unsafe fn from_anything<F>(f: F) -> Result<Option<Self>>
37673787
where
37683788
F: Fn(
37693789
*mut libc::group,
@@ -3793,7 +3813,9 @@ impl Group {
37933813
if res.is_null() {
37943814
return Ok(None);
37953815
} else {
3796-
let grp = unsafe { grp.assume_init() };
3816+
// SAFETY: `f` guarantees that `grp` is initialized if `res`
3817+
// is not null.
3818+
let grp = grp.assume_init();
37973819
return Ok(Some(Group::from(&grp)));
37983820
}
37993821
} else if Errno::last() == Errno::ERANGE {
@@ -3821,9 +3843,13 @@ impl Group {
38213843
/// assert!(res.name == "root");
38223844
/// ```
38233845
pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
3824-
Group::from_anything(|grp, cbuf, cap, res| unsafe {
3825-
libc::getgrgid_r(gid.0, grp, cbuf, cap, res)
3826-
})
3846+
// SAFETY: `getgrgid_r` will write to `res` if it initializes the value
3847+
// at `grp`.
3848+
unsafe {
3849+
Group::from_anything(|grp, cbuf, cap, res| {
3850+
libc::getgrgid_r(gid.0, grp, cbuf, cap, res)
3851+
})
3852+
}
38273853
}
38283854

38293855
/// Get a group by name.
@@ -3846,9 +3872,13 @@ impl Group {
38463872
Ok(c_str) => c_str,
38473873
Err(_nul_error) => return Ok(None),
38483874
};
3849-
Group::from_anything(|grp, cbuf, cap, res| unsafe {
3850-
libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res)
3851-
})
3875+
// SAFETY: `getgrnam_r` will write to `res` if it initializes the value
3876+
// at `grp`.
3877+
unsafe {
3878+
Group::from_anything(|grp, cbuf, cap, res| {
3879+
libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res)
3880+
})
3881+
}
38523882
}
38533883
}
38543884
}

0 commit comments

Comments
 (0)