Skip to content
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
10 changes: 10 additions & 0 deletions rust/agama-software/src/model/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ impl<'a> SoftwareStateBuilder<'a> {
ResolvableType::Package,
ResolvableSelection::AutoSelected { optional: false },
);

// FIPS enabled, so add fips pattern
if self.kernel_cmdline.get_last("fips") == Some("1".to_string()) {
tracing::info!("fips detected, adding fips pattern");
state.resolvables.add_or_replace(
"fips",
ResolvableType::Pattern,
ResolvableSelection::AutoSelected { optional: false },
);
}
}

/// Adds the elements from the user configuration.
Expand Down
66 changes: 58 additions & 8 deletions rust/agama-utils/src/kernel_cmdline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,28 @@

use std::{collections::HashMap, path::Path};

const CMDLINE_FILE: &str = "/run/agama/cmdline.d/agama.conf";
const AGAMA_CMDLINE_FILE: &str = "/run/agama/cmdline.d/agama.conf";
const KERNEL_CMDLINE_FILE: &str = "/run/agama/cmdline.d/kernel.conf";

/// Implements a mechanism to read the kernel's command-line arguments.
///
/// It supports multiple values for a single key.
/// It supports multiple values for a single key. Keys are case-insensitive.
#[derive(Default)]
pub struct KernelCmdline(HashMap<String, Vec<String>>);

impl KernelCmdline {
/// Parses the command-line.
///
/// The content of the command-line is stored, by default, in the {CMDLINE_FILE}.
/// The content of the command-line is stored, by default it is combination of agama and kernel cmdline args.
pub fn parse() -> std::io::Result<Self> {
Self::parse_file(CMDLINE_FILE)
.inspect_err(|e| tracing::warn!("Could not parse the kernel command-line: {e}"))
let agama = Self::parse_file(AGAMA_CMDLINE_FILE).inspect_err(|e| {
tracing::warn!("Could not parse the agama kernel command-line: {e}")
})?;
let kernel = Self::parse_file(KERNEL_CMDLINE_FILE).inspect_err(|e| {
tracing::warn!("Could not parse the filtered kernel command-line: {e}")
})?;

Ok(agama.merge(kernel))
}

/// Builds an instance from the given file.
Expand All @@ -57,23 +64,35 @@ impl KernelCmdline {
.map(|(k, v)| (k, v))
.unwrap_or_else(|| (param, "1"));

args.entry(key.to_string())
args.entry(key.to_lowercase())
.and_modify(|v| v.push(value.to_string()))
.or_insert(vec![value.to_string()]);
}
Self(args)
}

pub fn merge(self, other: Self) -> Self {
let mut args = self.0;
for (key, value) in other.0 {
args.entry(key)
// this modify is just for theoretical correctness as in reality we are merging kernel and agama
// args and they are exclusive
.and_modify(|v| v.extend(value.clone()))
.or_insert(value);
}
Self(args)
}

/// Returns the values for the argument.
///
/// * `name`: argument name.
pub fn get(&self, name: &str) -> Vec<String> {
self.0.get(name).cloned().unwrap_or(vec![])
self.0.get(&name.to_lowercase()).cloned().unwrap_or(vec![])
}

/// Returns the last value for the argument
pub fn get_last(&self, name: &str) -> Option<String> {
let values = self.0.get(name)?;
let values = self.0.get(&name.to_lowercase())?;
values.last().cloned()
}
}
Expand Down Expand Up @@ -102,4 +121,35 @@ mod tests {

assert_eq!(args.get_last("inst.auto_insecure"), Some("0".to_string()));
}

#[test]
fn test_cmdline_args_case_insensitive() {
let args_str = r"Inst.Auto=file:///profile.json RD.NEEDNET";
let args = KernelCmdline::parse_str(args_str);

assert_eq!(
args.get_last("inst.auto"),
Some("file:///profile.json".to_string())
);
assert_eq!(
args.get_last("INST.AUTO"),
Some("file:///profile.json".to_string())
);
assert_eq!(args.get("rd.neednet"), vec!["1".to_string()]);
}

#[test]
fn test_merge() {
let cmdline1 = KernelCmdline::parse_str("key1=val1 key2=val2");
let cmdline2 = KernelCmdline::parse_str("key2=val3 key3=val4");

let merged = cmdline1.merge(cmdline2);

assert_eq!(merged.get("key1"), vec!["val1".to_string()]);
assert_eq!(
merged.get("key2"),
vec!["val2".to_string(), "val3".to_string()]
);
assert_eq!(merged.get("key3"), vec!["val4".to_string()]);
}
}
6 changes: 6 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Fri Feb 20 09:35:01 UTC 2026 - Josef Reidinger <jreidinger@suse.com>

- Properly mark fips pattern for installation when fips kernel
parameter is used (bsc#1258306)

-------------------------------------------------------------------
Thu Feb 19 16:42:12 UTC 2026 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
Loading