evdev: export event device properties through sysctl interface
A big security advantage of Wayland is not allowing applications to read input devices all the time. Having /dev/input/* accessible to the user account subverts this advantage. libudev-devd was opening the evdev devices to detect their types (mouse, keyboard, touchpad, etc). This don't work if /dev/input/* is inaccessible. With the kernel exposing this information as sysctls (kern.evdev.input.*), we can work w/o /dev/input/* access, preserving the Wayland security model. Submitted by: Greg V <greg@unrelenting.technology> Reviewed by: wulf, imp MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D18694
This commit is contained in:
parent
9b119019bf
commit
fea6adbc28
@ -49,6 +49,7 @@ static const char rcsid[] =
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#include <dev/evdev/input.h>
|
||||
|
||||
#ifdef __amd64__
|
||||
#include <sys/efi.h>
|
||||
@ -680,6 +681,22 @@ S_vmtotal(size_t l2, void *p)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
S_input_id(size_t l2, void *p)
|
||||
{
|
||||
struct input_id *id = p;
|
||||
|
||||
if (l2 != sizeof(*id)) {
|
||||
warnx("S_input_id %zu != %zu", l2, sizeof(*id));
|
||||
return (1);
|
||||
}
|
||||
|
||||
printf("{ bustype = 0x%04x, vendor = 0x%04x, "
|
||||
"product = 0x%04x, version = 0x%04x }",
|
||||
id->bustype, id->vendor, id->product, id->version);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef __amd64__
|
||||
static int
|
||||
S_efi_map(size_t l2, void *p)
|
||||
@ -983,6 +1000,8 @@ show_var(int *oid, int nlen)
|
||||
func = S_loadavg;
|
||||
else if (strcmp(fmt, "S,vmtotal") == 0)
|
||||
func = S_vmtotal;
|
||||
else if (strcmp(fmt, "S,input_id") == 0)
|
||||
func = S_input_id;
|
||||
#ifdef __amd64__
|
||||
else if (strcmp(fmt, "S,efi_map_header") == 0)
|
||||
func = S_efi_map;
|
||||
|
@ -76,6 +76,8 @@ SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0,
|
||||
"bit2 - mouse hardware, bit3 - keyboard hardware");
|
||||
SYSCTL_INT(_kern_evdev, OID_AUTO, sysmouse_t_axis, CTLFLAG_RW,
|
||||
&evdev_sysmouse_t_axis, 0, "Extract T-axis from 0-none, 1-ums, 2-psm");
|
||||
SYSCTL_NODE(_kern_evdev, OID_AUTO, input, CTLFLAG_RD, 0,
|
||||
"Evdev input devices");
|
||||
#endif
|
||||
|
||||
static void evdev_start_repeat(struct evdev_dev *, uint16_t);
|
||||
@ -196,6 +198,87 @@ evdev_estimate_report_size(struct evdev_dev *evdev)
|
||||
return (size);
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_sysctl_create(struct evdev_dev *evdev)
|
||||
{
|
||||
struct sysctl_oid *ev_sysctl_tree;
|
||||
char ev_unit_str[8];
|
||||
|
||||
snprintf(ev_unit_str, sizeof(ev_unit_str), "%d", evdev->ev_unit);
|
||||
sysctl_ctx_init(&evdev->ev_sysctl_ctx);
|
||||
|
||||
ev_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_STATIC_CHILDREN(_kern_evdev_input), OID_AUTO,
|
||||
ev_unit_str, CTLFLAG_RD, NULL, "", "device index");
|
||||
|
||||
SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "name", CTLFLAG_RD,
|
||||
evdev->ev_name, 0,
|
||||
"Input device name");
|
||||
|
||||
SYSCTL_ADD_STRUCT(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "id", CTLFLAG_RD,
|
||||
&evdev->ev_id, input_id,
|
||||
"Input device identification");
|
||||
|
||||
/* ioctl returns ENOENT if phys is not set. sysctl returns "" here */
|
||||
SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "phys", CTLFLAG_RD,
|
||||
evdev->ev_shortname, 0,
|
||||
"Input device short name");
|
||||
|
||||
/* ioctl returns ENOENT if uniq is not set. sysctl returns "" here */
|
||||
SYSCTL_ADD_STRING(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "uniq", CTLFLAG_RD,
|
||||
evdev->ev_serial, 0,
|
||||
"Input device unique number");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "props", CTLFLAG_RD,
|
||||
evdev->ev_prop_flags, sizeof(evdev->ev_prop_flags), "",
|
||||
"Input device properties");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "type_bits", CTLFLAG_RD,
|
||||
evdev->ev_type_flags, sizeof(evdev->ev_type_flags), "",
|
||||
"Input device supported events types");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "key_bits", CTLFLAG_RD,
|
||||
evdev->ev_key_flags, sizeof(evdev->ev_key_flags),
|
||||
"", "Input device supported keys");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "rel_bits", CTLFLAG_RD,
|
||||
evdev->ev_rel_flags, sizeof(evdev->ev_rel_flags), "",
|
||||
"Input device supported relative events");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "abs_bits", CTLFLAG_RD,
|
||||
evdev->ev_abs_flags, sizeof(evdev->ev_abs_flags), "",
|
||||
"Input device supported absolute events");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "msc_bits", CTLFLAG_RD,
|
||||
evdev->ev_msc_flags, sizeof(evdev->ev_msc_flags), "",
|
||||
"Input device supported miscellaneous events");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "led_bits", CTLFLAG_RD,
|
||||
evdev->ev_led_flags, sizeof(evdev->ev_led_flags), "",
|
||||
"Input device supported LED events");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "snd_bits", CTLFLAG_RD,
|
||||
evdev->ev_snd_flags, sizeof(evdev->ev_snd_flags), "",
|
||||
"Input device supported sound events");
|
||||
|
||||
SYSCTL_ADD_OPAQUE(&evdev->ev_sysctl_ctx,
|
||||
SYSCTL_CHILDREN(ev_sysctl_tree), OID_AUTO, "sw_bits", CTLFLAG_RD,
|
||||
evdev->ev_sw_flags, sizeof(evdev->ev_sw_flags), "",
|
||||
"Input device supported switch events");
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_register_common(struct evdev_dev *evdev)
|
||||
{
|
||||
@ -235,6 +318,12 @@ evdev_register_common(struct evdev_dev *evdev)
|
||||
|
||||
/* Create char device node */
|
||||
ret = evdev_cdev_create(evdev);
|
||||
if (ret != 0)
|
||||
goto bail_out;
|
||||
|
||||
/* Create sysctls (for device enumeration without /dev/input access rights) */
|
||||
evdev_sysctl_create(evdev);
|
||||
|
||||
bail_out:
|
||||
return (ret);
|
||||
}
|
||||
@ -272,6 +361,8 @@ evdev_unregister(struct evdev_dev *evdev)
|
||||
debugf(evdev, "%s: unregistered evdev provider: %s\n",
|
||||
evdev->ev_shortname, evdev->ev_name);
|
||||
|
||||
sysctl_ctx_free(&evdev->ev_sysctl_ctx);
|
||||
|
||||
EVDEV_LOCK(evdev);
|
||||
evdev->ev_cdev->si_drv1 = NULL;
|
||||
/* Wake up sleepers */
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/evdev/evdev.h>
|
||||
#include <dev/evdev/input.h>
|
||||
@ -132,6 +133,9 @@ struct evdev_dev
|
||||
const struct evdev_methods * ev_methods;
|
||||
void * ev_softc;
|
||||
|
||||
/* Sysctl: */
|
||||
struct sysctl_ctx_list ev_sysctl_ctx;
|
||||
|
||||
LIST_ENTRY(evdev_dev) ev_link;
|
||||
LIST_HEAD(, evdev_client) ev_clients;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user