diff --git a/rust/src/builtins/scriptlet_intercept/groupadd.rs b/rust/src/builtins/scriptlet_intercept/groupadd.rs index e00e503ced..a8071f584e 100644 --- a/rust/src/builtins/scriptlet_intercept/groupadd.rs +++ b/rust/src/builtins/scriptlet_intercept/groupadd.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use cap_std::fs::{Dir, Permissions}; use cap_std_ext::prelude::CapStdExtDirExt; use clap::{Arg, Command}; @@ -13,6 +13,13 @@ use std::os::unix::prelude::PermissionsExt; pub(crate) fn entrypoint(args: &[&str]) -> Result<()> { fail::fail_point!("intercept_groupadd_ok", |_| Ok(())); + // Extract the package name from rpm-ostree/bwrap environment. + // This also works as a sanity check to ensure we are running in + // the context of a scriptlet. + static SCRIPT_PKG_VAR: &str = "RPMOSTREE_SCRIPT_PKG_NAME"; + let pkgname = std::env::var(SCRIPT_PKG_VAR) + .with_context(|| format!("Failed to access {SCRIPT_PKG_VAR} environment variable"))?; + // This parses the same CLI surface as the real `groupadd`, // but in the end we only extract the group name and (if // present) the static GID. @@ -29,7 +36,7 @@ pub(crate) fn entrypoint(args: &[&str]) -> Result<()> { } let rootdir = Dir::open_ambient_dir("/", cap_std::ambient_authority())?; - generate_sysusers_fragment(&rootdir, groupname, gid)?; + generate_sysusers_fragment(&rootdir, &pkgname, groupname, gid)?; Ok(()) } @@ -77,12 +84,17 @@ fn cli_cmd() -> Command<'static> { /// /// This returns whether a new fragment has been actually written /// to disk. -fn generate_sysusers_fragment(rootdir: &Dir, groupname: &str, gid: Option) -> Result { +fn generate_sysusers_fragment( + rootdir: &Dir, + pkgname: &str, + groupname: &str, + gid: Option, +) -> Result { static SYSUSERS_DIR: &str = "usr/lib/sysusers.d"; // The filename of the configuration fragment is in fact a public // API, because users may have masked it in /etc. Do not change this. - let filename = format!("30-pkg-group-{groupname}.conf"); + let filename = format!("30-pkg-{pkgname}-group-{groupname}.conf"); rootdir.create_dir_all(SYSUSERS_DIR)?; let conf_dir = rootdir.open_dir(SYSUSERS_DIR)?; @@ -146,10 +158,10 @@ mod test { ("bar", None, true, "-"), ]; for entry in groups { - let generated = generate_sysusers_fragment(&tmpdir, entry.0, entry.1).unwrap(); + let generated = generate_sysusers_fragment(&tmpdir, "foo", entry.0, entry.1).unwrap(); assert_eq!(generated, entry.2, "{:?}", entry); - let path = format!("usr/lib/sysusers.d/30-pkg-group-{}.conf", entry.0); + let path = format!("usr/lib/sysusers.d/30-pkg-foo-group-{}.conf", entry.0); assert!(tmpdir.is_file(&path)); let mut fragment = tmpdir.open(&path).unwrap(); diff --git a/src/libpriv/rpmostree-scripts.cxx b/src/libpriv/rpmostree-scripts.cxx index edbfdd4758..83d6f512a5 100644 --- a/src/libpriv/rpmostree-scripts.cxx +++ b/src/libpriv/rpmostree-scripts.cxx @@ -309,6 +309,9 @@ rpmostree_run_script_in_bwrap_container (int rootfs_fd, GLnxTmpDir *var_lib_rpm_ int provided_stdin_fd, GCancellable *cancellable, GError **error) { + g_assert (name != NULL); + g_assert (name[0] != '\0'); + const char *pkg_script = scriptdesc ? glnx_strjoina (name, ".", scriptdesc + 1) : name; // A dance just to pass a well-known fd for /dev/null to bwrap as fd 3 @@ -370,6 +373,8 @@ rpmostree_run_script_in_bwrap_container (int rootfs_fd, GLnxTmpDir *var_lib_rpm_ if (bridge_sysusers != NULL) bwrap->setenv ("RPMOSTREE_EXP_BRIDGE_SYSUSERS", rust::String (bridge_sysusers)); + bwrap->setenv ("RPMOSTREE_SCRIPT_PKG_NAME", name); + /* https://github.com/systemd/systemd/pull/7631 AKA * "systemctl,verbs: Introduce SYSTEMD_OFFLINE environment variable" * https://github.com/systemd/systemd/commit/f38951a62837a00a0b1ff42d007e9396b347742d