fix: use pidfd for polkit auth if possible, patch zbus_polkit

This commit is contained in:
Ilya Zlobintsev committed 2026-08-28 22:59:50 +03:00
1 parent 6cbb8319da
commit 40dcf29841
5 files changed
+63 -26

No files matched your search

Generated
+1 -2
View File
@@ -4076,8 +4076,7 @@ dependencies = [
[[package]]
name = "zbus_polkit"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad23d5c4d198c7e2641b33e6e0d1f866f117408ba66fe80bbe52e289eeb77c52"
source = "git+https://github.com/ilya-zlobintsev/zbus_polkit?branch=fix-uid-type#cebdd40f9f91780816427922e6c8aa41b4d59e66"
dependencies = [
"enumflags2",
"serde",
+3
View File
@@ -62,3 +62,6 @@ strip = false
debug = 1
lto = "thin"
codegen-units = 256
[patch.crates-io]
zbus_polkit = { git = "https://github.com/ilya-zlobintsev/zbus_polkit", branch = "fix-uid-type" }
+21 -10
View File
@@ -5,6 +5,12 @@
"commit": "eb47417eede43443f139053479618e96ad32893d",
"dest": "flatpak-cargo/git/nvml-wrapper-eb47417"
},
{
"type": "git",
"url": "https://github.com/ilya-zlobintsev/zbus_polkit",
"commit": "cebdd40f9f91780816427922e6c8aa41b4d59e66",
"dest": "flatpak-cargo/git/zbus_polkit-cebdd40"
},
{
"type": "archive",
"archive-type": "tar-gzip",
@@ -2678,7 +2684,7 @@
},
{
"type": "inline",
"contents": "[package]\nname = \"nvml-wrapper\"\nversion = \"0.12.1\"\nauthors = [\"Cldfire\"]\ndescription = \"A safe and ergonomic Rust wrapper for the NVIDIA Management Library\"\nreadme = \"../README.md\"\ndocumentation = \"https://docs.rs/nvml-wrapper\"\nrepository = \"https://github.com/Cldfire/nvml-wrapper\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.60.0\"\nkeywords = [\"nvidia\", \"gpu\", \"managment\", \"monitoring\", \"hardware\"]\ncategories = [\"api-bindings\", \"hardware-support\"]\n\n[features]\ndefault = []\nlegacy-functions = [\"nvml-wrapper-sys/legacy-functions\"]\nserde = [\"dep:serde\", \"dep:serde_derive\", \"bitflags/serde\"]\n\n[dependencies]\nthiserror = \"1.0\"\nbitflags = \"2.4.0\"\nwrapcenum-derive = \"0.4.1\"\nlibloading = \"0.8.1\"\nstatic_assertions = \"1.1\"\n\n[dependencies.serde]\nversion = \"1.0\"\noptional = true\n\n[dependencies.serde_derive]\nversion = \"1.0\"\noptional = true\n\n[dependencies.nvml-wrapper-sys]\nversion = \"0.9.1\"\npath = \"../nvml-wrapper-sys\"\n\n[dev-dependencies]\npretty-bytes = \"0.2\"\n",
"contents": "[package]\nname = \"nvml-wrapper\"\nversion = \"0.12.1\"\nauthors = [ \"Cldfire\",]\ndescription = \"A safe and ergonomic Rust wrapper for the NVIDIA Management Library\"\nreadme = \"../README.md\"\ndocumentation = \"https://docs.rs/nvml-wrapper\"\nrepository = \"https://github.com/Cldfire/nvml-wrapper\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.60.0\"\nkeywords = [ \"nvidia\", \"gpu\", \"managment\", \"monitoring\", \"hardware\",]\ncategories = [ \"api-bindings\", \"hardware-support\",]\n\n[features]\ndefault = []\nlegacy-functions = [ \"nvml-wrapper-sys/legacy-functions\",]\nserde = [ \"dep:serde\", \"dep:serde_derive\", \"bitflags/serde\",]\n\n[dependencies]\nthiserror = \"1.0\"\nbitflags = \"2.4.0\"\nwrapcenum-derive = \"0.4.1\"\nlibloading = \"0.8.1\"\nstatic_assertions = \"1.1\"\n\n[dev-dependencies]\npretty-bytes = \"0.2\"\n\n[dependencies.serde]\nversion = \"1.0\"\noptional = true\n\n[dependencies.serde_derive]\nversion = \"1.0\"\noptional = true\n\n[dependencies.nvml-wrapper-sys]\nversion = \"0.9.1\"\npath = \"../nvml-wrapper-sys\"\n",
"dest": "cargo/vendor/nvml-wrapper",
"dest-filename": "Cargo.toml"
},
@@ -2696,7 +2702,7 @@
},
{
"type": "inline",
"contents": "[package]\nname = \"nvml-wrapper-sys\"\nversion = \"0.9.1\"\nauthors = [\"Cldfire\"]\ndescription = \"Generated bindings to the NVIDIA Management Library.\"\nreadme = \"README.md\"\ndocumentation = \"https://docs.rs/nvml-wrapper-sys\"\nrepository = \"https://github.com/Cldfire/nvml-wrapper\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.60.0\"\nkeywords = [\"nvidia\", \"gpu\", \"managment\", \"monitoring\", \"hardware\"]\ncategories = [\"external-ffi-bindings\", \"hardware-support\"]\nexclude = [\"nvml.h\"]\n\n[dependencies]\nlibloading = \"0.8.1\"\n\n[features]\ndefault = []\nlegacy-functions = []\n",
"contents": "[package]\nname = \"nvml-wrapper-sys\"\nversion = \"0.9.1\"\nauthors = [ \"Cldfire\",]\ndescription = \"Generated bindings to the NVIDIA Management Library.\"\nreadme = \"README.md\"\ndocumentation = \"https://docs.rs/nvml-wrapper-sys\"\nrepository = \"https://github.com/Cldfire/nvml-wrapper\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version = \"1.60.0\"\nkeywords = [ \"nvidia\", \"gpu\", \"managment\", \"monitoring\", \"hardware\",]\ncategories = [ \"external-ffi-bindings\", \"hardware-support\",]\nexclude = [ \"nvml.h\",]\n\n[dependencies]\nlibloading = \"0.8.1\"\n\n[features]\ndefault = []\nlegacy-functions = []\n",
"dest": "cargo/vendor/nvml-wrapper-sys",
"dest-filename": "Cargo.toml"
},
@@ -5229,16 +5235,21 @@
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/zbus_polkit/zbus_polkit-5.0.0.crate",
"sha256": "ad23d5c4d198c7e2641b33e6e0d1f866f117408ba66fe80bbe52e289eeb77c52",
"dest": "cargo/vendor/zbus_polkit-5.0.0"
"type": "shell",
"commands": [
"cp -r --reflink=auto \"flatpak-cargo/git/zbus_polkit-cebdd40/.\" \"cargo/vendor/zbus_polkit\""
]
},
{
"type": "inline",
"contents": "{\"package\": \"ad23d5c4d198c7e2641b33e6e0d1f866f117408ba66fe80bbe52e289eeb77c52\", \"files\": {}}",
"dest": "cargo/vendor/zbus_polkit-5.0.0",
"contents": "[package]\nname = \"zbus_polkit\"\nversion = \"5.0.0\"\nauthors = [ \"Marc-Andr\u00e9 Lureau <marcandre.lureau@redhat.com>\", \"Zeeshan Ali Khan <zeenix@gmail.com>\",]\nedition = \"2021\"\nrust-version = \"1.64\"\ndescription = \"PolicyKit binding\"\nrepository = \"https://github.com/z-galaxy/zbus_polkit/\"\nkeywords = [ \"D-Bus\", \"DBus\", \"IPC\",]\nlicense = \"MIT\"\ncategories = [ \"os::unix-apis\",]\nreadme = \"README.md\"\n\n[features]\ndefault = [ \"zbus/async-io\", \"blocking-api\",]\ntokio = [ \"zbus/tokio\",]\nblocking-api = [ \"zbus/blocking-api\",]\n\n[dependencies]\nserde_repr = \"0.1.19\"\nstatic_assertions = \"1.1.0\"\n\n[dev-dependencies]\nbyteorder = \"1.5.0\"\n\n[dependencies.zbus]\nversion = \"5.0.0\"\ndefault-features = false\n\n[dependencies.serde]\nversion = \"1.0.200\"\nfeatures = [ \"derive\",]\n\n[dependencies.enumflags2]\nversion = \"0.7.9\"\nfeatures = [ \"serde\",]\n\n[dev-dependencies.tokio]\nversion = \"1\"\nfeatures = [ \"macros\", \"rt\",]\n",
"dest": "cargo/vendor/zbus_polkit",
"dest-filename": "Cargo.toml"
},
{
"type": "inline",
"contents": "{\"package\": null, \"files\": {}}",
"dest": "cargo/vendor/zbus_polkit",
"dest-filename": ".cargo-checksum.json"
},
{
@@ -5399,7 +5410,7 @@
},
{
"type": "inline",
"contents": "[source.vendored-sources]\ndirectory = \"cargo/vendor\"\n\n[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.\"https://github.com/rust-nvml/nvml-wrapper\"]\ngit = \"https://github.com/rust-nvml/nvml-wrapper\"\nreplace-with = \"vendored-sources\"\nrev = \"eb47417eede43443f139053479618e96ad32893d\"\n",
"contents": "[source.vendored-sources]\ndirectory = \"cargo/vendor\"\n\n[source.crates-io]\nreplace-with = \"vendored-sources\"\n\n[source.\"https://github.com/rust-nvml/nvml-wrapper\"]\ngit = \"https://github.com/rust-nvml/nvml-wrapper\"\nreplace-with = \"vendored-sources\"\nrev = \"eb47417eede43443f139053479618e96ad32893d\"\n\n[source.\"https://github.com/ilya-zlobintsev/zbus_polkit\"]\ngit = \"https://github.com/ilya-zlobintsev/zbus_polkit\"\nreplace-with = \"vendored-sources\"\nbranch = \"fix-uid-type\"\n",
"dest": "cargo",
"dest-filename": "config"
}
+19 -8
View File
@@ -12,9 +12,12 @@ use crate::{config::Config, socket, system};
use anyhow::Context;
use futures::future::join_all;
use lact_schema::{Pong, Request, Response};
use nix::sys::socket::{getsockopt, sockopt::PeerCredentials};
use nix::sys::socket::{
getsockopt,
sockopt::{PeerCredentials, PeerPidfd},
};
use serde::Serialize;
use std::fmt::Debug;
use std::{fmt::Debug, os::fd::OwnedFd};
use tokio::{
io::{AsyncBufReadExt, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader},
net::{TcpListener, UnixListener},
@@ -79,9 +82,14 @@ impl Server {
.inspect_err(|err| warn!("could not get client credentials: {err:#}"))
.ok();
let pid_fd = getsockopt(&stream, PeerPidfd)
.inspect_err(|err| warn!("could not get client pidfd: {err:#}"))
.ok();
let ctx = ClientContext {
pid: client_credentials.map(|creds| creds.pid().cast_unsigned()),
uid: client_credentials.map(|creds| creds.uid()),
pid_fd,
};
let handler = unix_handler.clone();
tokio::task::spawn_local(async move {
@@ -125,10 +133,11 @@ impl Server {
}
}
#[derive(Clone, Copy, Debug, Default)]
#[derive(Debug, Default)]
pub(crate) struct ClientContext {
pub pid: Option<u32>,
pub uid: Option<u32>,
pub pid_fd: Option<OwnedFd>,
}
#[instrument(level = "debug", skip(stream, handler))]
@@ -147,10 +156,12 @@ pub async fn handle_stream<T: AsyncRead + AsyncWrite + Unpin>(
let maybe_request = serde_json::from_str(&buf);
let response = match maybe_request {
Ok(request) => match handle_request(request, &handler, &disconnect_notify, ctx).await {
Ok(response) => response,
Err(error) => serde_json::to_vec(&Response::<()>::from(error))?,
},
Ok(request) => {
match handle_request(request, &handler, &disconnect_notify, &ctx).await {
Ok(response) => response,
Err(error) => serde_json::to_vec(&Response::<()>::from(error))?,
}
}
Err(error) => serde_json::to_vec(&Response::<()>::from(
anyhow::Error::new(error).context("Failed to deserialize"),
))?,
@@ -172,7 +183,7 @@ async fn handle_request<'a>(
request: Request<'a>,
handler: &'a Handler,
disconnect_notify: &std::sync::Arc<Notify>,
ctx: ClientContext,
ctx: &ClientContext,
) -> anyhow::Result<Vec<u8>> {
match request {
Request::Ping => ok_response(ping()),
+19 -6
View File
@@ -41,7 +41,10 @@ use std::{
env,
fs::{self, File, Permissions},
io::{BufWriter, Cursor, Write},
os::unix::fs::{MetadataExt, PermissionsExt},
os::{
fd::AsFd as _,
unix::fs::{MetadataExt, PermissionsExt},
},
path::{Path, PathBuf},
rc::Rc,
sync::LazyLock,
@@ -55,6 +58,7 @@ use tokio::{
time::sleep,
};
use tracing::{debug, error, info, trace, warn};
use zbus::zvariant::Value as ZbusValue;
use zbus_polkit::policykit1::{self, AuthorityProxy};
const CONTROLLERS_LOAD_RETRY_ATTEMPTS: u8 = 5;
@@ -948,7 +952,7 @@ impl<'a> Handler {
&self,
name: String,
base: ProfileBase,
ctx: ClientContext,
ctx: &ClientContext,
) -> anyhow::Result<()> {
{
let mut config = self.config.write().await;
@@ -1043,7 +1047,7 @@ impl<'a> Handler {
name: &str,
rule: Option<ProfileRule>,
hooks: ProfileHooks,
ctx: ClientContext,
ctx: &ClientContext,
) -> anyhow::Result<()> {
if !hooks.is_empty() {
self.check_auth(
@@ -1275,16 +1279,25 @@ impl<'a> Handler {
&self,
action: &str,
error_msg: &str,
ctx: ClientContext,
ctx: &ClientContext,
) -> anyhow::Result<()> {
let polkit_proxy = self
.polkit_proxy
.as_ref()
.context("Polkit not available, cannot ask for authorization")?;
let pid = ctx.pid.context("No client PID available")?;
let uid = ctx.uid.context("No client UID available")?;
let subject = policykit1::Subject::new_for_owner(pid, None, Some(uid))?;
let pid = ctx.pid.context("No client PID available")?;
let mut subject = policykit1::Subject::new_for_owner(pid, None, Some(uid))?;
if let Some(pid_fd) = &ctx.pid_fd {
subject.subject_details.insert(
"pidfd".to_owned(),
ZbusValue::Fd(pid_fd.as_fd().into()).try_into()?,
);
}
let result = polkit_proxy
.check_authorization(
&subject,