1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

chroot: improve support of --skip-chdir

Should unbreak tests/misc/chroot-fail.sh
This commit is contained in:
Sylvestre Ledru 2022-09-30 17:33:52 -10:00
parent d6ca61c279
commit d768b19f2b
2 changed files with 45 additions and 15 deletions

View file

@ -16,7 +16,8 @@ use std::io::Error;
use std::os::unix::prelude::OsStrExt; use std::os::unix::prelude::OsStrExt;
use std::path::Path; use std::path::Path;
use std::process; use std::process;
use uucore::error::{set_exit_code, UClapError, UResult}; use uucore::error::{set_exit_code, UClapError, UResult, UUsageError};
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
use uucore::libc::{self, chroot, setgid, setgroups, setuid}; use uucore::libc::{self, chroot, setgid, setgroups, setuid};
use uucore::{entries, format_usage}; use uucore::{entries, format_usage};
@ -48,6 +49,20 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
None => return Err(ChrootError::MissingNewRoot.into()), None => return Err(ChrootError::MissingNewRoot.into()),
}; };
let skip_chdir = matches.contains_id(options::SKIP_CHDIR);
// We are resolving the path in case it is a symlink or /. or /../
if skip_chdir
&& canonicalize(newroot, MissingHandling::Normal, ResolveMode::Logical)
.unwrap()
.to_str()
!= Some("/")
{
return Err(UUsageError::new(
125,
"option --skip-chdir only permitted if NEWROOT is old '/'",
));
}
if !newroot.is_dir() { if !newroot.is_dir() {
return Err(ChrootError::NoSuchDirectory(format!("{}", newroot.display())).into()); return Err(ChrootError::NoSuchDirectory(format!("{}", newroot.display())).into());
} }

View file

@ -1,4 +1,4 @@
// spell-checker:ignore (words) araba newroot userspec chdir pwd's // spell-checker:ignore (words) araba newroot userspec chdir pwd's isroot
use crate::common::util::*; use crate::common::util::*;
@ -145,22 +145,37 @@ fn test_chroot() {
} }
} }
#[test]
fn test_chroot_skip_chdir_not_root() {
let (at, mut ucmd) = at_and_ucmd!();
let dir = "foobar";
at.mkdir(dir);
ucmd.arg("--skip-chdir")
.arg(dir)
.fails()
.stderr_contains("chroot: option --skip-chdir only permitted if NEWROOT is old '/'")
.code_is(125);
}
#[test] #[test]
fn test_chroot_skip_chdir() { fn test_chroot_skip_chdir() {
let ts = TestScenario::new(util_name!()); let ts = TestScenario::new(util_name!());
let at = &ts.fixtures; let at = ts.fixtures.clone();
let dirs = ["/", "/.", "/..", "isroot"];
let dir = "CHROOT_DIR"; at.symlink_file("/", "isroot");
at.mkdir(dir); for dir in dirs {
let env_cd = std::env::current_dir().unwrap(); let env_cd = std::env::current_dir().unwrap();
if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "--skip-chdir", "pwd"]) { if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "--skip-chdir"]) {
// Should return the same path // Should return the same path
assert_eq!( assert_eq!(
result.success().no_stderr().stdout_str(), result.success().no_stderr().stdout_str(),
env_cd.to_str().unwrap() env_cd.to_str().unwrap()
); );
} else { } else {
print!("Test skipped; requires root user"); print!("Test skipped; requires root user");
}
} }
} }