mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-08 05:20:59 +03:00
drm: stop leaking the authorized _drm fd into forked children
libc::dup() does not copy the close-on-exec flag, so the dup'd _drm socket fd was inherited by every child this process forks. This process is the ROOT service and it does fork synchronously elsewhere (the loginctl active-uid lookup), and that fd is an ALREADY-AUTHORIZED channel to the one thing on the box that hands out scanout dma-bufs. F_DUPFD_CLOEXEC instead. Measured the difference rather than assuming it: dup() leaves FD_CLOEXEC clear, F_DUPFD_CLOEXEC sets it. Also the last two artifact sources without the stub check: - --package + --drm stages the .so straight out of a bundle somebody else produced, with no _assert_so_has_egl. Third source, same exposure as DRMTAP_PREBUILT_DIR, now asserted like the other two. All three artifact paths are covered. - the workflow triggers omitted src/server.rs, src/server/input_service.rs and src/platform/linux.rs, which all carry DRM wiring (warm_availability, the cursor path in run_cursor, the producer start and get_cursor/get_cursor_data), so a PR touching only those skipped the entire drm verification. Added to BOTH mirrored lists and asserted equal (15 == 15).
This commit is contained in:
@@ -188,7 +188,12 @@ impl Drop for DrmStopGuard {
|
||||
/// closing ITS fd, while the dup keeps the socket alive via the shared open file description.
|
||||
fn dup_to_drm_conn(stream: &Connection) -> ResultType<DrmConn> {
|
||||
let raw = stream.inner.get_ref().as_raw_fd();
|
||||
let dup = unsafe { hbb_common::libc::dup(raw) };
|
||||
// F_DUPFD_CLOEXEC, not dup(): `dup` never copies the close-on-exec flag, so the new fd would be
|
||||
// inherited by every child this process forks. This process is the ROOT service and it does fork
|
||||
// synchronously elsewhere (the `loginctl` active-uid lookup), and this fd is an ALREADY-AUTHORIZED
|
||||
// `_drm` socket -- the one thing on the box that hands out scanout dma-bufs. Leaking it into an
|
||||
// unrelated child is a privilege leak even if no child ever reads it.
|
||||
let dup = unsafe { hbb_common::libc::fcntl(raw, hbb_common::libc::F_DUPFD_CLOEXEC, 0) };
|
||||
if dup < 0 {
|
||||
return Err(std::io::Error::last_os_error().into());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user