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
1 change: 0 additions & 1 deletion rust/Cargo.lock

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

54 changes: 44 additions & 10 deletions rust/agama-manager/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,18 @@ impl SetConfigAction {

match &product {
Some(product) => {
self.progress
.call(progress::message::Next::new(Scope::Manager))
.await?;
self.software
.call(software::message::SetConfig::new(
Arc::clone(product),
config.software.clone(),
))
.await?;

self.set_selinux().await?;

self.progress
.call(progress::message::Next::new(Scope::Manager))
.await?;
Expand All @@ -322,16 +334,6 @@ impl SetConfigAction {
config.bootloader.clone(),
))
.await?;

self.progress
.call(progress::message::Next::new(Scope::Manager))
.await?;
self.software
.call(software::message::SetConfig::new(
Arc::clone(product),
config.software.clone(),
))
.await?;
}

None => {
Expand All @@ -356,6 +358,38 @@ impl SetConfigAction {

Ok(())
}

// Enables/Disables SELinux in the installed system.
//
// If the "selinux" pattern is selected, set the "security=selinux" boot
// kernel parameter.
//
// NOTE: this logic should live in another place, like "agama-security".
// It is temporarily here to fix bsc#1259890.
async fn set_selinux(&self) -> Result<(), service::Error> {
let selinux_selected = self
.software
.call(software::message::IsPatternSelected::new(
"selinux".to_string(),
))
.await?;

let value = if selinux_selected {
"security=selinux"
} else {
"security="
};
let message = agama_bootloader::message::SetKernelArg {
id: "selinux".to_string(),
value: value.to_string(),
};

if let Err(error) = self.bootloader.cast(message) {
tracing::warn!("Failed to send to bootloader new selinux state: {error:?}");
}

Ok(())
}
}

/// Implements the finish action.
Expand Down
1 change: 0 additions & 1 deletion rust/agama-manager/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ impl Starter {
progress.clone(),
self.questions.clone(),
security.clone(),
bootloader.clone(),
)
.start()
.await?
Expand Down
1 change: 0 additions & 1 deletion rust/agama-software/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ rust-version.workspace = true
edition.workspace = true

[dependencies]
agama-bootloader = { path = "../agama-bootloader" }
agama-l10n = { path = "../agama-l10n" }
agama-utils = { path = "../agama-utils" }
agama-security = { path = "../agama-security" }
Expand Down
15 changes: 15 additions & 0 deletions rust/agama-software/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,18 @@ impl SetLocale {
impl Message for SetLocale {
type Reply = ();
}

#[derive(Clone)]
pub struct IsPatternSelected {
pub name: String,
}

impl Message for IsPatternSelected {
type Reply = bool;
}

impl IsPatternSelected {
pub fn new(name: String) -> Self {
Self { name }
}
}
51 changes: 21 additions & 30 deletions rust/agama-software/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use crate::{
zypp_server::{self, SoftwareAction, ZyppServer},
Model, ResolvableType,
};
use agama_bootloader;
use agama_security as security;
use agama_utils::{
actor::{self, Actor, Handler, MessageHandler},
Expand Down Expand Up @@ -92,7 +91,6 @@ pub struct Starter {
progress: Handler<progress::Service>,
questions: Handler<question::Service>,
security: Handler<security::Service>,
bootloader: Handler<agama_bootloader::Service>,
}

impl Starter {
Expand All @@ -102,7 +100,6 @@ impl Starter {
progress: Handler<progress::Service>,
questions: Handler<question::Service>,
security: Handler<security::Service>,
bootloader: Handler<agama_bootloader::Service>,
) -> Self {
Self {
model: None,
Expand All @@ -111,7 +108,6 @@ impl Starter {
progress,
questions,
security,
bootloader,
}
}

Expand Down Expand Up @@ -158,7 +154,6 @@ impl Starter {
progress: self.progress,
product: None,
kernel_cmdline,
bootloader: self.bootloader,
};
service.setup().await?;
Ok(actor::spawn(service))
Expand All @@ -181,7 +176,6 @@ pub struct Service {
product: Option<Arc<RwLock<ProductSpec>>>,
selection: SoftwareSelection,
kernel_cmdline: KernelCmdline,
bootloader: Handler<agama_bootloader::Service>,
}

#[derive(Default)]
Expand All @@ -199,9 +193,8 @@ impl Service {
progress: Handler<progress::Service>,
questions: Handler<question::Service>,
security: Handler<security::Service>,
bootloader: Handler<agama_bootloader::Service>,
) -> Starter {
Starter::new(events, issues, progress, questions, security, bootloader)
Starter::new(events, issues, progress, questions, security)
}

pub async fn setup(&mut self) -> Result<(), Error> {
Expand All @@ -217,26 +210,6 @@ impl Service {
Ok(())
}

fn update_selinux(&self, state: &SoftwareState) {
let selinux_selected = state.resolvables.to_vec().iter().any(|(name, typ, state)| {
typ == &ResolvableType::Pattern && name == "selinux" && state.selected()
});

let value = if selinux_selected {
"security=selinux"
} else {
"security="
};
let message = agama_bootloader::message::SetKernelArg {
id: "selinux".to_string(),
value: value.to_string(),
};
let res = self.bootloader.cast(message);
if res.is_err() {
tracing::warn!("Failed to send to bootloader new selinux state: {:?}", res);
}
}

/// Updates the proposal and the service state.
///
/// This function performs the following actions:
Expand All @@ -258,8 +231,6 @@ impl Service {
SoftwareState::build_from(&product, &state.config, &state.system, &self.selection)
};

self.update_selinux(&new_state);

tracing::info!("Wanted software state: {new_state:?}");
{
let mut state = self.state.write().await;
Expand Down Expand Up @@ -513,6 +484,26 @@ impl MessageHandler<message::SetLocale> for Service {
}
}

#[async_trait]
impl MessageHandler<message::IsPatternSelected> for Service {
async fn handle(&mut self, message: message::IsPatternSelected) -> Result<bool, Error> {
let state = self.state.read().await;
let Some(software_state) = &state.state else {
return Ok(false);
};

let selected = software_state
.resolvables
.to_vec()
.iter()
.any(|(name, typ, state)| {
typ == &ResolvableType::Pattern && name == &message.name && state.selected()
});

Ok(selected)
}
}

const LIVE_REPO_DIR: &str = "run/initramfs/live/install";
const DUD_REPO_DIR: &str = "var/lib/agama/dud/repo";

Expand Down
6 changes: 2 additions & 4 deletions rust/agama-software/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use agama_utils::{
},
issue,
products::ProductSpec,
progress, question, test,
progress, question,
};
use async_trait::async_trait;

Expand Down Expand Up @@ -90,9 +90,7 @@ pub async fn start_service(
questions: Handler<question::Service>,
) -> Handler<Service> {
let security = start_security_service(questions.clone()).await;
let dbus = test::dbus::connection().await.unwrap();
let bootloader = agama_bootloader::test_utils::start_service(issues.clone(), dbus).await;
Service::starter(events, issues, progress, questions, security, bootloader)
Service::starter(events, issues, progress, questions, security)
.with_model(TestModel {})
.start()
.await
Expand Down
5 changes: 5 additions & 0 deletions rust/package/agama.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
-------------------------------------------------------------------
Fri Mar 20 13:55:22 UTC 2026 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

- Enable SELinux if needed in unattended installations (bsc#1259890).

-------------------------------------------------------------------
Fri Mar 20 08:46:19 UTC 2026 - Knut Anderssen <kanderssen@suse.com>

Expand Down
Loading