1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

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.
This commit is contained in:
Peter Hutterer 2022-04-12 14:48:04 +10:00 committed by Luca Boccassi
parent 16b50d4018
commit 305272ab2b
5 changed files with 47 additions and 2 deletions

View File

@ -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

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <linux/hidraw.h>
/* b31c9d9dc343146b9f4ce67b4eee748c49296e99 (6.12) */
#ifndef HIDIOCREVOKE
#define HIDIOCREVOKE _IOW('H', 0x0D, int)
#endif

View File

@ -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:

View File

@ -11,6 +11,7 @@ enum DeviceType {
DEVICE_TYPE_UNKNOWN,
DEVICE_TYPE_DRM,
DEVICE_TYPE_EVDEV,
DEVICE_TYPE_HIDRAW,
};
struct SessionDevice {

View File

@ -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