Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 2 additions & 2 deletions src/uu/chroot/src/chroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::os::unix::prelude::OsStrExt;
use std::os::unix::process::CommandExt;
use std::path::{Path, PathBuf};
use std::process;
use uucore::entries::{Locate, Passwd, grp2gid, usr2uid};
use uucore::entries::{Locate, Passwd, grp2gid, usr2gid, usr2uid};
use uucore::error::{UResult, UUsageError};
use uucore::fs::{MissingHandling, ResolveMode, canonicalize};
use uucore::libc::{self, chroot, setgid, setgroups, setuid};
Expand Down Expand Up @@ -401,7 +401,7 @@ fn set_context(options: &Options) -> UResult<()> {
}
Some(UserSpec::UserOnly(user)) => {
let uid = name_to_uid(user)?;
let gid = uid as libc::gid_t;
let gid = usr2gid(user).map_err(|_| ChrootError::NoGroupSpecified(uid))?;
let strategy = Strategy::FromUID(uid, false);
set_supplemental_gids_with_strategy(strategy, options.groups.as_ref())?;
set_gid(gid).map_err(|e| ChrootError::SetGidFailed(user.to_owned(), e))?;
Expand Down
5 changes: 5 additions & 0 deletions src/uucore/src/lib/features/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,11 @@ pub fn usr2uid(name: &str) -> IOResult<uid_t> {
Passwd::locate(name).map(|p| p.uid)
}

#[inline]
pub fn usr2gid(name: &str) -> IOResult<gid_t> {
Passwd::locate(name).map(|p| p.gid)
}

#[inline]
pub fn grp2gid(name: &str) -> IOResult<gid_t> {
Group::locate(name).map(|p| p.gid)
Expand Down
25 changes: 25 additions & 0 deletions tests/by-util/test_chroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,28 @@ fn test_chroot_extra_arg() {
print!("Test skipped; requires root user");
}
}

#[test]
fn test_chroot_userspec_does_not_set_gid_with_uid() {
use uucore::entries::{usr2gid, usr2uid};

let ts = TestScenario::new(util_name!());
if let Ok(uid) = usr2uid("sync") {
if let Ok(gid) = usr2gid("sync") {
if gid == uid {
println!("Test skipped; requires sync user to have uid != gid");
return;
}
// Ubuntu has a sync user whose gid is 65534 per default
if let Ok(result) = run_ucmd_as_root(&ts, &["--userspec=sync", "/", "id", "-g"]) {
result.success().no_stderr().stdout_is(format!("{gid}\n"));
} else {
println!("Test skipped; requires root user");
}
} else {
println!("Test skipped; requires 'sync' user");
}
} else {
println!("Test skipped; requires 'sync' user");
}
}
Loading