From 53ada31d748476701d7f704c884f0e40a708d826 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 24 Jul 2024 17:55:54 +0200 Subject: [PATCH] xwayland: disable direct libei access --- src/config/handler.rs | 1 + src/forker.rs | 25 ++++++++++++++-------- src/xwayland.rs | 48 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/config/handler.rs b/src/config/handler.rs index 905af050..a21fcea9 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1300,6 +1300,7 @@ impl ConfigProxyHandler { Some(f) => f, _ => return Err(CphError::NoForker), }; + let env = env.into_iter().map(|(k, v)| (k, Some(v))).collect(); forker.spawn(prog.to_string(), args, env, fds); Ok(()) } diff --git a/src/forker.rs b/src/forker.rs index 0067198d..3d6a3508 100644 --- a/src/forker.rs +++ b/src/forker.rs @@ -3,7 +3,7 @@ mod io; use { crate::{ async_engine::{AsyncEngine, SpawnedFuture}, - compositor::{DISPLAY, WAYLAND_DISPLAY}, + compositor::{DISPLAY, LIBEI_SOCKET, WAYLAND_DISPLAY}, forker::io::{IoIn, IoOut}, io_uring::IoUring, state::State, @@ -151,14 +151,18 @@ impl ForkerProxy { pub async fn xwayland( &self, + state: &State, stderr: Rc, dfd: Rc, listenfd: Rc, wmfd: Rc, waylandfd: Rc, ) -> Result<(Rc, c::pid_t), ForkerError> { - let (prog, args) = xwayland::build_args(); - let env = vec![("WAYLAND_SOCKET".to_string(), "6".to_string())]; + let (prog, args) = xwayland::build_args(state, self).await; + let env = vec![ + ("WAYLAND_SOCKET".to_string(), Some("6".to_string())), + (LIBEI_SOCKET.to_string(), None), + ]; let fds = vec![ (2, stderr), (3, dfd), @@ -175,7 +179,7 @@ impl ForkerProxy { &self, prog: String, args: Vec, - env: Vec<(String, String)>, + env: Vec<(String, Option)>, fds: Vec<(i32, Rc)>, ) { self.spawn_(prog, args, env, fds, None) @@ -185,7 +189,7 @@ impl ForkerProxy { &self, prog: String, args: Vec, - env: Vec<(String, String)>, + env: Vec<(String, Option)>, fds: Vec<(i32, Rc)>, pidfd_id: Option, ) { @@ -291,7 +295,7 @@ enum ServerMessage { Spawn { prog: String, args: Vec, - env: Vec<(String, String)>, + env: Vec<(String, Option)>, fds: Vec, pidfd_id: Option, }, @@ -408,7 +412,7 @@ impl Forker { self: &Rc, prog: String, args: Vec, - env: Vec<(String, String)>, + env: Vec<(String, Option)>, fds: Vec, io: &mut IoIn, pidfd_id: Option, @@ -424,7 +428,7 @@ impl Forker { self: &Rc, prog: String, args: Vec, - env: Vec<(String, String)>, + env: Vec<(String, Option)>, fds: Vec<(i32, OwnedFd)>, pidfd_id: Option, ) { @@ -502,7 +506,10 @@ impl Forker { c::signal(c::SIGCHLD, c::SIG_DFL); } for (key, val) in env { - env::set_var(&key, &val); + match val { + None => env::remove_var(&key), + Some(val) => env::set_var(&key, &val), + } } let prog = prog.into_ustr(); let mut argsnt = UstrPtr::new(); diff --git a/src/xwayland.rs b/src/xwayland.rs index 7b11d972..bd2e1d6a 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -14,7 +14,7 @@ use { io_uring::IoUringError, state::State, user_session::import_environment, - utils::{errorfmt::ErrorFmt, line_logger::log_lines, oserror::OsError}, + utils::{buf::Buf, errorfmt::ErrorFmt, line_logger::log_lines, oserror::OsError}, wire::WlSurfaceId, xcon::XconError, xwayland::{ @@ -153,6 +153,7 @@ async fn run( let stderr_read = state.eng.spawn(log_xwayland(state.clone(), stderr_read)); let pidfd = forker .xwayland( + &state, Rc::new(stderr_write), Rc::new(dfdwrite), socket, @@ -195,9 +196,12 @@ async fn run( Ok(()) } -pub fn build_args() -> (String, Vec) { - let prog = "Xwayland".to_string(); - let args = vec![ +const PROG: &str = "Xwayland"; +const ENABLE_EI_PORTAL: &str = "-enable-ei-portal"; + +pub async fn build_args(state: &State, forker: &ForkerProxy) -> (String, Vec) { + let prog = PROG.to_string(); + let mut args = vec![ "-terminate".to_string(), "-rootless".to_string(), "-verbose".to_string(), @@ -209,9 +213,45 @@ pub fn build_args() -> (String, Vec) { "-wm".to_string(), "5".to_string(), ]; + let features = detect_features(state, forker).await; + if features.ei_portal { + args.push(ENABLE_EI_PORTAL.to_string()); + } (prog, args) } +#[derive(Default, Debug)] +struct XwaylandFeatures { + ei_portal: bool, +} + +async fn detect_features(state: &State, forker: &ForkerProxy) -> XwaylandFeatures { + let mut features = Default::default(); + let Ok((read, write)) = pipe2(c::O_CLOEXEC) else { + return features; + }; + forker.spawn( + PROG.to_string(), + vec!["-help".to_string()], + vec![], + vec![(2, Rc::new(write))], + ); + let read = Rc::new(read); + let mut help = Vec::new(); + let mut buf = Buf::new(1024); + loop { + match state.ring.read(&read, buf.clone()).await { + Ok(0) => break, + Ok(n) => help.extend_from_slice(&buf[..n]), + Err(_) => return features, + } + } + if help.as_bstr().contains_str(ENABLE_EI_PORTAL) { + features.ei_portal = true; + } + features +} + async fn log_xwayland(state: Rc, stderr: OwnedFd) { let stderr = Rc::new(stderr); let res = log_lines(&state.ring, &stderr, |left, right| {