Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lint: Add a sysusers lint #1111

Merged
merged 10 commits into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ members = [
"blockdev",
"xtask",
"tests-integration",
"tmpfiles"
"tmpfiles",
"sysusers",
]
resolver = "2"

Expand Down
7 changes: 7 additions & 0 deletions hack/provision-derived.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@ d /var/roothome/buildinfo/content_manifests 0755 - - -
f /var/roothome/buildinfo/content_manifests/content-sets.json 0644 - - -
EOF
fi

# And add missing sysusers.d entries
if ! grep -q -r sudo /usr/lib/sysusers.d; then
cat >/usr/lib/sysusers.d/bootc-sudo-workaround.conf <<'EOF'
g sudo 16
EOF
fi
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ anyhow = { workspace = true }
bootc-utils = { path = "../utils" }
bootc-blockdev = { path = "../blockdev" }
bootc-tmpfiles = { path = "../tmpfiles" }
bootc-sysusers = { path = "../sysusers" }
camino = { workspace = true, features = ["serde1"] }
ostree-ext = { path = "../ostree-ext", features = ["bootc"] }
chrono = { workspace = true, features = ["serde"] }
Expand Down
53 changes: 52 additions & 1 deletion lib/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::fmt::Write as WriteFmt;
use std::os::unix::ffi::OsStrExt;

use anyhow::Result;
use bootc_utils::PathQuotedDisplay;
use camino::{Utf8Path, Utf8PathBuf};
use cap_std::fs::Dir;
use cap_std_ext::cap_std;
Expand Down Expand Up @@ -505,8 +506,58 @@ fn check_var_tmpfiles(_root: &Dir) -> LintResult {
bootc_utils::iterator_split_nonempty_rest_count(r.unsupported.iter(), 5)
{
msg.push_str("Found non-directory/non-symlink files in /var:\n");
for elt in samples.map(PathQuotedDisplay::new) {
writeln!(msg, " {elt}")?;
}
if rest > 0 {
writeln!(msg, " ...and {} more", rest)?;
}
}
lint_err(msg)
}

#[distributed_slice(LINTS)]
static LINT_SYSUSERS: Lint = Lint {
name: "sysusers",
ty: LintType::Warning,
description: indoc! { r#"
Check for users in /etc/passwd and groups in /etc/group that do not have corresponding
systemd sysusers.d entries in /usr/lib/sysusers.d.
This can cause a problem across upgrades because if /etc is not transient and is locally
modified (commonly due to local user additions), then the contents of /etc/passwd in the new container
image may not be visible.

Using systemd-sysusers to allocate users and groups will ensure that these are allocated
on system startup alongside other users.

More on this topic in <https://containers.github.io/bootc/building/users-and-groups.html>
"#},
f: check_sysusers,
root_type: None,
};
fn check_sysusers(rootfs: &Dir) -> LintResult {
let r = bootc_sysusers::analyze(rootfs)?;
if r.is_empty() {
return lint_ok();
}
let mut msg = String::new();
if let Some((samples, rest)) =
bootc_utils::iterator_split_nonempty_rest_count(r.missing_users.iter(), 5)
{
msg.push_str("Found /etc/passwd entry without corresponding systemd sysusers.d:\n");
for elt in samples {
writeln!(msg, " {elt:?}")?;
writeln!(msg, " {elt}")?;
}
if rest > 0 {
writeln!(msg, " ...and {} more", rest)?;
}
}
if let Some((samples, rest)) =
bootc_utils::iterator_split_nonempty_rest_count(r.missing_groups.iter(), 5)
{
msg.push_str("Found /etc/group entry without corresponding systemd sysusers.d:\n");
for elt in samples {
writeln!(msg, " {elt}")?;
}
if rest > 0 {
writeln!(msg, " ...and {} more", rest)?;
Expand Down
25 changes: 25 additions & 0 deletions sysusers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "bootc-sysusers"
version = "0.1.0"
license = "MIT OR Apache-2.0"
edition = "2021"
publish = false

[dependencies]
anyhow = { workspace = true }
camino = { workspace = true }
fn-error-context = { workspace = true }
cap-std-ext = { version = "4", features = ["fs_utf8"] }
hex = "0.4"
thiserror = { workspace = true }
tempfile = { workspace = true }
bootc-utils = { path = "../utils" }
rustix = { workspace = true }
uzers = "0.12"

[dev-dependencies]
indoc = { workspace = true }
similar-asserts = { workspace = true }

[lints]
workspace = true
Loading