Commit Graph

172 Commits

Author SHA1 Message Date
Kees Cook
331415ff16 HID: provide a helper for validating hid reports
Many drivers need to validate the characteristics of their HID report
during initialization to avoid misusing the reports. This adds a common
helper to perform validation of the report exisitng, the field existing,
and the expected number of values within the field.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-09-13 15:11:21 +02:00
Jiri Kosina
63faf15dba Merge branches 'for-3.12/devm', 'for-3.12/i2c-hid', 'for-3.12/i2c-hid-dt', 'for-3.12/logitech', 'for-3.12/multitouch-win8', 'for-3.12/trasnport-driver-cleanup', 'for-3.12/uhid', 'for-3.12/upstream' and 'for-3.12/wiimote' into for-linus 2013-09-06 11:58:37 +02:00
David Herrmann
39054a5afb HID: move HID_REPORT_TYPES closer to the report-definitions
HID_REPORT_TYPES defines the number of available report-types. Move it
closer to the actualy definition of the report-types so we can see the
relation more clearly (and hopefully will never forget to update it).

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-09-04 12:12:53 +02:00
Jiri Kosina
47ab1a2de4 Merge branch 'for-3.11/CVE-2013-2888' into for-3.12/upstream
This one didn't make it for 3.11 due to being applied too close
to release, queue it for 3.12 merge window.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-09-04 12:06:58 +02:00
Kees Cook
43622021d2 HID: validate HID report id size
The "Report ID" field of a HID report is used to build indexes of
reports. The kernel's index of these is limited to 256 entries, so any
malicious device that sets a Report ID greater than 255 will trigger
memory corruption on the host:

[ 1347.156239] BUG: unable to handle kernel paging request at ffff88094958a878
[ 1347.156261] IP: [<ffffffff813e4da0>] hid_register_report+0x2a/0x8b

CVE-2013-2888

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: stable@kernel.org
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-08-29 11:01:25 +02:00
Benjamin Tissoires
595e9276ce HID: do not init input reports for Win 8 multitouch devices
Some multitouch screens do not like to be polled for input reports.
However, the Win8 spec says that all touches should be sent during
each report, making the initialization of reports unnecessary.
The Win7 spec is less precise, so do not use this for those devices.

Add the quirk HID_QUIRK_NO_INIT_INPUT_REPORTS so that we do not have to
introduce a quirk for each problematic device. This quirk makes the driver
behave the same way the Win 8 does. It actually retrieves the features,
but not the inputs.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Tested-by: Srinivas Pandruvada<srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-08-27 10:00:00 +02:00
Benjamin Tissoires
f961bd3516 HID: detect Win 8 multitouch devices in core
Detecting Win 8 multitouch devices in core allows us to set quirks
before the device is parsed through hid_hw_start().
It also simplifies the detection of those devices in hid-multitouch and
makes the handling of those devices cleaner.

As Win 8 multitouch panels are in the group multitouch and rely on a
special feature to be detected, this patch adds a bitfield in the parser.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Tested-by: Srinivas Pandruvada<srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-08-27 10:00:00 +02:00
David Herrmann
50c9d75b6f HID: input: generic hidinput_input_event handler
The hidinput_input_event() callback converts input events written from
userspace into HID reports and sends them to the device. We currently
implement this in every HID transport driver, even though most of them do
the same.

This provides a generic hidinput_input_event() implementation which is
mostly copied from usbhid. It uses a delayed worker to allow multiple LED
events to be collected into a single output event.
We use the custom ->request() transport driver callback to allow drivers
to adjust the outgoing report and handle the request asynchronously. If no
custom ->request() callback is available, we fall back to the generic raw
output report handler (which is synchronous).

Drivers can still provide custom hidinput_input_event() handlers (see
logitech-dj) if the generic implementation doesn't fit their needs.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-07-31 11:02:02 +02:00
David Herrmann
ddf64a3c03 HID: usbhid: make usbhid_set_leds() static
usbhid_set_leds() is only used inside of usbhid/hid-core.c so no need to
export it.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-07-31 10:24:08 +02:00
Jiri Kosina
27ce405039 HID: fix data access in implement()
implement() is setting bytes in LE data stream. In case the data is not
aligned to 64bits, it reads past the allocated buffer. It doesn't really
change any value there (it's properly bitmasked), but in case that this
read past the boundary hits a page boundary, pagefault happens when
accessing 64bits of 'x' in implement(), and kernel oopses.

This happens much more often when numbered reports are in use, as the
initial 8bit skip in the buffer makes the whole process work on values
which are not aligned to 64bits.

This problem dates back to attempts in 2005 and 2006 to make implement()
and extract() as generic as possible, and even back then the problem
was realized by Adam Kroperlin, but falsely assumed to be impossible
to cause any harm:

  http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg47690.html

I have made several attempts at fixing it "on the spot" directly in
implement(), but the results were horrible; the special casing for processing
last 64bit chunk and switching to different math makes it unreadable mess.

I therefore took a path to allocate a few bytes more which will never make
it into final report, but are there as a cushion for all the 64bit math
operations happening in implement() and extract().

All callers of hid_output_report() are converted at the same time to allocate
the buffer by newly introduced hid_alloc_report_buf() helper.

Bruno noticed that the whole raw_size test can be dropped as well, as
hid_alloc_report_buf() makes sure that the buffer is always of a proper
size.

Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-07-22 16:16:40 +02:00
Jiri Kosina
1deb9d341d HID: debug: fix RCU preemption issue
Commit 2353f2bea ("HID: protect hid_debug_list") introduced mutex
locking around debug_list access to prevent SMP races when debugfs
nodes are being operated upon by multiple userspace processess.

mutex is not a proper synchronization primitive though, as the hid-debug
callbacks are being called from atomic contexts.

We also have to be careful about disabling IRQs when taking the lock
to prevent deadlock against IRQ handlers.

Benjamin reports this has also been reported in RH bugzilla as bug #958935.

 ===============================
 [ INFO: suspicious RCU usage. ]
 3.9.0+ #94 Not tainted
 -------------------------------
 include/linux/rcupdate.h:476 Illegal context switch in RCU read-side critical section!

 other info that might help us debug this:

 rcu_scheduler_active = 1, debug_locks = 0
 4 locks held by Xorg/5502:
  #0:  (&evdev->mutex){+.+...}, at: [<ffffffff81512c3d>] evdev_write+0x6d/0x160
  #1:  (&(&dev->event_lock)->rlock#2){-.-...}, at: [<ffffffff8150dd9b>] input_inject_event+0x5b/0x230
  #2:  (rcu_read_lock){.+.+..}, at: [<ffffffff8150dd82>] input_inject_event+0x42/0x230
  #3:  (&(&usbhid->lock)->rlock){-.....}, at: [<ffffffff81565289>] usb_hidinput_input_event+0x89/0x120

 stack backtrace:
 CPU: 0 PID: 5502 Comm: Xorg Not tainted 3.9.0+ #94
 Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A09 07/24/2012
  0000000000000001 ffff8800689c7c38 ffffffff816f249f ffff8800689c7c68
  ffffffff810acb1d 0000000000000000 ffffffff81a03ac7 000000000000019d
  0000000000000000 ffff8800689c7c90 ffffffff8107cda7 0000000000000000
 Call Trace:
  [<ffffffff816f249f>] dump_stack+0x19/0x1b
  [<ffffffff810acb1d>] lockdep_rcu_suspicious+0xfd/0x130
  [<ffffffff8107cda7>] __might_sleep+0xc7/0x230
  [<ffffffff816f7770>] mutex_lock_nested+0x40/0x3a0
  [<ffffffff81312ac4>] ? vsnprintf+0x354/0x640
  [<ffffffff81553cc4>] hid_debug_event+0x34/0x100
  [<ffffffff81554197>] hid_dump_input+0x67/0xa0
  [<ffffffff81556430>] hid_set_field+0x50/0x120
  [<ffffffff8156529a>] usb_hidinput_input_event+0x9a/0x120
  [<ffffffff8150d89e>] input_handle_event+0x8e/0x530
  [<ffffffff8150df10>] input_inject_event+0x1d0/0x230
  [<ffffffff8150dd82>] ? input_inject_event+0x42/0x230
  [<ffffffff81512cae>] evdev_write+0xde/0x160
  [<ffffffff81185038>] vfs_write+0xc8/0x1f0
  [<ffffffff81185535>] SyS_write+0x55/0xa0
  [<ffffffff81704482>] system_call_fastpath+0x16/0x1b
 BUG: sleeping function called from invalid context at kernel/mutex.c:413
 in_atomic(): 1, irqs_disabled(): 1, pid: 5502, name: Xorg
 INFO: lockdep is turned off.
 irq event stamp: 1098574
 hardirqs last  enabled at (1098573): [<ffffffff816fb53f>] _raw_spin_unlock_irqrestore+0x3f/0x70
 hardirqs last disabled at (1098574): [<ffffffff816faaf5>] _raw_spin_lock_irqsave+0x25/0xa0
 softirqs last  enabled at (1098306): [<ffffffff8104971f>] __do_softirq+0x18f/0x3c0
 softirqs last disabled at (1097867): [<ffffffff81049ad5>] irq_exit+0xa5/0xb0
 CPU: 0 PID: 5502 Comm: Xorg Not tainted 3.9.0+ #94
 Hardware name: Dell Inc. OptiPlex 390/0M5DCD, BIOS A09 07/24/2012
  ffffffff81a03ac7 ffff8800689c7c68 ffffffff816f249f ffff8800689c7c90
  ffffffff8107ce60 0000000000000000 ffff8800689c7fd8 ffff88006a62c800
  ffff8800689c7d10 ffffffff816f7770 ffff8800689c7d00 ffffffff81312ac4
 Call Trace:
  [<ffffffff816f249f>] dump_stack+0x19/0x1b
  [<ffffffff8107ce60>] __might_sleep+0x180/0x230
  [<ffffffff816f7770>] mutex_lock_nested+0x40/0x3a0
  [<ffffffff81312ac4>] ? vsnprintf+0x354/0x640
  [<ffffffff81553cc4>] hid_debug_event+0x34/0x100
  [<ffffffff81554197>] hid_dump_input+0x67/0xa0
  [<ffffffff81556430>] hid_set_field+0x50/0x120
  [<ffffffff8156529a>] usb_hidinput_input_event+0x9a/0x120
  [<ffffffff8150d89e>] input_handle_event+0x8e/0x530
  [<ffffffff8150df10>] input_inject_event+0x1d0/0x230
  [<ffffffff8150dd82>] ? input_inject_event+0x42/0x230
  [<ffffffff81512cae>] evdev_write+0xde/0x160
  [<ffffffff81185038>] vfs_write+0xc8/0x1f0
  [<ffffffff81185535>] SyS_write+0x55/0xa0
  [<ffffffff81704482>] system_call_fastpath+0x16/0x1b

Reported-by: majianpeng <majianpeng@gmail.com>
Reported-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-05-06 13:07:33 +02:00
Jiri Kosina
72c16d9a5c Merge branch 'for-3.10/mt-hybrid-finger-pen' into for-linus
Conflicts:
	drivers/hid/hid-multitouch.c
2013-04-30 10:17:48 +02:00
Jiri Kosina
4f5a810429 Merge branches 'for-3.10/appleir', 'for-3.10/hid-debug', 'for-3.10/hid-driver-transport-cleanups', 'for-3.10/i2c-hid' and 'for-3.10/logitech' into for-linus 2013-04-30 10:12:44 +02:00
Jiri Kosina
2353f2bea3 HID: protect hid_debug_list
Accesses to hid_device->hid_debug_list are not serialized properly, which
could result in SMP concurrency issues when HID debugfs events are accessesed
by multiple userspace processess.

Serialize all the list operations by a mutex.

Spotted by Al Viro.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-04-30 10:09:31 +02:00
Benjamin Tissoires
4f22decf9b HID: input: don't register unmapped input devices
There is no need to register an input device containing no events.
This allows drivers using the quirk MULTI_INPUT to register one input
per report effectively used.

For backward compatibility, we need to add a quirk to request
this behavior.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-03-27 14:02:45 +01:00
Benjamin Tissoires
9684819b5a HID: ll_driver: Extend the interface with idle requests
Some drivers send the idle command directly to underlying device,
creating an unwanted dependency on the underlying transport layer.
This patch adds hid_hw_idle() to the interface, thereby removing
usbhid from the lion share of the drivers.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-03-07 15:58:17 +01:00
Andrew de los Reyes
c849a6143b HID: Separate struct hid_device's driver_lock into two locks.
This patch separates struct hid_device's driver_lock into two. The
goal is to allow hid device drivers to receive input during their
probe() or remove() function calls. This is necessary because some
drivers need to communicate with the device to determine parameters
needed during probe (e.g., size of a multi-touch surface), and if
possible, may perfer to communicate with a device on host-initiated
disconnect (e.g., to put it into a low-power state).

Historically, three functions used driver_lock:

- hid_device_probe: blocks to acquire lock
- hid_device_remove: blocks to acquire lock
- hid_input_report: if locked returns -EBUSY, else acquires lock

This patch adds another lock (driver_input_lock) which is used to
block input from occurring. The lock behavior is now:

- hid_device_probe: blocks to acq. driver_lock, then driver_input_lock
- hid_device_remove: blocks to acq. driver_lock, then driver_input_lock
- hid_input_report: if driver_input_lock locked returns -EBUSY, else
  acquires driver_input_lock

This patch also adds two helper functions to be called during probe()
or remove(): hid_device_io_start() and hid_device_io_stop(). These
functions lock and unlock, respectively, driver_input_lock; they also
make a note of whether they did so that hid-core knows if a driver has
changed the lock state.

This patch results in no behavior change for existing devices and
drivers. However, during a probe() or remove() function call in a
driver, that driver may now selectively call hid_device_io_start() to
let input events come through, then optionally call
hid_device_io_stop() to stop them.

Signed-off-by: Andrew de los Reyes <adlr@chromium.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-03-01 14:13:07 +01:00
Henrik Rydberg
3373443bef HID: Extend the interface with wait io request
Some drivers need to wait for an io from the underlying device, creating
an unwanted dependency on the underlying transport layer. This patch adds
wait() to the interface, thereby removing usbhid from the lion share of
the drivers.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-02-25 13:26:39 +01:00
Henrik Rydberg
e90a6df80d HID: Extend the interface with report requests
Some drivers send reports directly to underlying device, creating an
unwanted dependency on the underlying transport layer. This patch adds
hid_hw_request() to the interface, thereby removing usbhid from the
lion share of the drivers.

Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-02-25 13:26:39 +01:00
Jiri Kosina
73759518d6 Merge branches 'for-3.9/logitech', 'for-3.9/multitouch', 'for-3.9/ntrig', 'for-3.9/thingm' and 'for-3.9/upstream' into for-linus 2013-02-21 10:45:01 +01:00
Benjamin Tissoires
6d85d037d6 HID: core: add "report" hook, called once the report has been parsed
This callback is called when the parsing of the report has been done
by hid-core (so after the calls to .event). The hid drivers can now
have access to the whole report by relying on the values stored in
the different fields.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-02-05 12:07:39 +01:00
H Hartley Sweeten
d463f4719a HID: hid.h: remove unused hid_generic_{init,exit} prototypes
These functions are not defined. Remove the extern declarations.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-01-03 10:27:31 +01:00
H Hartley Sweeten
4d02c58eb1 HID: introduce helper for hid_driver boilerplate
Introduce the module_hid_driver macro which is a convenience macro
for HID driver modules similar to module_usb_driver. It is intended
to be used by drivers with init/exit sections that do nothing but
register/unregister the HID driver.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2013-01-03 10:27:30 +01:00
Jiri Kosina
818b930bc1 Merge branches 'for-3.7/upstream-fixes', 'for-3.8/hidraw', 'for-3.8/i2c-hid', 'for-3.8/multitouch', 'for-3.8/roccat', 'for-3.8/sensors' and 'for-3.8/upstream' into for-linus
Conflicts:
	drivers/hid/hid-core.c
2012-12-12 21:41:55 +01:00
Alexander Holler
83499b52c6 HID: sensors: autodetect USB HID sensor hubs
It should not be necessary to add IDs for HID sensor hubs to lists in
hid-core.c and hid-sensor-hub.c. So instead of a whitelist, autodetect such USB
HID sensor hubs, based on a collection of type physical inside a useage page of
type sensor. If some sensor hubs stil must be usable as raw devices, a
blacklist might be created.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
Acked-by: "Pandruvada, Srinivas" <srinivas.pandruvada@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2012-12-12 16:49:10 +01:00