From 0baa689f62998d84e653a785a9edea827d3ba8cf Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 19 May 2026 02:57:56 +0100 Subject: [PATCH 1/3] fix: correct feature flag name for SELinux context test --- tests/by-util/test_mv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index c836d3c0e1e..9fbc7c574e2 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -2617,7 +2617,7 @@ fn test_mv_cross_device_permission_denied() { } #[test] -#[cfg(feature = "selinux")] +#[cfg(feature = "feat_selinux")] fn test_mv_selinux_context() { let test_cases = [ ("-Z", None), From 864b023ee94fc462c564fc3892cc1940c77b53a9 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 19 May 2026 03:12:41 +0100 Subject: [PATCH 2/3] fix(tests): refine feature checks for SELinux --- tests/by-util/test_chcon.rs | 5 +++- tests/by-util/test_cp.rs | 50 ++++++++++++++++++++++++++++------- tests/by-util/test_id.rs | 5 +++- tests/by-util/test_install.rs | 20 +++++++++++--- tests/by-util/test_ls.rs | 35 +++++++++++++++++++----- tests/by-util/test_mkdir.rs | 15 ++++++++--- tests/by-util/test_mkfifo.rs | 15 ++++++++--- tests/by-util/test_mknod.rs | 20 +++++++++++--- tests/by-util/test_mv.rs | 10 +++++-- tests/by-util/test_runcon.rs | 15 ++++++++--- tests/by-util/test_stat.rs | 5 +++- 11 files changed, 156 insertions(+), 39 deletions(-) diff --git a/tests/by-util/test_chcon.rs b/tests/by-util/test_chcon.rs index 12c8c6e85ba..f90bbdb0c78 100644 --- a/tests/by-util/test_chcon.rs +++ b/tests/by-util/test_chcon.rs @@ -4,7 +4,10 @@ // file that was distributed with this source code. // spell-checker:ignore (jargon) xattributes #![allow(clippy::missing_errors_doc, clippy::similar_names)] -#![cfg(feature = "feat_selinux")] +#![cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use std::ffi::CString; use std::path::Path; diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index f0ec1d68c65..8a178d1725d 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -8,7 +8,10 @@ #[cfg(unix)] use rstest::rstest; use uucore::display::Quotable; -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; use uutests::util::TestScenario; use uutests::{at_and_ucmd, new_ucmd, path_concat, util_name}; @@ -6771,7 +6774,10 @@ fn test_cp_from_stream_permission() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_selinux() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -6820,7 +6826,10 @@ fn test_cp_selinux_invalid() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_preserve_selinux() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -6858,7 +6867,10 @@ fn test_cp_preserve_selinux() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_preserve_selinux_admin_context() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -6917,7 +6929,10 @@ fn test_cp_preserve_selinux_admin_context() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_selinux_context_priority() { // This test verifies that -Z takes priority over --context @@ -6997,7 +7012,10 @@ fn test_cp_selinux_context_priority() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_selinux_empty_context() { // This test verifies that --context without a value works like -Z @@ -7043,7 +7061,10 @@ fn test_cp_selinux_empty_context() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_selinux_recursive() { // Test SELinux context preservation in recursive directory copies @@ -7097,7 +7118,10 @@ fn test_cp_selinux_recursive() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_preserve_context_root() { use uutests::util::run_ucmd_as_root; let scene = TestScenario::new(util_name!()); @@ -7800,7 +7824,10 @@ fn test_cp_gnu_preserve_mode() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_a_z_overrides_context() { // Verifies -aZ succeeds (-Z overrides implicit --preserve=context from -a) use std::path::Path; @@ -7818,7 +7845,10 @@ fn test_cp_a_z_overrides_context() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_cp_a_preserves_context() { use std::path::Path; use uucore::selinux::{get_selinux_security_context, set_selinux_security_context}; diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index dd2b9779924..1a30b75c91c 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -383,7 +383,10 @@ fn test_id_zero() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_id_context() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); diff --git a/tests/by-util/test_install.rs b/tests/by-util/test_install.rs index afb10eaa250..ec1c0e07a17 100644 --- a/tests/by-util/test_install.rs +++ b/tests/by-util/test_install.rs @@ -15,7 +15,10 @@ use std::process; #[cfg(any(target_os = "linux", target_os = "android"))] use std::thread::sleep; use uucore::process::{getegid, geteuid}; -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; use uutests::at_and_ucmd; use uutests::new_ucmd; @@ -2334,7 +2337,10 @@ fn test_install_no_target_basic() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_selinux() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -2383,7 +2389,10 @@ fn test_selinux() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_selinux_invalid_args() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -2416,7 +2425,10 @@ fn test_selinux_invalid_args() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_selinux_default_context() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 0893c3ffb68..0370e9201cc 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -4656,7 +4656,10 @@ fn test_ls_dangling_symlinks() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_context1() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); @@ -4671,7 +4674,10 @@ fn test_ls_context1() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_context2() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); @@ -4687,7 +4693,10 @@ fn test_ls_context2() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_context_long() { if !uucore::selinux::is_selinux_enabled() { return; @@ -4706,7 +4715,10 @@ fn test_ls_context_long() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_context_format() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); @@ -4736,7 +4748,10 @@ fn test_ls_context_format() { } /// Helper function to validate `SELinux` context format -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn validate_selinux_context(context: &str) { assert!( context.contains(':'), @@ -4751,7 +4766,10 @@ fn validate_selinux_context(context: &str) { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_selinux_context_format() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); @@ -4784,7 +4802,10 @@ fn test_ls_selinux_context_format() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_ls_selinux_context_indicator() { if !uucore::selinux::is_selinux_enabled() { println!("test skipped: Kernel has no support for SElinux context"); diff --git a/tests/by-util/test_mkdir.rs b/tests/by-util/test_mkdir.rs index fb919ac0ad8..17c12422534 100644 --- a/tests/by-util/test_mkdir.rs +++ b/tests/by-util/test_mkdir.rs @@ -11,7 +11,10 @@ use libc::mode_t; #[cfg(not(windows))] use std::os::unix::fs::PermissionsExt; -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; #[cfg(not(windows))] use uutests::at_and_ucmd; @@ -449,7 +452,10 @@ fn test_empty_argument() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_selinux() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -473,7 +479,10 @@ fn test_selinux() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_selinux_invalid() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; diff --git a/tests/by-util/test_mkfifo.rs b/tests/by-util/test_mkfifo.rs index 4d19da636a2..02fa91b2a52 100644 --- a/tests/by-util/test_mkfifo.rs +++ b/tests/by-util/test_mkfifo.rs @@ -5,7 +5,10 @@ // spell-checker:ignore nconfined -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; use uutests::new_ucmd; use uutests::util::TestScenario; @@ -167,7 +170,10 @@ fn test_create_fifo_permission_denied() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mkfifo_selinux() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -191,7 +197,10 @@ fn test_mkfifo_selinux() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mkfifo_selinux_invalid() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; diff --git a/tests/by-util/test_mknod.rs b/tests/by-util/test_mknod.rs index 1bcae7ea31a..a19a4e4d785 100644 --- a/tests/by-util/test_mknod.rs +++ b/tests/by-util/test_mknod.rs @@ -7,7 +7,10 @@ use std::os::unix::fs::PermissionsExt; -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; use uutests::new_ucmd; use uutests::util::TestScenario; @@ -184,7 +187,10 @@ fn test_mknod_mode_comma_separated() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mknod_selinux() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -215,7 +221,10 @@ fn test_mknod_selinux() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mknod_selinux_invalid() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -242,7 +251,10 @@ fn test_mknod_selinux_invalid() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mknod_selinux_invalid_cleanup() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index 9fbc7c574e2..a8cb184af85 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -10,7 +10,10 @@ use rstest::rstest; use std::io::Write; #[cfg(not(windows))] use std::path::Path; -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uucore::selinux::get_getfattr_output; use uutests::new_ucmd; #[cfg(unix)] @@ -2617,7 +2620,10 @@ fn test_mv_cross_device_permission_denied() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_mv_selinux_context() { let test_cases = [ ("-Z", None), diff --git a/tests/by-util/test_runcon.rs b/tests/by-util/test_runcon.rs index 39a73d8832e..3d85b8f7b2a 100644 --- a/tests/by-util/test_runcon.rs +++ b/tests/by-util/test_runcon.rs @@ -4,7 +4,10 @@ // file that was distributed with this source code. // spell-checker:ignore (jargon) xattributes -#![cfg(feature = "feat_selinux")] +#![cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] use uutests::new_ucmd; @@ -84,7 +87,10 @@ fn invalid() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn plain_context() { let ctx = "unconfined_u:unconfined_r:unconfined_t:s0-s0"; new_ucmd!().args(&[ctx, "/bin/true"]).succeeds(); @@ -103,7 +109,10 @@ fn plain_context() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn custom_context() { let t_ud = "unconfined_t"; let u_ud = "unconfined_u"; diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index c536a7744f7..d73dcf9b80e 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -550,7 +550,10 @@ fn test_printf_invalid_directive() { } #[test] -#[cfg(feature = "feat_selinux")] +#[cfg(all( + feature = "feat_selinux", + any(target_os = "linux", target_os = "android") +))] fn test_stat_selinux() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; From e4b141c45839cba4a873da519b743a04468c3a6f Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Tue, 19 May 2026 03:40:59 +0100 Subject: [PATCH 3/3] cargo: move SELinux dependency to target-specific section --- Cargo.toml | 2 +- src/uu/cp/Cargo.toml | 4 +++- src/uu/id/Cargo.toml | 4 +++- src/uu/install/Cargo.toml | 4 +++- src/uu/ls/Cargo.toml | 4 +++- src/uucore/Cargo.toml | 4 +++- 6 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 37f40ad8bdd..25af7527a1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -564,7 +564,6 @@ itertools.workspace = true jiff = { workspace = true, optional = true } phf.workspace = true regex = { workspace = true, optional = true } -selinux = { workspace = true, optional = true } textwrap.workspace = true uucore.workspace = true zip = { workspace = true, optional = true } @@ -714,6 +713,7 @@ rstest_reuse.workspace = true [target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] rustix.workspace = true +selinux = { workspace = true, optional = true } # this breaks clippy linting with: "tests/by-util/test_factor_benches.rs: No such file or directory (os error 2)" # factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" } diff --git a/src/uu/cp/Cargo.toml b/src/uu/cp/Cargo.toml index a184ee887b4..1d248b9e936 100644 --- a/src/uu/cp/Cargo.toml +++ b/src/uu/cp/Cargo.toml @@ -22,7 +22,6 @@ doctest = false clap = { workspace = true } filetime = { workspace = true } libc = { workspace = true } -selinux = { workspace = true, optional = true } uucore = { workspace = true, features = [ "backup-control", "buf-copy", @@ -41,6 +40,9 @@ thiserror = { workspace = true } fluent = { workspace = true } rustix = { workspace = true } +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +selinux = { workspace = true, optional = true } + [target.'cfg(unix)'.dependencies] exacl = { workspace = true, optional = true } nix = { workspace = true, features = ["fs"] } diff --git a/src/uu/id/Cargo.toml b/src/uu/id/Cargo.toml index 7fcdc64c001..3890aadc944 100644 --- a/src/uu/id/Cargo.toml +++ b/src/uu/id/Cargo.toml @@ -23,9 +23,11 @@ doctest = false clap = { workspace = true } rustix = { workspace = true } uucore = { workspace = true, features = ["entries", "process"] } -selinux = { workspace = true, optional = true } fluent = { workspace = true } +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +selinux = { workspace = true, optional = true } + [[bin]] name = "id" path = "src/main.rs" diff --git a/src/uu/install/Cargo.toml b/src/uu/install/Cargo.toml index 229fd06b466..d4f8b52bffb 100644 --- a/src/uu/install/Cargo.toml +++ b/src/uu/install/Cargo.toml @@ -21,7 +21,6 @@ path = "src/install.rs" clap = { workspace = true } filetime = { workspace = true } file_diff = { workspace = true } -selinux = { workspace = true, optional = true } thiserror = { workspace = true } uucore = { workspace = true, default-features = true, features = [ "backup-control", @@ -34,6 +33,9 @@ uucore = { workspace = true, default-features = true, features = [ ] } fluent = { workspace = true } +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +selinux = { workspace = true, optional = true } + [features] selinux = ["dep:selinux", "uucore/selinux"] diff --git a/src/uu/ls/Cargo.toml b/src/uu/ls/Cargo.toml index dfe7f21107e..260743a1f9b 100644 --- a/src/uu/ls/Cargo.toml +++ b/src/uu/ls/Cargo.toml @@ -26,7 +26,6 @@ clap = { workspace = true, features = ["env"] } glob = { workspace = true } lscolors = { workspace = true } rustc-hash = { workspace = true } -selinux = { workspace = true, optional = true } terminal_size = { workspace = true } thiserror = { workspace = true } uucore = { workspace = true, features = [ @@ -45,6 +44,9 @@ uucore = { workspace = true, features = [ uutils_term_grid = { workspace = true } fluent = { workspace = true } +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +selinux = { workspace = true, optional = true } + # hostname crate does not support WASI (no OS-level hostname API) [target.'cfg(not(target_os = "wasi"))'.dependencies] hostname = { workspace = true } diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index da2c1b90397..c34d5fae0e8 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -67,7 +67,6 @@ sm3 = { workspace = true, optional = true } crc-fast = { workspace = true, optional = true, features = ["std"] } bigdecimal = { workspace = true, optional = true } num-traits = { workspace = true, optional = true } -selinux = { workspace = true, optional = true } # icu stuff icu_calendar = { workspace = true, optional = true, features = [ @@ -95,6 +94,9 @@ thiserror = { workspace = true } [dev-dependencies] tempfile = { workspace = true } +[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies] +selinux = { workspace = true, optional = true } + [target.'cfg(unix)'.dependencies] nix = { workspace = true, features = [ "dir",