diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 80d03e257..9abfcaa81 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -13,8 +13,8 @@ env: PROJECT_NAME: coreutils PROJECT_DESC: "Core universal (cross-platform) utilities" PROJECT_AUTH: "uutils" - RUST_MIN_SRV: "1.51.0" ## v1.51.0 - RUST_COV_SRV: "1.51.0" ## supported rust version for code coverage; (date required/used by 'coverage') ## !maint: refactor when code coverage support is included in the stable channel + RUST_MIN_SRV: "1.51.0" ## MSRV v1.51.0 + RUST_COV_SRV: "2020-07-01" ## (~v1.47.0) supported rust version for code coverage; (date required/used by 'coverage') ## !maint: refactor when code coverage support is included in the stable channel on: [push, pull_request] @@ -249,6 +249,8 @@ jobs: # { os, target, cargo-options, features, use-cross, toolchain } - { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , features: feat_os_unix_gnueabihf , use-cross: use-cross } - { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf , use-cross: use-cross } + - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } + # - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross } # - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only # - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only - { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } @@ -272,7 +274,9 @@ jobs: esac case '${{ matrix.job.os }}' in macos-latest) brew install coreutils ;; # needed for testing - ubuntu-latest) sudo apt-get -y update ; sudo apt-get -y install libselinux1 libselinux1-dev ;; # TODO: probably redundant here + esac + case '${{ matrix.job.features }}' in + feat_selinux) sudo apt-get -y update ; sudo apt-get -y install libselinux1-dev ;; # TODO: is here the right place for this? esac - name: Initialize workflow variables id: vars diff --git a/Cargo.toml b/Cargo.toml index d11b57bfe..c588f735e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -146,6 +146,7 @@ feat_os_unix_musl = [ feat_require_crate_cpp = [ "stdbuf", ] +feat_selinux = ["id/selinux", "selinux"] # "feat_require_unix" == set of utilities requiring support which is only available on unix platforms (as of 2020-04-23) feat_require_unix = [ "chgrp", @@ -229,6 +230,7 @@ clap = { version = "2.33", features = ["wrap_help"] } lazy_static = { version="1.3" } textwrap = { version="=0.11.0", features=["term_size"] } # !maint: [2020-05-10; rivy] unstable crate using undocumented features; pinned currently, will review uucore = { version=">=0.0.9", package="uucore", path="src/uucore" } +selinux = { version="0.1.1", optional = true } # * uutils uu_test = { optional=true, version="0.0.7", package="uu_test", path="src/uu/test" } # @@ -353,7 +355,6 @@ unindent = "0.1" uucore = { version=">=0.0.9", package="uucore", path="src/uucore", features=["entries", "process"] } walkdir = "2.2" atty = "0.2" -selinux = "0.1.1" [target.'cfg(unix)'.dev-dependencies] rlimit = "0.4.0" diff --git a/build.rs b/build.rs index e9fe129eb..4fbb27cce 100644 --- a/build.rs +++ b/build.rs @@ -28,8 +28,8 @@ pub fn main() { if val == "1" && key.starts_with(env_feature_prefix) { let krate = key[env_feature_prefix.len()..].to_lowercase(); match krate.as_ref() { - "default" | "macos" | "unix" | "windows" => continue, // common/standard feature names - "nightly" | "test_unimplemented" => continue, // crate-local custom features + "default" | "macos" | "unix" | "windows" | "selinux" => continue, // common/standard feature names + "nightly" | "test_unimplemented" => continue, // crate-local custom features "test" => continue, // over-ridden with 'uu_test' to avoid collision with rust core crate 'test' s if s.starts_with(feature_prefix) => continue, // crate feature sets _ => {} // util feature name diff --git a/src/uu/id/Cargo.toml b/src/uu/id/Cargo.toml index 5a99c8431..b82c0e0f0 100644 --- a/src/uu/id/Cargo.toml +++ b/src/uu/id/Cargo.toml @@ -18,8 +18,11 @@ path = "src/id.rs" clap = { version = "2.33", features = ["wrap_help"] } uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "process"] } uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" } -selinux = "0.1.1" +selinux = { version="0.1.1", optional = true } [[bin]] name = "id" path = "src/main.rs" + +[features] +feat_selinux = ["selinux"] diff --git a/src/uu/id/src/id.rs b/src/uu/id/src/id.rs index b220bfdba..ce44b513d 100644 --- a/src/uu/id/src/id.rs +++ b/src/uu/id/src/id.rs @@ -35,8 +35,8 @@ extern crate uucore; use clap::{crate_version, App, Arg}; -#[cfg(target_os = "linux")] -use selinux::{self, KernelSupport, SecurityContext}; +#[cfg(all(target_os = "linux", feature = "selinux"))] +use selinux; use std::ffi::CStr; use uucore::entries::{self, Group, Locate, Passwd}; pub use uucore::libc; @@ -52,6 +52,11 @@ macro_rules! cstr2cow { static ABOUT: &str = "Print user and group information for each specified USER, or (when USER omitted) for the current user."; +#[cfg(not(feature = "selinux"))] +static CONTEXT_HELP_TEXT: &str = "print only the security context of the process (not enabled)"; +#[cfg(feature = "selinux")] +static CONTEXT_HELP_TEXT: &str = "print only the security context of the process"; + mod options { pub const OPT_AUDIT: &str = "audit"; // GNU's id does not have this pub const OPT_CONTEXT: &str = "context"; @@ -138,10 +143,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 { zflag: matches.is_present(options::OPT_ZERO), cflag: matches.is_present(options::OPT_CONTEXT), - #[cfg(not(target_os = "linux"))] - selinux_supported: false, - #[cfg(target_os = "linux")] - selinux_supported: selinux::kernel_support() != KernelSupport::Unsupported, + selinux_supported: { + #[cfg(feature = "selinux")] + { + selinux::kernel_support() != selinux::KernelSupport::Unsupported + } + #[cfg(not(feature = "selinux"))] + { + false + } + }, user_specified: !users.is_empty(), ids: None, }; @@ -181,8 +192,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { if state.cflag { if state.selinux_supported { // print SElinux context and exit - #[cfg(target_os = "linux")] - if let Ok(context) = SecurityContext::current(false) { + #[cfg(all(target_os = "linux", feature = "selinux"))] + if let Ok(context) = selinux::SecurityContext::current(false) { let bytes = context.as_bytes(); print!("{}{}", String::from_utf8_lossy(bytes), line_ending); } else { @@ -412,7 +423,7 @@ pub fn uu_app() -> App<'static, 'static> { .short("Z") .long(options::OPT_CONTEXT) .conflicts_with_all(&[options::OPT_GROUP, options::OPT_EFFECTIVE_USER]) - .help("print only the security context of the process"), + .help(CONTEXT_HELP_TEXT), ) .arg( Arg::with_name(options::ARG_USERS) @@ -555,13 +566,13 @@ fn id_print(state: &State, groups: Vec) { .join(",") ); - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", feature = "selinux"))] if state.selinux_supported && !state.user_specified && std::env::var_os("POSIXLY_CORRECT").is_none() { // print SElinux context (does not depend on "-Z") - if let Ok(context) = SecurityContext::current(false) { + if let Ok(context) = selinux::SecurityContext::current(false) { let bytes = context.as_bytes(); print!(" context={}", String::from_utf8_lossy(bytes)); } diff --git a/tests/by-util/test_id.rs b/tests/by-util/test_id.rs index eeb12f28b..c6e67a923 100644 --- a/tests/by-util/test_id.rs +++ b/tests/by-util/test_id.rs @@ -17,6 +17,17 @@ fn test_id_no_specified_user() { let exp_result = unwrap_or_return!(expected_result(&ts, &[])); let mut _exp_stdout = exp_result.stdout_str().to_string(); + #[cfg(not(feature = "feat_selinux"))] + { + // NOTE: strip 'context' part from exp_stdout if selinux not enabled: + // example: + // uid=1001(runner) gid=121(docker) groups=121(docker),4(adm),101(systemd-journal) \ + // context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 + if let Some(context_offset) = exp_result.stdout_str().find(" context=") { + _exp_stdout.replace_range(context_offset.._exp_stdout.len() - 1, ""); + } + } + result .stdout_is(_exp_stdout) .stderr_is(exp_result.stderr_str()) @@ -354,7 +365,7 @@ fn test_id_zero() { } #[test] -#[cfg(target_os = "linux")] +#[cfg(feature = "feat_selinux")] fn test_id_context() { use selinux::{self, KernelSupport}; if selinux::kernel_support() == KernelSupport::Unsupported { @@ -423,7 +434,7 @@ fn test_id_no_specified_user_posixly() { let result = ts.ucmd().env("POSIXLY_CORRECT", "1").succeeds(); assert!(!result.stdout_str().contains("context=")); - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", feature = "feat_selinux"))] { use selinux::{self, KernelSupport}; if selinux::kernel_support() == KernelSupport::Unsupported {