generate_control_file goes back to upstream byte for byte: no extra parameters, no
conditional inside it. The variant instead rewrites the control file that function
just produced, so everything specific to the consent-free package lives in added
code rather than in the shared one. That rewrite fails loudly if either anchor line
stops matching, so a future upstream change to the control layout cannot quietly
yield a variant deb wearing the stock package name.
finalize_deb is gone. It had pulled the tail of both deb builders into one shared
helper, which is a refactor of a path the feature has no business touching. Both
builders now carry their upstream tail verbatim, with the drm work added as three
guarded blocks: stage the library, retarget the control, rename the output. With
the feature off, every line is upstream's.
Verified rather than argued, by building both packages with this script:
the drm deb is Package: rustdesk-unattended-wayland, carries Conflicts, Replaces
and Provides on rustdesk, has libdrm2, libegl1 and libgles2 appended to Depends,
and ships libdrmtap.so.0.4.15 plus its soname symlink. The stock deb is
Package: rustdesk, carries none of those three fields, and contains no libdrmtap
file at all.
`git clone --depth 1 --branch main` fetches only the tip of that branch, so the
moment upstream pushes to libdrmtap `main` the pinned commit is no longer present
in the shallow clone at all: the build fails on an unreachable object rather than
on a mismatched pin, and it fails for a reason that has nothing to do with the
checkout being wrong. In the release workflow the whole block is wrapped so the
job stays green, which means the drm deb would simply stop being produced without
anyone noticing.
Fetch the sha directly instead. No branch or tag name takes part in the build now,
so it survives every upstream push and cannot be affected by a ref being moved or
repointed. DRMTAP_REF is gone, along with the regex that validated it.
The post-fetch sha check stays, with a narrower job: a fetch by sha cannot resolve
to anything else, so it now guards a reused checkout left at a different pin, which
is exactly what a version bump leaves behind. It still removes that tree so the
next run re-fetches cleanly.
build.py is now the single source of truth for the pin.
Point the DRM capture build at the libdrmtap v0.4.14 release commit
(816766dedaba3140c613712ce97aa2614e8899e7) instead of v0.4.13, in build.py and
the flutter-build workflow, and correct the scrap Cargo.toml note to describe
the actual DRMTAP_SHA anchor. 0.4.14 keeps the same public API, so the dlopen
consumer needs no change.
5e: the deb dropped /usr/lib/rustdesk into /etc/ld.so.conf.d so the private libdrmtap
could be found by soname -- a system-wide search-path entry that lets it shadow a
system library for every binary on the host, which Debian Policy 10.2 forbids. Resolve
it by absolute path (/usr/lib/rustdesk/libdrmtap.so.0) at the dlopen site instead, with
the bare sonames kept only as a dev fallback, and drop the ld.so.conf.d file and the
ldconfig/try-restart postinst entirely (the .so is present at its absolute path right
after unpack, so the pre-warm resolves with no linker-cache step). The dlopen site is
this PR's own code, so this is in scope, not a follow-up.
6a: extract the _drm admission bound and the per-frame re-auth decision into pure
helpers (drm_conn_admitted, drm_peer_authorized) and unit-test them: admission admits
strictly below MAX_DRM_CONNS and rejects at/above it; re-auth passes root always,
passes a non-root peer only while it equals the active-session uid, and fails closed on
a switched-away, unknown-session, or unknown-peer case. (The /proc/exe-mismatch
rejection is exercised by the accept-time authorize call; unit-testing it in isolation
would need a second process with a different exe, so it stays an integration concern.)
The dlopened .so is loaded into the CAP_SYS_ADMIN root service, so it should come
from the maintainer-owned repo, not a personal fork. rustdesk-org/libdrmtap main is
already synced to the exact commit we pin (c9cf0938 = v0.4.13) but carries no release
tag, so point both build.py and the CI job at rustdesk-org and track main with the
immutable commit pinned via DRMTAP_SHA. The post-clone sha check makes this
fail-closed: main moving off the pinned commit fails the build instead of silently
swapping the .so. The CI ref guard now accepts a vX.Y.Z tag or main (a loose branch is
still rejected). Switch DRMTAP_REF to a tag if rustdesk-org later publishes one.
3.1: snapshot the stock flutter bundle before the CI drm relink and restore it
before makepkg, so the official Arch package ships the stock cdylib, not the
drm-enabled one. 4.2: wrap the drm block in a failure-tolerant subshell so a
drm-only failure no longer aborts the stock deb/rpm/arch publish. 4.3: narrow the
publish glob to rustdesk-[0-9]*.deb so the consent-bypass unattended-wayland deb
stays an artifact, not on the public release. 4.4: rewrite the three stale
DRM_CAPTURE_SECURITY.md statements to the split (default path passes a read-only
scanout dma-buf fd over SCM_RIGHTS with an import-once cache; export validation is
metadata-only; BGRA-over-the-wire is the fallback) and document that grab_desc's
fd is O_RDONLY (DRM_RDWR dropped upstream, dup preserves it). 4.7: only
short-circuit to the DRM cursor when it is authoritative (visible, or hidden in a
pure-DRM session); fall through to the normal cursor path in a mixed
DRM+PipeWire session. minors: thread the deb variant by feature not glob; TODO
for the ld.so.conf.d system path; drop a stray blank line. All gated or
whitespace so the drm-off build stays byte-identical.
since libdrmtap 0.4.11 the project builds both a shared object and a static
archive, so 'meson compile drmtap' is ambiguous. ask for drmtap:shared_library
(rustdesk dlopens the .so and never links the archive).
gate the commit-SHA pin check on third_party/libdrmtap being a git checkout, so a
clone (fresh, reused, or a stale/failed one) is still verified, but a non-git
source tree a developer placed there on purpose to build unreleased local
libdrmtap is used as-is (it has no tag to verify).
1- verify the commit-SHA pin on a reused checkout too, not only on a fresh clone:
a stale or mismatched third_party/libdrmtap (e.g. from a failed clone) is now
removed and the build fails instead of silently reusing unpinned source.
2- default DRMTAP_REPO to the fork that actually publishes the pinned tag, so a
clean git clone --branch v0.4.13 resolves (and to the expected commit) instead of
failing on a repo that does not carry the tag.
1- make PipeWire init atomic: build every per-display capturer into owned staging
first and publish them to CAP_DISPLAY_INFO only after all succeed, so a mid-loop
Capturer::new failure neither leaves partial entries (which the next check_init
would treat as already-initialized) nor leaks the raw pointers already created.
2- pin the immutable libdrmtap commit, not just the tag: git clone --branch
follows a mutable tag, so verify the cloned HEAD equals DRMTAP_SHA in both the CI
workflow and build.py, failing on a moved/compromised tag.
3- drop the stale comment claiming a libdrmtap-sys crate pin (the drm backend has
no such dependency).
1- do not depend on the libdrmtap-sys crate for the pin: its build.rs statically
compiles the whole libdrmtap C tree and a CAP_SYS_ADMIN helper and links
-ldrm/-lseccomp/-lcap, which defeats the runtime-dlopen model. keep drm a pure
dlopen backend and pin the .so by the build.py DRMTAP_REF release tag, guarded by
a strict vX.Y.Z regex. drops the now-moot Cargo.lock freshness CI checks.
2- render-node-less consumers no longer lose the stream: the --server signals
need_cpu on DrmStart when it cannot open a convert context, and the --service
streams the CPU-converted frame path for that connection instead of a dma-buf fd
the consumer cannot detile (which used to fall through to a PipeWire path nobody
can approve on an unattended seat).
3- mark PipeWire initialized only after every per-display capturer is created, so
a partial failure retries instead of the flag falsely reporting a complete init.
4- reject a degenerate (zero width/height) or short CPU frame before it reaches
PixelBuffer::new (which derives stride as data.len()/height, dividing by zero).
5- keep the export-ledger epoch at DRM_DISPLAY_GENERATION so a hotplug invalidates
cached buffers (elision stays off until the recycled-fb_id inode case is handled).
6- validate the udev uevent source (kernel nl_pid, multicast) with recvmsg so a
local process cannot unicast a spoofed drm-change event to the root listener.
move the egl detile and rgba pack out of the root --service and into the
unprivileged --server. the root now calls only drmtap_open + drmtap_grab_desc
and exports a raw dma-buf fd; the fd rides the _drm channel over SCM_RIGHTS with
a small descriptor (geometry, per-plane offsets/pitches, modifier, hdr) instead
of the full rgba frame, dropping the per-frame copy. the --server imports the fd
with drmtap_open_render + drmtap_convert_dmabuf, keyed by the import-once egl
cache, and the render context is created and dropped on the recv thread.
the _drm transport moves off Framed<BytesCodec> (which cannot carry a fd) to a
bespoke sendmsg/recvmsg framing (DrmConn) that attaches one SCM_RIGHTS cmsg only
when a fd is present and rejects a truncated ancillary message. the split
symbols are bound optionally so an older libdrmtap still loads the cpu path, and
the whole thing degrades to the cpu BGRA path or PipeWire when no render node is
available. pins libdrmtap-sys to =0.4.13 with the Cargo.lock checksum. folds in
the DP-MST, ldconfig-restart and per-display PipeWire-fallback review fixes and a
udev hotplug refresh.
adds an opt-in `drm` feature for unattended remote access on Wayland: it
captures below the compositor via libdrmtap, so there is no
xdg-desktop-portal consent dialog and it works at the login screen.
off by default. when the feature is off the build is byte-identical.
everything is gated behind feature = "drm" or lives only in the separate
rustdesk-unattended-wayland deb, whose package name is the informed consent.
architecture (agreed with the maintainer): the capture runs inside the root
--service, which already holds the privilege it needs, and streams frames to
the user --server over a service-scoped _drm ipc channel. libdrmtap is loaded
with dlopen at runtime (no link-time dependency, so the base build is
unchanged and it still runs on ubuntu 18), and the .so is built in ci from the
rustdesk-org/libdrmtap fork and shipped only in the drm deb. no setcap helper.
- service: DrmReader reads scanout directly via the dlopen loader; an
IpcDrmCapturer serves _drm consumers with a per-connection capture worker;
durable availability cache + pre-warm to avoid enumerate/re-probe restarts
- capture: multi-display (targets the selected crtc), hardware cursor over
_drm, transient-errno retry with a bounded stall, rejects non-32bpp scanouts
before the frame copy
- robustness: only active, crtc-bound outputs are offered (an unbound
crtc_id=0 connector is filtered and a client-selected 0 is refused, both
fall back to pipewire); a per-display rapid-rebuild guard demotes a flapping
display to pipewire; per-display (not global) zero-frame failure tracking
- root-service hardening: bounded frame allocation and a concurrent-connection
cap so a malformed scanout or a buggy consumer cannot OOM or thread-exhaust
the service; a negative availability verdict expires so displays that appear
after startup recover without a --server restart; exactly-one .so selection
in the packaging so a stale object is never silently shipped
- build: libdrmtap.so cloned at build time from rustdesk-org/libdrmtap main
and bundled only for the --drm deb; ci builds a separate
rustdesk-unattended-wayland deb (incl. an ubuntu 18.04 container)
- DRM_CAPTURE_SECURITY.md: threat model and hardening notes
* Add initial arm64 build logic
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Upgrade Flutter to 3.44.0 and introduce Windows arm64 in CI
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Bump bridge build to Flutter 3.44 as well
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Fix install flutter step for Win arm64
* Bump install-llvm-action to v2 for arm64 support
* Fix libsodium logic to only install through vcpkg on win arm64
* Fix Flutter installations on Win
* Flutter XCode: only build the current arch as it defaults to universal
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Ensure that we really have arm64 Dart + Flutter engine in CI
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Enable hwcodec feature now that upstream supports building it
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* CI: improve logic for getting Flutter arm64 SDK
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Apply PR feedback (only bump Flutter version on Win arm64)
* Exclude MSI build on arm64
* CI: build the MSI for Windows arm64 (WiX v4 ARM64 platform + native CustomActions)
* Address PR feedback
* Update Cargo.toml
* Update Cargo.lock
* Update Cargo.lock
* Add Flutter 3.44 DialogThemeData background colors
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
Debian 13 Trixie and Ubuntu 24.04 Noble come with time64 transitioned packages: https://wiki.debian.org/ReleaseGoals/64bit-time
This means, all packages with use the time_t syscall on 32-bit do now use the time64 syscall instead, to get 64-bit year 2038 prove UNIX time values. Those packages get a "t64" suffix for their name, also for 64-bit architectures for consistency. Since time_t values on 64-bit are 64-bit already, no actual change happened there, and a package dependency without the t64 suffix is still satisfied by the packages with t64 suffix, via "Provides" attribute. This however is not he case for 32-bit.
The rustdesk package currently depends on libgtk-3-0 and libasound2, while Debian Trixie and Ubuntu Noble serve libgtk-3-0t64 and libasound2t64. On 64-bit architectures (amd64 and arm64), the available packages satisfy the dependency, but on 32-bit (armhf) this is not the case. In turn the rustdesk armv7-sciter.deb package cannot be installed on recent distro versions.
This commit solves the issue by adding the respective t64 packages are alternative dependency. If available, the t64 package is installed, else (on older distro versions), the one without t64 suffix.
Signed-off-by: MichaIng <micha@dietpi.com>
1. Linux dynamic load libva, which can fix lack of libva dependency for
appimage or flatpak, also fix libva version mismatch between build
and run.
2. Remove libvdpau, it's not used, and add libva2 explicitly for deb and
appimage
3. Print FFmpeg configure log to know the actual codecs.
Test
* ubuntu 22.04 x64
- [x] deb
- [x] flatpak
- [x] appimage
* ubuntu 18.04
* deb: fcntl64 not found
- [x]:appimage
- [ ]: platpak
hwcodec example:
- [x]: combination of lacking any of libva2, libva-x11-2, libva-drm2,
intel-media-va-driver
- [ ] federa
- [ ] arch
- [ ] arm64: my ci can't finish arm64 building
Signed-off-by: 21pages <sunboeasy@gmail.com>
* Fix https://github.com/rustdesk/rustdesk/issues/9286, replace pkexec
with gtk sudo. Tested on gnome (ubuntu 22.04, debian 13), xfce (manjaro, suse), kde (kubuntu 23), lxqt (lubuntu 22), Cinnamon (mint 21.3), Mate (mint 21.2)
* Fix incorrect config of the main window opened by the tray, replace
xdg-open with run_me, replace with dbus + run_me
* Fix `check_if_stop_service`, it causes the problem fixed in
https://github.com/rustdesk/rustdesk/pull/8414, now revert that fix and fix itself.
Signed-off-by: 21pages <sunboeasy@gmail.com>
* update hwcodec, gpucodec repo is merged to hwcodec
Signed-off-by: 21pages <pages21@163.com>
* rename gpucodec.rs to vram.rs
Signed-off-by: 21pages <pages21@163.com>
* rename all gpucodec to vram, because vram is a feature of hwcodec
Signed-off-by: 21pages <pages21@163.com>
* use one check process and one config file
* set check encode image size to 720p
Signed-off-by: 21pages <pages21@163.com>
---------
Signed-off-by: 21pages <pages21@163.com>