Skip to content

Commit f00a4ee

Browse files
valpackettslp
authored andcommitted
muvm-guest: pwbridge: actually read fd indexes in the Transport msg
The message payload contains indexes for the attached file descriptors. We must use them instead of relying on the order, which was never guaranteed, and *actually* differs in practice between architectures in compilers because current PipeWire code calls the fd-attaching function inside of function call arguments, which *don't* have a defined evaluation order in the C language standard. Signed-off-by: Val Packett <[email protected]>
1 parent 51c3960 commit f00a4ee

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

crates/muvm/src/guest/bridge/pipewire.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const CROSS_DOMAIN_CMD_READ: u8 = 6;
2121
const CROSS_DOMAIN_CMD_WRITE: u8 = 7;
2222

2323
const SPA_TYPE_STRUCT: u32 = 14;
24+
const SPA_TYPE_FD: u32 = 18;
2425

2526
const PW_OPC_CORE_CREATE_OBJECT: u8 = 6;
2627
const PW_OPC_CORE_ADD_MEM: u8 = 6;
@@ -53,6 +54,10 @@ fn read_u32(data: &[u8], at: usize) -> u32 {
5354
u32::from_ne_bytes(data[at..(at + 4)].try_into().unwrap())
5455
}
5556

57+
fn read_u64(data: &[u8], at: usize) -> u64 {
58+
u64::from_ne_bytes(data[at..(at + 8)].try_into().unwrap())
59+
}
60+
5661
#[derive(Debug)]
5762
struct CoreCreateObject<'a> {
5863
obj_type: &'a CStr,
@@ -115,6 +120,27 @@ impl<'a> ClientUpdateProperties<'a> {
115120
}
116121
}
117122

123+
#[derive(Debug)]
124+
struct ClientNodeTransport {
125+
readfd: u64,
126+
writefd: u64,
127+
// .. don't care about the remaining ones
128+
}
129+
130+
impl ClientNodeTransport {
131+
fn new(data: &[u8]) -> Self {
132+
let ty = read_u32(data, 4);
133+
assert_eq!(ty, SPA_TYPE_STRUCT);
134+
let readfd_ty = read_u32(data, 12);
135+
assert_eq!(readfd_ty, SPA_TYPE_FD);
136+
let readfd = read_u64(data, 16);
137+
let writefd_ty = read_u32(data, 28);
138+
assert_eq!(writefd_ty, SPA_TYPE_FD);
139+
let writefd = read_u64(data, 32);
140+
ClientNodeTransport { readfd, writefd }
141+
}
142+
}
143+
118144
struct PipeWireHeader {
119145
id: u32,
120146
opcode: u8,
@@ -267,10 +293,21 @@ impl ProtocolHandler for PipeWireProtocolHandler {
267293
let rsc = resources.pop_front().ok_or(Errno::EIO)?;
268294
fds.push(Self::create_guest_to_host_eventfd(this, hdr.id, rsc)?);
269295
} else if hdr.opcode == PW_OPC_CLIENT_NODE_TRANSPORT {
270-
let rsc1 = resources.pop_front().ok_or(Errno::EIO)?;
271-
fds.push(Self::create_host_to_guest_eventfd(this, hdr.id, rsc1)?);
272-
let rsc2 = resources.pop_front().ok_or(Errno::EIO)?;
273-
fds.push(Self::create_guest_to_host_eventfd(this, hdr.id, rsc2)?);
296+
let msg = ClientNodeTransport::new(&data[PipeWireHeader::SIZE..]);
297+
// We need to take elements out by index without shifting the indices.
298+
let mut resources: Vec<_> = resources.drain(..hdr.num_fd).map(Some).collect();
299+
let writefd_rsc = resources.get_mut(msg.writefd as usize).ok_or(Errno::EIO)?;
300+
fds.push(Self::create_guest_to_host_eventfd(
301+
this,
302+
hdr.id,
303+
writefd_rsc.take().ok_or(Errno::EIO)?,
304+
)?);
305+
let readfd_rsc = resources.get_mut(msg.readfd as usize).ok_or(Errno::EIO)?;
306+
fds.push(Self::create_host_to_guest_eventfd(
307+
this,
308+
hdr.id,
309+
readfd_rsc.take().ok_or(Errno::EIO)?,
310+
)?);
274311
} else {
275312
unimplemented!()
276313
}

0 commit comments

Comments
 (0)