Skip to content

Commit ac75ff7

Browse files
committed
coreutils: Protect against env -a for security
1 parent 1f4a976 commit ac75ff7

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ wc = { optional = true, version = "0.6.0", package = "uu_wc", path = "src/uu/wc"
539539
who = { optional = true, version = "0.6.0", package = "uu_who", path = "src/uu/who" }
540540
whoami = { optional = true, version = "0.6.0", package = "uu_whoami", path = "src/uu/whoami" }
541541
yes = { optional = true, version = "0.6.0", package = "uu_yes", path = "src/uu/yes" }
542+
libc.workspace = true
542543

543544
# this breaks clippy linting with: "tests/by-util/test_factor_benches.rs: No such file or directory (os error 2)"
544545
# factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }

src/bin/coreutils.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6+
// spell-checker:ignore getauxval EXECFN
7+
68
use clap::Command;
79
use coreutils::validation;
810
use itertools::Itertools as _;
@@ -45,8 +47,24 @@ fn main() {
4547
let utils = util_map();
4648
let mut args = uucore::args_os();
4749

50+
#[cfg(any(target_os = "linux", target_os = "android"))]
51+
// protect against env -a
52+
let binary = {
53+
use std::ffi::{CStr, OsString};
54+
use std::os::unix::ffi::OsStringExt;
55+
let p: *const libc::c_char = unsafe { libc::getauxval(libc::AT_EXECFN) as _ };
56+
if p.is_null() {
57+
let _ = writeln!(io::stderr(), "getauxval failed");
58+
process::exit(1);
59+
}
60+
let _ = args.next();
61+
let n = unsafe { CStr::from_ptr(p) };
62+
OsString::from_vec(n.to_bytes().to_vec())
63+
};
64+
#[cfg(not(any(target_os = "linux", target_os = "android")))]
4865
let binary = validation::binary_path(&mut args);
49-
let binary_as_util = validation::name(&binary).unwrap_or_else(|| {
66+
67+
let binary_as_util = validation::name(binary.as_ref()).unwrap_or_else(|| {
5068
usage(&utils, "<unknown binary name>");
5169
process::exit(0);
5270
});
@@ -55,8 +73,12 @@ fn main() {
5573
let is_coreutils = binary_as_util.ends_with("utils");
5674
let matched_util = utils
5775
.keys()
76+
//*utils is not ls
5877
.filter(|&&u| binary_as_util.ends_with(u) && !is_coreutils)
59-
.max_by_key(|u| u.len()); //Prefer stty more than tty. *utils is not ls
78+
//Prefer stty more than tty
79+
.max_by_key(|u| u.len())
80+
// todo: with coreutils -> ls -> blah symlink chain, blah calls ls
81+
;
6082

6183
let util_name = if let Some(&util) = matched_util {
6284
Some(OsString::from(util))

tests/by-util/test_env.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,11 @@ fn test_env_with_empty_executable_double_quotes() {
722722
}
723723

724724
#[test]
725-
#[cfg(all(unix, feature = "dirname", feature = "echo"))]
725+
#[cfg(all(
726+
all(unix, feature = "dirname", feature = "echo"),
727+
not(any(target_os = "linux", target_os = "android"))
728+
))]
729+
// protected against hijack at Linux
726730
fn test_env_overwrite_arg0() {
727731
let ts = TestScenario::new(util_name!());
728732

@@ -746,7 +750,11 @@ fn test_env_overwrite_arg0() {
746750
}
747751

748752
#[test]
749-
#[cfg(all(unix, feature = "echo"))]
753+
#[cfg(all(
754+
all(unix, feature = "echo"),
755+
not(any(target_os = "linux", target_os = "android"))
756+
))]
757+
// protected against hijack at Linux
750758
fn test_env_arg_argv0_overwrite() {
751759
let ts = TestScenario::new(util_name!());
752760

@@ -794,7 +802,11 @@ fn test_env_arg_argv0_overwrite() {
794802
}
795803

796804
#[test]
797-
#[cfg(all(unix, feature = "echo"))]
805+
#[cfg(all(
806+
all(unix, feature = "echo"),
807+
not(any(target_os = "linux", target_os = "android"))
808+
))]
809+
// protected against hijack at Linux
798810
fn test_env_arg_argv0_overwrite_mixed_with_string_args() {
799811
let ts = TestScenario::new(util_name!());
800812

0 commit comments

Comments
 (0)