svn commit: r344984 - in stable/11: sbin/sysctl sys/dev/evdev
Vladimir Kondratyev
wulf at FreeBSD.org
Sun Mar 10 20:58:25 UTC 2019
Author: wulf
Date: Sun Mar 10 20:58:24 2019
New Revision: 344984
URL: https://svnweb.freebsd.org/changeset/base/344984
Log:
MFC r344494,r344495:
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 at unrelenting.technology>
Reviewed by: wulf, imp
Differential Revision: https://reviews.freebsd.org/D18694
Modified:
stable/11/sbin/sysctl/sysctl.c
stable/11/sys/dev/evdev/evdev.c
stable/11/sys/dev/evdev/evdev_private.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sbin/sysctl/sysctl.c
==============================================================================
--- stable/11/sbin/sysctl/sysctl.c Sun Mar 10 20:43:08 2019 (r344983)
+++ stable/11/sbin/sysctl/sysctl.c Sun Mar 10 20:58:24 2019 (r344984)
@@ -47,6 +47,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>
@@ -678,6 +679,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)
@@ -1097,6 +1114,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;
Modified: stable/11/sys/dev/evdev/evdev.c
==============================================================================
--- stable/11/sys/dev/evdev/evdev.c Sun Mar 10 20:43:08 2019 (r344983)
+++ stable/11/sys/dev/evdev/evdev.c Sun Mar 10 20:58:24 2019 (r344984)
@@ -67,14 +67,16 @@ MALLOC_DEFINE(M_EVDEV, "evdev", "evdev memory");
int evdev_rcpt_mask = EVDEV_RCPT_SYSMOUSE | EVDEV_RCPT_KBDMUX;
int evdev_sysmouse_t_axis = 0;
-#ifdef EVDEV_SUPPORT
SYSCTL_NODE(_kern, OID_AUTO, evdev, CTLFLAG_RW, 0, "Evdev args");
+#ifdef EVDEV_SUPPORT
SYSCTL_INT(_kern_evdev, OID_AUTO, rcpt_mask, CTLFLAG_RW, &evdev_rcpt_mask, 0,
"Who is receiving events: bit0 - sysmouse, bit1 - kbdmux, "
"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");
#endif
+SYSCTL_NODE(_kern_evdev, OID_AUTO, input, CTLFLAG_RD, 0,
+ "Evdev input devices");
static void evdev_start_repeat(struct evdev_dev *, uint16_t);
static void evdev_stop_repeat(struct evdev_dev *);
@@ -194,6 +196,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)
{
@@ -233,6 +316,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);
}
@@ -269,6 +358,8 @@ evdev_unregister(struct evdev_dev *evdev)
int ret;
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;
Modified: stable/11/sys/dev/evdev/evdev_private.h
==============================================================================
--- stable/11/sys/dev/evdev/evdev_private.h Sun Mar 10 20:43:08 2019 (r344983)
+++ stable/11/sys/dev/evdev/evdev_private.h Sun Mar 10 20:58:24 2019 (r344984)
@@ -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>
@@ -127,6 +128,9 @@ struct evdev_dev
/* Parent driver callbacks: */
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;
More information about the svn-src-all
mailing list