clientmem: store more information about mappings
This commit is contained in:
parent
92f7cb56fd
commit
604974c927
6 changed files with 67 additions and 18 deletions
|
|
@ -353,8 +353,9 @@ impl Input {
|
||||||
async fn handle_keymap(&self, input: JayInputId) -> Vec<u8> {
|
async fn handle_keymap(&self, input: JayInputId) -> Vec<u8> {
|
||||||
let data = Rc::new(RefCell::new(Vec::new()));
|
let data = Rc::new(RefCell::new(Vec::new()));
|
||||||
jay_input::Keymap::handle(&self.tc, input, data.clone(), |d, map| {
|
jay_input::Keymap::handle(&self.tc, input, data.clone(), |d, map| {
|
||||||
let mem = Rc::new(ClientMem::new(map.keymap.raw(), map.keymap_len as _, true).unwrap())
|
let mem =
|
||||||
.offset(0);
|
Rc::new(ClientMem::new(&map.keymap, map.keymap_len as _, true, None).unwrap())
|
||||||
|
.offset(0);
|
||||||
mem.read(d.borrow_mut().deref_mut()).unwrap();
|
mem.read(d.borrow_mut().deref_mut()).unwrap();
|
||||||
});
|
});
|
||||||
self.tc.round_trip().await;
|
self.tc.round_trip().await;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::utils::vec_ext::VecExt,
|
crate::{client::Client, utils::vec_ext::VecExt},
|
||||||
std::{
|
std::{
|
||||||
cell::Cell,
|
cell::Cell,
|
||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
|
|
@ -8,7 +8,10 @@ use {
|
||||||
sync::atomic::{compiler_fence, Ordering},
|
sync::atomic::{compiler_fence, Ordering},
|
||||||
},
|
},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
uapi::{c, c::raise},
|
uapi::{
|
||||||
|
c::{self, raise},
|
||||||
|
OwnedFd,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
@ -22,6 +25,7 @@ pub enum ClientMemError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ClientMem {
|
pub struct ClientMem {
|
||||||
|
fd: Rc<OwnedFd>,
|
||||||
failed: Cell<bool>,
|
failed: Cell<bool>,
|
||||||
sigbus_impossible: bool,
|
sigbus_impossible: bool,
|
||||||
data: *const [Cell<u8>],
|
data: *const [Cell<u8>],
|
||||||
|
|
@ -30,19 +34,34 @@ pub struct ClientMem {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientMemOffset {
|
pub struct ClientMemOffset {
|
||||||
mem: Rc<ClientMem>,
|
mem: Rc<ClientMem>,
|
||||||
|
offset: usize,
|
||||||
data: *const [Cell<u8>],
|
data: *const [Cell<u8>],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientMem {
|
impl ClientMem {
|
||||||
pub fn new(fd: i32, len: usize, read_only: bool) -> Result<Self, ClientMemError> {
|
pub fn new(
|
||||||
|
fd: &Rc<OwnedFd>,
|
||||||
|
len: usize,
|
||||||
|
read_only: bool,
|
||||||
|
client: Option<&Client>,
|
||||||
|
) -> Result<Self, ClientMemError> {
|
||||||
let mut sigbus_impossible = false;
|
let mut sigbus_impossible = false;
|
||||||
if let Ok(seals) = uapi::fcntl_get_seals(fd) {
|
if let Ok(seals) = uapi::fcntl_get_seals(fd.raw()) {
|
||||||
if seals & c::F_SEAL_SHRINK != 0 {
|
if seals & c::F_SEAL_SHRINK != 0 {
|
||||||
if let Ok(stat) = uapi::fstat(fd) {
|
if let Ok(stat) = uapi::fstat(fd.raw()) {
|
||||||
sigbus_impossible = stat.st_size as u64 >= len as u64;
|
sigbus_impossible = stat.st_size as u64 >= len as u64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !sigbus_impossible {
|
||||||
|
if let Some(client) = client {
|
||||||
|
log::debug!(
|
||||||
|
"Client {} ({}) has created a shm buffer that might cause SIGBUS",
|
||||||
|
client.pid_info.comm,
|
||||||
|
client.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
let data = if len == 0 {
|
let data = if len == 0 {
|
||||||
&mut [][..]
|
&mut [][..]
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -51,7 +70,7 @@ impl ClientMem {
|
||||||
false => c::PROT_READ | c::PROT_WRITE,
|
false => c::PROT_READ | c::PROT_WRITE,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = c::mmap64(ptr::null_mut(), len, prot, c::MAP_SHARED, fd, 0);
|
let data = c::mmap64(ptr::null_mut(), len, prot, c::MAP_SHARED, fd.raw(), 0);
|
||||||
if data == c::MAP_FAILED {
|
if data == c::MAP_FAILED {
|
||||||
return Err(ClientMemError::MmapFailed(uapi::Errno::default().into()));
|
return Err(ClientMemError::MmapFailed(uapi::Errno::default().into()));
|
||||||
}
|
}
|
||||||
|
|
@ -59,6 +78,7 @@ impl ClientMem {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
fd: fd.clone(),
|
||||||
failed: Cell::new(false),
|
failed: Cell::new(false),
|
||||||
sigbus_impossible,
|
sigbus_impossible,
|
||||||
data,
|
data,
|
||||||
|
|
@ -73,12 +93,38 @@ impl ClientMem {
|
||||||
let mem = unsafe { &*self.data };
|
let mem = unsafe { &*self.data };
|
||||||
ClientMemOffset {
|
ClientMemOffset {
|
||||||
mem: self.clone(),
|
mem: self.clone(),
|
||||||
|
offset,
|
||||||
data: &mem[offset..],
|
data: &mem[offset..],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn fd(&self) -> &Rc<OwnedFd> {
|
||||||
|
&self.fd
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn sigbus_impossible(&self) -> bool {
|
||||||
|
self.sigbus_impossible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientMemOffset {
|
impl ClientMemOffset {
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn pool(&self) -> &ClientMem {
|
||||||
|
&self.mem
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn offset(&self) -> usize {
|
||||||
|
self.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
pub fn ptr(&self) -> *const [Cell<u8>] {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
|
||||||
pub fn access<T, F: FnOnce(&[Cell<u8>]) -> T>(&self, f: F) -> Result<T, ClientMemError> {
|
pub fn access<T, F: FnOnce(&[Cell<u8>]) -> T>(&self, f: F) -> Result<T, ClientMemError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.mem.sigbus_impossible {
|
if self.mem.sigbus_impossible {
|
||||||
|
|
|
||||||
|
|
@ -165,11 +165,11 @@ impl JayInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_keymap_impl<F>(&self, keymap: &OwnedFd, len: u32, f: F) -> Result<(), JayInputError>
|
fn set_keymap_impl<F>(&self, keymap: &Rc<OwnedFd>, len: u32, f: F) -> Result<(), JayInputError>
|
||||||
where
|
where
|
||||||
F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>,
|
F: FnOnce(&Rc<XkbKeymap>) -> Result<(), JayInputError>,
|
||||||
{
|
{
|
||||||
let cm = Rc::new(ClientMem::new(keymap.raw(), len as _, true)?).offset(0);
|
let cm = Rc::new(ClientMem::new(keymap, len as _, true, Some(&self.client))?).offset(0);
|
||||||
let mut map = vec![];
|
let mut map = vec![];
|
||||||
cm.read(&mut map)?;
|
cm.read(&mut map)?;
|
||||||
self.or_error(|| {
|
self.or_error(|| {
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ impl ZwpVirtualKeyboardV1RequestHandler for ZwpVirtualKeyboardV1 {
|
||||||
if req.size > MAX_SIZE {
|
if req.size > MAX_SIZE {
|
||||||
return Err(ZwpVirtualKeyboardV1Error::OversizedKeymap);
|
return Err(ZwpVirtualKeyboardV1Error::OversizedKeymap);
|
||||||
}
|
}
|
||||||
let client_mem = ClientMem::new(req.fd.raw(), req.size as usize - 1, true)
|
let client_mem = ClientMem::new(&req.fd, req.size as usize - 1, true, Some(&self.client))
|
||||||
.map(Rc::new)
|
.map(Rc::new)
|
||||||
.map_err(ZwpVirtualKeyboardV1Error::MapKeymap)?;
|
.map_err(ZwpVirtualKeyboardV1Error::MapKeymap)?;
|
||||||
let mut map = vec![];
|
let mut map = vec![];
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl WlShmPool {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id,
|
id,
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
mem: CloneCell::new(Rc::new(ClientMem::new(fd.raw(), len, false)?)),
|
mem: CloneCell::new(Rc::new(ClientMem::new(&fd, len, false, Some(client))?)),
|
||||||
fd,
|
fd,
|
||||||
tracker: Default::default(),
|
tracker: Default::default(),
|
||||||
version,
|
version,
|
||||||
|
|
@ -82,9 +82,10 @@ impl WlShmPoolRequestHandler for WlShmPool {
|
||||||
return Err(WlShmPoolError::CannotShrink);
|
return Err(WlShmPoolError::CannotShrink);
|
||||||
}
|
}
|
||||||
self.mem.set(Rc::new(ClientMem::new(
|
self.mem.set(Rc::new(ClientMem::new(
|
||||||
self.fd.raw(),
|
&self.fd,
|
||||||
req.size as usize,
|
req.size as usize,
|
||||||
false,
|
false,
|
||||||
|
Some(&self.client),
|
||||||
)?));
|
)?));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use {
|
||||||
},
|
},
|
||||||
bstr::ByteSlice,
|
bstr::ByteSlice,
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
|
uapi::OwnedFd,
|
||||||
};
|
};
|
||||||
|
|
||||||
testcase!();
|
testcase!();
|
||||||
|
|
@ -15,7 +16,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
let virtual_keymap_str = {
|
let virtual_keymap_str = {
|
||||||
let xkb = XkbContext::new()?;
|
let xkb = XkbContext::new()?;
|
||||||
let map = xkb.keymap_from_str(VIRTUAL_KEYMAP).unwrap();
|
let map = xkb.keymap_from_str(VIRTUAL_KEYMAP).unwrap();
|
||||||
read_keymap(map.map.raw(), map.map_len)
|
read_keymap(&map.map, map.map_len)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ds = run.create_default_setup().await?;
|
let ds = run.create_default_setup().await?;
|
||||||
|
|
@ -51,7 +52,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
s_client.sync().await;
|
s_client.sync().await;
|
||||||
let (start, keymap) = s_keymap.next().expect("virtual keymap");
|
let (start, keymap) = s_keymap.next().expect("virtual keymap");
|
||||||
tassert_eq!(
|
tassert_eq!(
|
||||||
&read_keymap(keymap.fd.raw(), keymap.size as _),
|
&read_keymap(&keymap.fd, keymap.size as _),
|
||||||
&virtual_keymap_str
|
&virtual_keymap_str
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
|
|
@ -119,7 +120,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
s_client.sync().await;
|
s_client.sync().await;
|
||||||
let (pos, keymap) = s_keymap.next().expect("seat keymap");
|
let (pos, keymap) = s_keymap.next().expect("seat keymap");
|
||||||
tassert_eq!(pos, start + 8);
|
tassert_eq!(pos, start + 8);
|
||||||
tassert!(read_keymap(keymap.fd.raw(), keymap.size as _) != virtual_keymap_str);
|
tassert!(read_keymap(&keymap.fd, keymap.size as _) != virtual_keymap_str);
|
||||||
{
|
{
|
||||||
let (pos, mods) = s_modifiers.next().expect("mods 0");
|
let (pos, mods) = s_modifiers.next().expect("mods 0");
|
||||||
tassert_eq!(pos, start + 9);
|
tassert_eq!(pos, start + 9);
|
||||||
|
|
@ -147,8 +148,8 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_keymap(fd: i32, size: usize) -> String {
|
fn read_keymap(fd: &Rc<OwnedFd>, size: usize) -> String {
|
||||||
let client_mem = ClientMem::new(fd, size - 1, true).unwrap();
|
let client_mem = ClientMem::new(fd, size - 1, true, None).unwrap();
|
||||||
let client_mem = Rc::new(client_mem).offset(0);
|
let client_mem = Rc::new(client_mem).offset(0);
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
client_mem.read(&mut v).unwrap();
|
client_mem.read(&mut v).unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue