1
0
Fork 0
forked from wry/wry

security: remove context protocol

This commit is contained in:
kossLAN 2026-05-29 18:13:14 -04:00
parent 6f913d5f69
commit 8a35bc3ca4
No known key found for this signature in database
16 changed files with 42 additions and 423 deletions

View file

@ -1,7 +1,7 @@
use {
crate::{
async_engine::SpawnedFuture,
security_context_acceptor::AcceptorMetadata,
client::ClientMetadata,
state::State,
utils::{
errorfmt::ErrorFmt,
@ -138,7 +138,7 @@ impl Acceptor {
}
async fn accept(fd: Rc<OwnedFd>, state: Rc<State>) {
let metadata = Rc::new(AcceptorMetadata::default());
let metadata = Rc::new(ClientMetadata::default());
loop {
let fd = match state.ring.accept(&fd, c::SOCK_CLOEXEC).await {
Ok(fd) => fd,

View file

@ -14,7 +14,6 @@ use {
},
leaks::Tracker,
object::{Interface, Object, ObjectId, WL_DISPLAY_ID},
security_context_acceptor::AcceptorMetadata,
state::State,
utils::{
asyncevent::AsyncEvent,
@ -95,6 +94,14 @@ pub struct Clients {
shutdown_clients: RefCell<AHashMap<ClientId, ClientHolder>>,
}
#[derive(Default)]
pub struct ClientMetadata {
pub sandboxed: bool,
pub sandbox_engine: Option<String>,
pub app_id: Option<String>,
pub instance_id: Option<String>,
}
impl Clients {
pub fn new() -> Self {
Self {
@ -126,12 +133,12 @@ impl Clients {
id: ClientId,
global: &Rc<State>,
socket: Rc<OwnedFd>,
acceptor: &Rc<AcceptorMetadata>,
metadata: &Rc<ClientMetadata>,
) -> Result<(), ClientError> {
let Some((uid, pid)) = get_socket_creds(&socket) else {
return Ok(());
};
self.spawn2(id, global, socket, uid, pid, false, acceptor)?;
self.spawn2(id, global, socket, uid, pid, false, metadata)?;
Ok(())
}
@ -143,7 +150,7 @@ impl Clients {
uid: c::uid_t,
pid: c::pid_t,
is_xwayland: bool,
acceptor: &Rc<AcceptorMetadata>,
metadata: &Rc<ClientMetadata>,
) -> Result<Rc<Client>, ClientError> {
let data = Rc::new_cyclic(|slf| Client {
id,
@ -173,7 +180,7 @@ impl Clients {
focus_stealing_serial: Default::default(),
changed_properties: Default::default(),
destroyed: Default::default(),
acceptor: acceptor.clone(),
metadata: metadata.clone(),
});
track!(data, data);
let display = Rc::new(WlDisplay::new(&data));
@ -292,7 +299,7 @@ pub struct Client {
pub focus_stealing_serial: Cell<Option<u64>>,
pub changed_properties: Cell<ClMatcherChange>,
pub destroyed: CopyHashMap<CritMatcherId, Weak<dyn CritDestroyListener<Self>>>,
pub acceptor: Rc<AcceptorMetadata>,
pub metadata: Rc<ClientMetadata>,
}
pub const NUM_CACHED_SERIAL_RANGES: usize = 64;

View file

@ -325,7 +325,6 @@ fn start_compositor2(
explicit_sync_supported: Default::default(),
keyboard_state_ids: Default::default(),
physical_keyboard_ids: Default::default(),
security_context_acceptors: Default::default(),
cursor_user_group_ids: Default::default(),
cursor_user_ids: Default::default(),
cursor_user_groups: Default::default(),

View file

@ -8,6 +8,6 @@ fixed_root_criterion!(ClmMatchSandboxed, sandboxed);
impl CritFixedRootCriterion<Client> for ClmMatchSandboxed {
fn matches(&self, data: &Client) -> bool {
data.acceptor.sandboxed
data.metadata.sandboxed
}
}

View file

@ -1,44 +1,43 @@
use {
crate::{
client::Client,
client::{Client, ClientMetadata},
criteria::{
clm::{ClmRootMatcherMap, RootMatchers},
crit_matchers::critm_string::{CritMatchString, StringAccess},
},
security_context_acceptor::AcceptorMetadata,
},
std::marker::PhantomData,
};
pub type ClmMatchString<T> = CritMatchString<Client, T>;
pub type ClmMatchSandboxEngine = ClmMatchString<AcceptorMetadataAccess<SandboxEngineField>>;
pub type ClmMatchSandboxAppId = ClmMatchString<AcceptorMetadataAccess<SandboxAppIdField>>;
pub type ClmMatchSandboxInstanceId = ClmMatchString<AcceptorMetadataAccess<SandboxInstanceIdField>>;
pub type ClmMatchSandboxEngine = ClmMatchString<ClientMetadataAccess<SandboxEngineField>>;
pub type ClmMatchSandboxAppId = ClmMatchString<ClientMetadataAccess<SandboxAppIdField>>;
pub type ClmMatchSandboxInstanceId = ClmMatchString<ClientMetadataAccess<SandboxInstanceIdField>>;
pub type ClmMatchComm = ClmMatchString<CommAccess>;
pub type ClmMatchExe = ClmMatchString<ExeAccess>;
pub struct AcceptorMetadataAccess<T>(PhantomData<T>);
pub struct ClientMetadataAccess<T>(PhantomData<T>);
pub struct CommAccess;
pub struct ExeAccess;
trait AcceptorMetadataField: Sized + 'static {
fn field(meta: &AcceptorMetadata) -> &Option<String>;
trait ClientMetadataField: Sized + 'static {
fn field(meta: &ClientMetadata) -> &Option<String>;
fn nodes(
roots: &RootMatchers,
) -> &ClmRootMatcherMap<ClmMatchString<AcceptorMetadataAccess<Self>>>;
) -> &ClmRootMatcherMap<ClmMatchString<ClientMetadataAccess<Self>>>;
}
pub struct SandboxEngineField;
pub struct SandboxAppIdField;
pub struct SandboxInstanceIdField;
impl<T> StringAccess<Client> for AcceptorMetadataAccess<T>
impl<T> StringAccess<Client> for ClientMetadataAccess<T>
where
T: AcceptorMetadataField,
T: ClientMetadataField,
{
fn with_string(data: &Client, f: impl FnOnce(&str) -> bool) -> bool {
f(T::field(&data.acceptor).as_deref().unwrap_or_default())
f(T::field(&data.metadata).as_deref().unwrap_or_default())
}
fn nodes(roots: &RootMatchers) -> &ClmRootMatcherMap<ClmMatchString<Self>> {
@ -46,38 +45,38 @@ where
}
}
impl AcceptorMetadataField for SandboxEngineField {
fn field(meta: &AcceptorMetadata) -> &Option<String> {
impl ClientMetadataField for SandboxEngineField {
fn field(meta: &ClientMetadata) -> &Option<String> {
&meta.sandbox_engine
}
fn nodes(
roots: &RootMatchers,
) -> &ClmRootMatcherMap<ClmMatchString<AcceptorMetadataAccess<Self>>> {
) -> &ClmRootMatcherMap<ClmMatchString<ClientMetadataAccess<Self>>> {
&roots.sandbox_engine
}
}
impl AcceptorMetadataField for SandboxAppIdField {
fn field(meta: &AcceptorMetadata) -> &Option<String> {
impl ClientMetadataField for SandboxAppIdField {
fn field(meta: &ClientMetadata) -> &Option<String> {
&meta.app_id
}
fn nodes(
roots: &RootMatchers,
) -> &ClmRootMatcherMap<ClmMatchString<AcceptorMetadataAccess<Self>>> {
) -> &ClmRootMatcherMap<ClmMatchString<ClientMetadataAccess<Self>>> {
&roots.sandbox_app_id
}
}
impl AcceptorMetadataField for SandboxInstanceIdField {
fn field(meta: &AcceptorMetadata) -> &Option<String> {
impl ClientMetadataField for SandboxInstanceIdField {
fn field(meta: &ClientMetadata) -> &Option<String> {
&meta.instance_id
}
fn nodes(
roots: &RootMatchers,
) -> &ClmRootMatcherMap<ClmMatchString<AcceptorMetadataAccess<Self>>> {
) -> &ClmRootMatcherMap<ClmMatchString<ClientMetadataAccess<Self>>> {
&roots.sandbox_instance_id
}
}

View file

@ -56,7 +56,6 @@ use {
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1Global,
wp_linux_drm_syncobj_manager_v1::WpLinuxDrmSyncobjManagerV1Global,
wp_presentation::WpPresentationGlobal,
wp_security_context_manager_v1::WpSecurityContextManagerV1Global,
wp_single_pixel_buffer_manager_v1::WpSinglePixelBufferManagerV1Global,
wp_tearing_control_manager_v1::WpTearingControlManagerV1Global,
wp_viewporter::WpViewporterGlobal,
@ -205,7 +204,6 @@ singletons! {
ZwpVirtualKeyboardManagerV1,
ZwpInputMethodManagerV2,
ZwpTextInputManagerV3,
WpSecurityContextManagerV1,
XdgWmDialogV1,
ExtTransientSeatManagerV1,
ZwpPointerGesturesV1,

View file

@ -74,8 +74,6 @@ pub mod wp_linux_drm_syncobj_manager_v1;
pub mod wp_linux_drm_syncobj_timeline_v1;
pub mod wp_presentation;
pub mod wp_presentation_feedback;
pub mod wp_security_context_manager_v1;
pub mod wp_security_context_v1;
pub mod wp_single_pixel_buffer_manager_v1;
pub mod wp_tearing_control_manager_v1;
pub mod wp_viewporter;

View file

@ -71,25 +71,25 @@ impl JayClientQueryRequestHandler for JayClientQuery {
exe: &client.pid_info.exe,
});
}
if client.acceptor.sandboxed {
if client.metadata.sandboxed {
self.client.event(Sandboxed { self_id: self.id });
}
if client.is_xwayland {
self.client.event(IsXwayland { self_id: self.id });
}
if let Some(engine) = &client.acceptor.sandbox_engine {
if let Some(engine) = &client.metadata.sandbox_engine {
self.client.event(SandboxEngine {
self_id: self.id,
engine,
});
}
if let Some(app_id) = &client.acceptor.app_id {
if let Some(app_id) = &client.metadata.app_id {
self.client.event(SandboxAppId {
self_id: self.id,
app_id,
});
}
if let Some(instance_id) = &client.acceptor.instance_id {
if let Some(instance_id) = &client.metadata.instance_id {
self.client.event(SandboxInstanceId {
self_id: self.id,
instance_id,

View file

@ -1,103 +0,0 @@
use {
crate::{
client::{Client, ClientError},
globals::{Global, GlobalName},
ifs::wp_security_context_v1::WpSecurityContextV1,
leaks::Tracker,
object::{Object, Version},
wire::{WpSecurityContextManagerV1Id, wp_security_context_manager_v1::*},
},
std::rc::Rc,
thiserror::Error,
};
pub struct WpSecurityContextManagerV1Global {
pub name: GlobalName,
}
impl WpSecurityContextManagerV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: WpSecurityContextManagerV1Id,
client: &Rc<Client>,
version: Version,
) -> Result<(), WpSecurityContextManagerV1Error> {
let obj = Rc::new(WpSecurityContextManagerV1 {
id,
client: client.clone(),
tracker: Default::default(),
version,
});
track!(client, obj);
client.add_client_obj(&obj)?;
Ok(())
}
}
global_base!(
WpSecurityContextManagerV1Global,
WpSecurityContextManagerV1,
WpSecurityContextManagerV1Error
);
impl Global for WpSecurityContextManagerV1Global {
fn version(&self) -> u32 {
1
}
}
simple_add_global!(WpSecurityContextManagerV1Global);
pub struct WpSecurityContextManagerV1 {
pub id: WpSecurityContextManagerV1Id,
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub version: Version,
}
impl WpSecurityContextManagerV1RequestHandler for WpSecurityContextManagerV1 {
type Error = WpSecurityContextManagerV1Error;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}
fn create_listener(&self, req: CreateListener, _slf: &Rc<Self>) -> Result<(), Self::Error> {
let obj = Rc::new(WpSecurityContextV1 {
id: req.id,
client: self.client.clone(),
tracker: Default::default(),
version: self.version,
listen_fd: req.listen_fd,
close_fd: req.close_fd,
sandbox_engine: Default::default(),
app_id: Default::default(),
instance_id: Default::default(),
committed: Default::default(),
});
track!(self.client, obj);
self.client.add_client_obj(&obj)?;
Ok(())
}
}
object_base! {
self = WpSecurityContextManagerV1;
version = self.version;
}
impl Object for WpSecurityContextManagerV1 {}
simple_add_obj!(WpSecurityContextManagerV1);
#[derive(Debug, Error)]
pub enum WpSecurityContextManagerV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(WpSecurityContextManagerV1Error, ClientError);

View file

@ -1,117 +0,0 @@
use {
crate::{
client::{Client, ClientError},
leaks::Tracker,
object::{Object, Version},
wire::{WpSecurityContextV1Id, wp_security_context_v1::*},
},
std::{
cell::{Cell, RefCell},
rc::Rc,
},
thiserror::Error,
uapi::OwnedFd,
};
pub struct WpSecurityContextV1 {
pub id: WpSecurityContextV1Id,
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub version: Version,
pub listen_fd: Rc<OwnedFd>,
pub close_fd: Rc<OwnedFd>,
pub sandbox_engine: RefCell<Option<String>>,
pub app_id: RefCell<Option<String>>,
pub instance_id: RefCell<Option<String>>,
pub committed: Cell<bool>,
}
impl WpSecurityContextV1 {
fn check_committed(&self) -> Result<(), WpSecurityContextV1Error> {
if self.committed.get() {
return Err(WpSecurityContextV1Error::Committed);
}
Ok(())
}
}
impl WpSecurityContextV1RequestHandler for WpSecurityContextV1 {
type Error = WpSecurityContextV1Error;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.client.remove_obj(self)?;
Ok(())
}
fn set_sandbox_engine(
&self,
req: SetSandboxEngine<'_>,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.check_committed()?;
let val = &mut *self.sandbox_engine.borrow_mut();
if val.is_some() {
return Err(WpSecurityContextV1Error::EnginSet);
}
*val = Some(req.name.to_string());
Ok(())
}
fn set_app_id(&self, req: SetAppId<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.check_committed()?;
let val = &mut *self.app_id.borrow_mut();
if val.is_some() {
return Err(WpSecurityContextV1Error::AppSet);
}
*val = Some(req.app_id.to_string());
Ok(())
}
fn set_instance_id(&self, req: SetInstanceId<'_>, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.check_committed()?;
let val = &mut *self.instance_id.borrow_mut();
if val.is_some() {
return Err(WpSecurityContextV1Error::InstanceSet);
}
*val = Some(req.instance_id.to_string());
Ok(())
}
fn commit(&self, _req: Commit, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.check_committed()?;
self.committed.set(true);
self.client.state.security_context_acceptors.spawn(
&self.client.state,
self.sandbox_engine.take(),
self.app_id.take(),
self.instance_id.take(),
&self.listen_fd,
&self.close_fd,
);
Ok(())
}
}
object_base! {
self = WpSecurityContextV1;
version = self.version;
}
impl Object for WpSecurityContextV1 {}
simple_add_obj!(WpSecurityContextV1);
#[derive(Debug, Error)]
pub enum WpSecurityContextV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("The sandbox engine has already been set")]
EnginSet,
#[error("The app id has already been set")]
AppSet,
#[error("The instance id has already been set")]
InstanceSet,
#[error("The context has already been committed")]
Committed,
}
efrom!(WpSecurityContextV1Error, ClientError);

View file

@ -97,7 +97,6 @@ mod rect;
mod renderer;
mod scale;
mod screenshoter;
mod security_context_acceptor;
mod sighand;
mod state;
mod tasks;

View file

@ -1,132 +0,0 @@
use {
crate::{
async_engine::SpawnedFuture,
state::State,
utils::{copyhashmap::CopyHashMap, errorfmt::ErrorFmt, hash_map_ext::HashMapExt},
},
std::{
cell::Cell,
fmt::{Display, Formatter},
rc::Rc,
},
uapi::{OwnedFd, c},
};
#[derive(Default)]
pub struct SecurityContextAcceptors {
ids: AcceptorIds,
acceptors: CopyHashMap<AcceptorId, Rc<Acceptor>>,
}
linear_ids!(AcceptorIds, AcceptorId, u64);
struct Acceptor {
id: AcceptorId,
state: Rc<State>,
metadata: Rc<AcceptorMetadata>,
listen_fd: Rc<OwnedFd>,
close_fd: Rc<OwnedFd>,
listen_future: Cell<Option<SpawnedFuture<()>>>,
close_future: Cell<Option<SpawnedFuture<()>>>,
}
#[derive(Default)]
pub struct AcceptorMetadata {
pub sandboxed: bool,
pub sandbox_engine: Option<String>,
pub app_id: Option<String>,
pub instance_id: Option<String>,
}
impl SecurityContextAcceptors {
pub fn clear(&self) {
for acceptor in self.acceptors.lock().drain_values() {
acceptor.kill();
}
}
pub fn spawn(
&self,
state: &Rc<State>,
sandbox_engine: Option<String>,
app_id: Option<String>,
instance_id: Option<String>,
listen_fd: &Rc<OwnedFd>,
close_fd: &Rc<OwnedFd>,
) {
let acceptor = Rc::new(Acceptor {
id: self.ids.next(),
state: state.clone(),
metadata: Rc::new(AcceptorMetadata {
sandboxed: true,
sandbox_engine,
app_id,
instance_id,
}),
listen_fd: listen_fd.clone(),
close_fd: close_fd.clone(),
listen_future: Cell::new(None),
close_future: Cell::new(None),
});
log::info!("Creating security acceptor {acceptor}");
acceptor.listen_future.set(Some(
state
.eng
.spawn("security accept", acceptor.clone().accept()),
));
acceptor.close_future.set(Some(
state
.eng
.spawn("security await close", acceptor.clone().close()),
));
self.acceptors.set(acceptor.id, acceptor);
}
}
impl Acceptor {
fn kill(&self) {
log::info!("Destroying security acceptor {self}");
self.listen_future.take();
self.close_future.take();
self.state
.security_context_acceptors
.acceptors
.remove(&self.id);
}
async fn accept(self: Rc<Self>) {
let s = &self.state;
loop {
let fd = match s.ring.accept(&self.listen_fd, c::SOCK_CLOEXEC).await {
Ok(fd) => fd,
Err(e) => {
log::error!("Could not accept a client: {}", ErrorFmt(e));
break;
}
};
let id = s.clients.id();
if let Err(e) = s.clients.spawn(id, s, fd, &self.metadata) {
log::error!("Could not spawn a client: {}", ErrorFmt(e));
break;
}
}
self.kill();
}
async fn close(self: Rc<Self>) {
let _ = self.state.ring.poll(&self.close_fd, 0).await;
self.kill();
}
}
impl Display for Acceptor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}/{}/{}",
self.metadata.sandbox_engine.as_deref().unwrap_or(""),
self.metadata.app_id.as_deref().unwrap_or(""),
self.metadata.instance_id.as_deref().unwrap_or(""),
)
}
}

View file

@ -108,7 +108,6 @@ use {
rect::{Rect, Region},
renderer::Renderer,
scale::Scale,
security_context_acceptor::SecurityContextAcceptors,
theme::{BarPosition, Color, Theme, ThemeColor, ThemeSized},
time::Time,
tree::{
@ -343,7 +342,6 @@ pub struct State {
pub explicit_sync_supported: Cell<bool>,
pub keyboard_state_ids: KeyboardStateIds,
pub physical_keyboard_ids: PhysicalKeyboardIds,
pub security_context_acceptors: SecurityContextAcceptors,
pub cursor_user_group_ids: CursorUserGroupIds,
pub cursor_user_ids: CursorUserIds,
pub cursor_user_groups: CopyHashMap<CursorUserGroupId, Rc<CursorUserGroup>>,
@ -1249,7 +1247,6 @@ impl State {
self.render_ctx_watchers.clear();
self.workspace_watchers.clear();
self.toplevel_lists.clear();
self.security_context_acceptors.clear();
self.slow_clients.clear();
for h in self.input_device_handlers.borrow_mut().drain_values() {
h.async_event.clear();

View file

@ -3,7 +3,7 @@ mod xwm;
use {
crate::{
client::ClientError,
client::{ClientError, ClientMetadata},
compositor::DISPLAY,
forker::{ForkerError, ForkerProxy},
ifs::{
@ -12,7 +12,6 @@ use {
wl_surface::x_surface::xwindow::{Xwindow, XwindowData},
},
io_uring::IoUringError,
security_context_acceptor::AcceptorMetadata,
state::State,
user_session::import_environment,
utils::{
@ -192,7 +191,7 @@ async fn run(
uapi::getuid(),
pid,
true,
&Rc::new(AcceptorMetadata::default()),
&Rc::new(ClientMetadata::default()),
);
let client = match client {
Ok(c) => c,

View file

@ -1,8 +0,0 @@
request destroy (destructor) {
}
request create_listener {
id: id(wp_security_context_v1) (new),
listen_fd: fd,
close_fd: fd,
}

View file

@ -1,17 +0,0 @@
request destroy (destructor) {
}
request set_sandbox_engine {
name: str,
}
request set_app_id {
app_id: str,
}
request set_instance_id {
instance_id: str,
}
request commit {
}