From: Peter Hutterer Date: Tue, 12 Apr 2022 04:48:04 +0000 (+1000) Subject: logind: add support for hidraw devices X-Git-Tag: v257-rc1~334 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=305272ab2b62a031a91ed3490cb053bee0594964;p=thirdparty%2Fsystemd.git logind: add support for hidraw devices Add support for opening /dev/hidraw devices via logind's TakeDevice(). Same semantics as our support for evdev devices, but it requires the HIDIOCREVOKE ioctl in the kernel. --- diff --git a/rules.d/71-seat.rules.in b/rules.d/71-seat.rules.in index 1fd7ec23b09..8cc904c2829 100644 --- a/rules.d/71-seat.rules.in +++ b/rules.d/71-seat.rules.in @@ -12,6 +12,7 @@ ACTION=="remove", GOTO="seat_end" TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" +SUBSYSTEM=="hidraw", KERNEL=="hidraw*", TAG+="seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat" # Assign keyboard and LCD backlights to the seat diff --git a/src/basic/missing_hidraw.h b/src/basic/missing_hidraw.h new file mode 100644 index 00000000000..98ba5c019a2 --- /dev/null +++ b/src/basic/missing_hidraw.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include + +/* b31c9d9dc343146b9f4ce67b4eee748c49296e99 (6.12) */ +#ifndef HIDIOCREVOKE +#define HIDIOCREVOKE _IOW('H', 0x0D, int) +#endif diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index 2aff0b7c8c3..adea60aef6b 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -16,6 +16,7 @@ #include "logind-session-dbus.h" #include "logind-session-device.h" #include "missing_drm.h" +#include "missing_hidraw.h" #include "missing_input.h" #include "parse-util.h" @@ -105,6 +106,20 @@ static void sd_eviocrevoke(int fd) { } } +static void sd_hidiocrevoke(int fd) { + static bool warned = false; + + assert(fd >= 0); + + if (!warned && ioctl(fd, HIDIOCREVOKE, NULL) < 0) { + if (errno == EINVAL) { + log_warning_errno(errno, "Kernel does not support hidraw-revocation, continuing without revoking device access: %m"); + warned = true; + } else if (errno != ENODEV) + log_warning_errno(errno, "Failed to revoke hidraw device, continuing without revoking device access: %m"); + } +} + static int sd_drmsetmaster(int fd) { assert(fd >= 0); return RET_NERRNO(ioctl(fd, DRM_IOCTL_SET_MASTER, 0)); @@ -148,6 +163,11 @@ static int session_device_open(SessionDevice *sd, bool active) { sd_eviocrevoke(fd); break; + case DEVICE_TYPE_HIDRAW: + if (!active) + sd_hidiocrevoke(fd); + break; + case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices without synchronizations */ @@ -181,12 +201,13 @@ static int session_device_start(SessionDevice *sd) { break; case DEVICE_TYPE_EVDEV: - /* Evdev devices are revoked while inactive. Reopen it and we are fine. */ + case DEVICE_TYPE_HIDRAW: + /* Evdev/hidraw devices are revoked while inactive. Reopen it and we are fine. */ r = session_device_open(sd, true); if (r < 0) return r; - /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming + /* For evdev/hidraw devices, the file descriptor might be left uninitialized. This might happen while resuming * into a session and logind has been restarted right before. */ close_and_replace(sd->fd, r); break; @@ -230,6 +251,14 @@ static void session_device_stop(SessionDevice *sd) { sd_eviocrevoke(sd->fd); break; + case DEVICE_TYPE_HIDRAW: + /* Revoke access on hidraw file-descriptors during deactivation. + * This will basically prevent any operations on the fd and + * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN + * protection this way. */ + sd_hidiocrevoke(sd->fd); + break; + case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices without synchronization */ @@ -252,6 +281,9 @@ static DeviceType detect_device_type(sd_device *dev) { } else if (device_in_subsystem(dev, "input")) { if (startswith(sysname, "event")) return DEVICE_TYPE_EVDEV; + } else if (device_in_subsystem(dev, "hidraw")) { + if (startswith(sysname, "hidraw")) + return DEVICE_TYPE_HIDRAW; } return DEVICE_TYPE_UNKNOWN; @@ -289,6 +321,7 @@ static int session_device_verify(SessionDevice *sd) { break; case DEVICE_TYPE_DRM: + case DEVICE_TYPE_HIDRAW: break; case DEVICE_TYPE_UNKNOWN: diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h index 06a8f80c060..1c6f12f21b1 100644 --- a/src/login/logind-session-device.h +++ b/src/login/logind-session-device.h @@ -11,6 +11,7 @@ enum DeviceType { DEVICE_TYPE_UNKNOWN, DEVICE_TYPE_DRM, DEVICE_TYPE_EVDEV, + DEVICE_TYPE_HIDRAW, }; struct SessionDevice { diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index cc1b6be429c..9a918bf0b63 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -27,6 +27,7 @@ CapabilityBoundingSet=CAP_SYS_ADMIN CAP_MAC_ADMIN CAP_AUDIT_CONTROL CAP_CHOWN CA DeviceAllow=block-* r DeviceAllow=char-/dev/console rw DeviceAllow=char-drm rw +DeviceAllow=char-hidraw rw DeviceAllow=char-input rw DeviceAllow=char-tty rw DeviceAllow=char-vcs rw