Skip to content

Wayland input blocking via setuid EVIOCGRAB daemon - #1145

Merged
tobydox merged 3 commits into
veyon:mainfrom
NICourced:fix-screenlock
Jul 8, 2026
Merged

tobydox merged 3 commits into
veyon:mainfrom
NICourced:fix-screenlock

Conversation

@NICourced

Copy link
Copy Markdown
Contributor

Add a privileged daemon (veyon-input-helper) that runs as root via setuid and listens on a Unix socket for block/unblock commands. The daemon uses EVIOCGRAB on /dev/input/event* to block physical input devices on Wayland where the Veyon Server runs as a regular user.

Components:

  • input-block-helper.c: setuid root daemon, Unix socket at /run/veyon/input-block.sock, select() event loop, sigsuspend for signal-safe wait, PR_SET_PDEATHSIG for orphan cleanup, auto-creates /run/veyon directory and socket with world-readable permissions
  • InputBlockHelper: Qt wrapper using QLocalSocket to communicate with the daemon, spawns/terminates the daemon process, retry-after-spawn for socket readiness, killall fallback for cleaning up stale daemons
  • LinuxInputDeviceFunctions: delegates Wayland blocking to InputBlockHelper; enableInputDevices() always runs unblock on Wayland to handle startup cleanup
  • ScreenLockFeaturePlugin: calls disableInputDevices() directly from the server on StartLock (in addition to forwarding to the worker for the visual LockWidget); StopLock always calls enableInputDevices() regardless of worker state; cleanup runs on both Service and Server component startup
  • PipeWireVncServer: newClientHook/clientGoneHook set after rfbInitServer to avoid being overwritten, manages VeyonCore::isRemoteControlActive() flag for underControl tracking
  • VeyonCore: added isRemoteControlActive()/setRemoteControlActive()
  • LinuxServerProcess: suppress unused-result warnings (seteuid/setgid/setuid)
  • LinuxKeyboardInput: suppress unused-result warnings (write)

Now on wayland on locking student's screen widget wont open in fullscreen, but all student's input will be locked, but teacher still has remote control, so remote control can be with or without student's input.

}
// Block input devices immediately — worker handles the visual LockWidget
VeyonCore::platform().inputDeviceFunctions().disableInputDevices();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work on the X11 path, i.e. does veyon-server (running as root) have proper access to the X11 socket of the user session etc.?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, didnt test X11

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It surely does not work

{
VeyonCore::setRemoteControlActive(true);
VeyonCore::platform().inputDeviceFunctions().disableInputDevices();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this new behavior may be desired in some scenarios, it should not be default, especially since every client (even just the monitoring mode in Veyon Master) counts as client and even just opening Veyon Master without remote control would block the input devices.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

@tobydox

tobydox commented Jul 1, 2026 •

Copy link
Copy Markdown
Member

So in general a good and welcome improvement (since it makes input device blocking work more reliably) but too intrusive at the moment ;-) It should not block on every connection and we have to take care of X11 compatibility (while of course blocking devices at the uinput layer should work here as well).

@NICourced

Copy link
Copy Markdown
Contributor Author

Thanks, it's going to be improved (:

@NICourced

Copy link
Copy Markdown
Contributor Author

Now correctly blocks on x11, remote control works on blocked device.

Comment thread core/src/VeyonCore.h
instance()->m_remoteControlActive = active;
}

static BuiltinFeatures& builtinFeatures()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can drop this as well


/* Allow any user to connect */
chmod(SOCKET_PATH, 0666);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a potential security issue? Any chance we can make this more strict such that it's guaranteed that only the input-block-helper instance forked by veyon-server can communicate through this (SO_PEERCRED)? Once merged we should also discuss about how we can make this multi-seat capable, i.e. if multiple veyon-server instances are running (for different sessions). But that's a special case e.g. for remote desktop servers.

@tobydox

tobydox commented Jul 3, 2026

Copy link
Copy Markdown
Member

Thanks again for continueing this! I'd like to see the PR splitted, ideally in separate PRs-> separate Wayland input blocking improvements and changes to ScreenLockFeaturePlugin. The Wayland input blocking can be merged short term (to be part of the Veyon 4.11 release next week) while I'd like to have a deeper look and discussion about the other changes.

@NICourced

Copy link
Copy Markdown
Contributor Author

New pr created with only wayland realisation, this branch is 1 commit ahead of that, x11 blocking.

@NICourced

Copy link
Copy Markdown
Contributor Author

Thanks for merging my wayland pr, now there only x11 commit left.

The old setEmptyKeyMapTable() only blocked keyboard input by zeroing the
keymap — mouse and system shortcuts were unaffected, yet it interfered with
x11vnc's XTest-based keyboard injection during remote control.

Replace with XIGrabDevice from XInput2:
- Query all slave devices (XIQueryDevice) and grab each physical slave
  keyboard/pointer with XIGrabDevice(GrabModeAsync, owner_events=False)
- Explicitly skip the virtual 'XTEST' device so x11vnc's XTestFakeKeyEvent
  injection continues working during screen lock
@tobydox
tobydox merged commit e4d2aa8 into veyon:main Jul 8, 2026
@NICourced
NICourced deleted the fix-screenlock branch July 9, 2026 11:21
@tobydox

tobydox commented Jul 10, 2026

Copy link
Copy Markdown
Member

FYI: I omitted the changed input device blocking on X11 via XIGrabDevice() since it did not grab Ctrl+Alt+Fx so users could switch to VTs, login and unlock the computer.

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.

2 participants