Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3228,16 +3228,23 @@ mod setres {
/// * returns: Ok or libc error code.
///
/// Err is returned if the user doesn't have permission to set this UID.
///
/// If one of the arguments equals None, the corresponding value is not changed.
#[inline]
pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
pub fn setresuid(ruid: Option<Uid>, euid: Option<Uid>, suid: Option<Uid>) -> Result<()> {
let ruid = ruid.map(Into::into).unwrap_or((0 as libc::uid_t).wrapping_sub(1));
let euid = euid.map(Into::into).unwrap_or((0 as libc::uid_t).wrapping_sub(1));
let suid = suid.map(Into::into).unwrap_or((0 as libc::uid_t).wrapping_sub(1));
let res =
unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
unsafe { libc::setresuid(ruid, euid, suid) };

Errno::result(res).map(drop)
}

/// Sets the real, effective, and saved gid.
/// ([see setresuid(2)](https://man7.org/linux/man-pages/man2/setresuid.2.html))
///
/// If one of the arguments equals None, the corresponding value is not changed.
/// ([see setresgid(2)](https://man7.org/linux/man-pages/man2/setresgid.2.html))
///
/// * `rgid`: real group id
/// * `egid`: effective group id
Expand All @@ -3246,9 +3253,12 @@ mod setres {
///
/// Err is returned if the user doesn't have permission to set this GID.
#[inline]
pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
pub fn setresgid(rgid: Option<Gid>, egid: Option<Gid>, sgid: Option<Gid>) -> Result<()> {
let rgid = rgid.map(Into::into).unwrap_or((0 as libc::gid_t).wrapping_sub(1));
let egid = egid.map(Into::into).unwrap_or((0 as libc::gid_t).wrapping_sub(1));
let sgid = sgid.map(Into::into).unwrap_or((0 as libc::gid_t).wrapping_sub(1));
let res =
unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
unsafe { libc::setresgid(rgid, egid, sgid) };

Errno::result(res).map(drop)
}
Expand Down
37 changes: 37 additions & 0 deletions test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1430,3 +1430,40 @@ fn test_group_from() {
assert_eq!(group.gid, group_id);
assert_eq!(group.name, "wheel");
}

// Tests for PR #1305: setresuid/setresgid with Option support
#[test]
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
fn test_setresuid_with_option() {
let uid = getuid();

// Test 1: Set all to current values
assert!(setresuid(Some(uid), Some(uid), Some(uid)).is_ok());
assert_eq!(geteuid(), uid);

// Test 2: No-change (None for all)
let euid_before = geteuid();
assert!(setresuid(None, None, None).is_ok());
assert_eq!(geteuid(), euid_before, "UID should not change with None");

// Test 3: Selective change (only effective)
assert!(setresuid(None, Some(uid), None).is_ok());
}

#[test]
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
fn test_setresgid_with_option() {
let gid = getgid();

// Test 1: Set all to current values
assert!(setresgid(Some(gid), Some(gid), Some(gid)).is_ok());
assert_eq!(getegid(), gid);

// Test 2: No-change (None for all)
let egid_before = getegid();
assert!(setresgid(None, None, None).is_ok());
assert_eq!(getegid(), egid_before, "GID should not change with None");

// Test 3: Selective change (only effective)
assert!(setresgid(None, Some(gid), None).is_ok());
}
Loading