Skip to content

Refactor fm-shim to use D-Bus forwarding instead of CLI invocation#361

Closed
assisted-by-ai wants to merge 2 commits intoKicksecure:masterfrom
assisted-by-ai:claude/build-fm-shim-backend-C7WRa
Closed

Refactor fm-shim to use D-Bus forwarding instead of CLI invocation#361
assisted-by-ai wants to merge 2 commits intoKicksecure:masterfrom
assisted-by-ai:claude/build-fm-shim-backend-C7WRa

Conversation

@assisted-by-ai
Copy link
Copy Markdown

Summary

This PR refactors the fm-shim file manager handler to eliminate a TOCTOU (Time-of-Check-Time-of-Use) vulnerability by forwarding confirmed file manager requests to pcmanfm-qt via D-Bus instead of CLI invocation. The frontend is now a confirmation-only dialog, with the backend handling the actual file manager launch.

Key Changes

Backend (fm-shim-backend.c):

  • Refactored launch_frontend_process() into separate functions:
    • get_systemd_environment(): Fetches environment from systemd's user manager on each request
    • launch_frontend(): Forks and execs the confirmation dialog, returns child PID
    • launch_pcmanfm_qt_daemon(): Starts pcmanfm-qt in daemon mode using double-fork to avoid zombies
    • wait_for_dbus_name_owner(): Polls until pcmanfm-qt claims the D-Bus name
    • forward_dbus_request(): Forwards the original request via D-Bus ShowFolders/ShowItems/ShowItemProperties
  • Changed SIGCHLD handling from SIG_IGN to SIG_DFL to enable waitpid() for the frontend process
  • Implemented the core workflow:
    1. Release the D-Bus name so pcmanfm-qt can claim it
    2. Start pcmanfm-qt in daemon mode
    3. Wait for pcmanfm-qt to claim the name
    4. Forward the request via D-Bus (eliminates TOCTOU vulnerability)
    5. Re-request the name (queued behind pcmanfm-qt)
  • Updated comments to document the new architecture and security rationale
  • Fixed typo: "return" → "returns" in existing comment

Frontend (fm_shim_frontend.py):

  • Simplified to confirmation-only dialog
  • Removed all file manager launching logic (desktop file lookup, gio launch, TOCTOU checks)
  • Removed subprocess and QMessageBox imports
  • open_dir_list() now simply exits with code 0 to signal confirmation
  • exit_app() now exits with code 1 to signal cancellation
  • Updated docstrings to reflect new role

New Files:

  • etc/xdg/autostart/security-misc-dbus-env-sync.desktop: Autostart script that syncs session environment to D-Bus and systemd user manager via dbus-update-activation-environment --systemd --all
  • usr/share/dbus-1/services/org.freedesktop.FileManager1.service: D-Bus service activation file for fm-shim-backend

Notable Implementation Details

  • Environment variables are fetched from systemd's user manager on each request, allowing environment updates (e.g., from dbus-update-activation-environment) to be picked up without restarting the service
  • Double-fork technique used for pcmanfm-qt daemon launch to avoid zombie processes
  • D-Bus name ownership is carefully managed: released before launching pcmanfm-qt, then re-requested to queue behind it
  • Timeout and polling constants added for waiting on pcmanfm-qt name ownership
  • All error paths properly clean up allocated memory and D-Bus resources

https://claude.ai/code/session_01SAkV8U9vft3vzZAyJfzXGE

claude added 2 commits April 9, 2026 10:50
Root cause fixes for fm-shim issues on Qubes OS:

1. Backend: Transform from full intercepting proxy into D-Bus activation
   proxy (marmarek's suggestion). On confirmed request, release the
   FileManager1 name, start pcmanfm-qt --daemon-mode, and forward the
   request via D-Bus ShowFolders. This eliminates the TOCTOU
   vulnerability that existed with CLI invocation (gio launch).

2. Backend: Fix name ownership handling. When another process already
   owns org.freedesktop.FileManager1 (e.g. pcmanfm-qt in daemon mode),
   send READY=1 so systemd does not time out the service. The shim
   stays queued and takes over when the current owner exits.

3. Frontend: Simplify to confirmation-only dialog. Exit code 0 = user
   confirmed (backend handles D-Bus forwarding), exit code 1 = user
   cancelled. Remove all xdg-mime query and gio launch code.

4. Add XDG autostart entry that runs dbus-update-activation-environment
   --systemd --all at session start. This syncs the session environment
   to systemd's user manager, fixing the stale XDG_DATA_DIRS that caused
   xdg-mime to return Catfish instead of pcmanfm-qt on Qubes OS.

5. Add D-Bus service activation file for org.freedesktop.FileManager1
   so the shim can be started on-demand by D-Bus.

https://forums.whonix.org/t/is-catfish-the-new-default-in-the-qubes-domain-open-file-manager-quick-widget-for-whonix/20233

https://claude.ai/code/session_01SAkV8U9vft3vzZAyJfzXGE
The stale systemd user manager environment on Qubes OS is a Qubes bug
(QubesOS/qubes-issues), not a security-misc bug. Working around it
here is fixing the issue in the wrong place.

The D-Bus forwarding approach already eliminates the dependency on
xdg-mime (which was the component affected by stale XDG_DATA_DIRS),
so the env mismatch no longer causes Catfish to open.

https://claude.ai/code/session_01SAkV8U9vft3vzZAyJfzXGE
@adrelanos
Copy link
Copy Markdown
Member

Superseded by assisted-by-ai#7

@adrelanos adrelanos closed this Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants