1. 11 10月, 2017 1 次提交
    • J
      HID: usbhid: fix out-of-bounds bug · f043bfc9
      Jaejoong Kim 提交于
      The hid descriptor identifies the length and type of subordinate
      descriptors for a device. If the received hid descriptor is smaller than
      the size of the struct hid_descriptor, it is possible to cause
      out-of-bounds.
      
      In addition, if bNumDescriptors of the hid descriptor have an incorrect
      value, this can also cause out-of-bounds while approaching hdesc->desc[n].
      
      So check the size of hid descriptor and bNumDescriptors.
      
      	BUG: KASAN: slab-out-of-bounds in usbhid_parse+0x9b1/0xa20
      	Read of size 1 at addr ffff88006c5f8edf by task kworker/1:2/1261
      
      	CPU: 1 PID: 1261 Comm: kworker/1:2 Not tainted
      	4.14.0-rc1-42251-gebb2c243 #169
      	Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
      	Workqueue: usb_hub_wq hub_event
      	Call Trace:
      	__dump_stack lib/dump_stack.c:16
      	dump_stack+0x292/0x395 lib/dump_stack.c:52
      	print_address_description+0x78/0x280 mm/kasan/report.c:252
      	kasan_report_error mm/kasan/report.c:351
      	kasan_report+0x22f/0x340 mm/kasan/report.c:409
      	__asan_report_load1_noabort+0x19/0x20 mm/kasan/report.c:427
      	usbhid_parse+0x9b1/0xa20 drivers/hid/usbhid/hid-core.c:1004
      	hid_add_device+0x16b/0xb30 drivers/hid/hid-core.c:2944
      	usbhid_probe+0xc28/0x1100 drivers/hid/usbhid/hid-core.c:1369
      	usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
      	really_probe drivers/base/dd.c:413
      	driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
      	__device_attach_driver+0x230/0x290 drivers/base/dd.c:653
      	bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
      	__device_attach+0x26e/0x3d0 drivers/base/dd.c:710
      	device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
      	bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
      	device_add+0xd0b/0x1660 drivers/base/core.c:1835
      	usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
      	generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
      	usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
      	really_probe drivers/base/dd.c:413
      	driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
      	__device_attach_driver+0x230/0x290 drivers/base/dd.c:653
      	bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
      	__device_attach+0x26e/0x3d0 drivers/base/dd.c:710
      	device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
      	bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
      	device_add+0xd0b/0x1660 drivers/base/core.c:1835
      	usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
      	hub_port_connect drivers/usb/core/hub.c:4903
      	hub_port_connect_change drivers/usb/core/hub.c:5009
      	port_event drivers/usb/core/hub.c:5115
      	hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
      	process_one_work+0xc7f/0x1db0 kernel/workqueue.c:2119
      	worker_thread+0x221/0x1850 kernel/workqueue.c:2253
      	kthread+0x3a1/0x470 kernel/kthread.c:231
      	ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
      
      Cc: stable@vger.kernel.org
      Reported-by: NAndrey Konovalov <andreyknvl@google.com>
      Signed-off-by: NJaejoong Kim <climbbb.kim@gmail.com>
      Tested-by: NAndrey Konovalov <andreyknvl@google.com>
      Acked-by: NAlan Stern <stern@rowland.harvard.edu>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      f043bfc9
  2. 27 7月, 2017 1 次提交
    • J
      HID: introduce hid_is_using_ll_driver · fc2237a7
      Jason Gerecke 提交于
      Although HID itself is transport-agnostic, occasionally a driver may
      want to interact with the low-level transport that a device is connected
      through. To do this, we need to know what kind of bus is in use. The
      first guess may be to look at the 'bus' field of the 'struct hid_device',
      but this field may be emulated in some cases (e.g. uhid).
      
      More ideally, we can check which ll_driver a device is using. This
      function introduces a 'hid_is_using_ll_driver' function and makes the
      'struct hid_ll_driver' of the four most common transports accessible
      through hid.h.
      Signed-off-by: NJason Gerecke <jason.gerecke@wacom.com>
      Acked-By: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      fc2237a7
  3. 22 7月, 2017 1 次提交
  4. 08 6月, 2017 4 次提交
  5. 21 3月, 2017 1 次提交
    • B
      HID: remove initial reading of reports at connect · 9143059f
      Benjamin Tissoires 提交于
      It looks like a bunch of devices do not like to be polled
      for their reports at init time. When you look into the details,
      it seems that for those that are requiring the quirk
      HID_QUIRK_NO_INIT_REPORTS, the driver fails to retrieve part
      of the features/inputs while others (more generic) work.
      
      IMO, it should be acceptable to remove the need for the quirk
      in the general case. On the small amount of cases where
      we actually need to read the current values, the driver
      in charge (hid-mt or wacom) already retrieves the features
      manually.
      
      There are 2 cases where we might need to retrieve the reports at
      init:
      1. hiddev devices with specific use-space tool
      2. a device that would require the driver to fetch a specific
         feature/input at plug
      
      For case 2, I have seen this a few time on hid-multitouch. It
      is solved in hid-multitouch directly by fetching the feature.
      I hope it won't be too common and this can be solved on a per-case
      basis (crossing fingers).
      
      For case 1, we moved the implementation of HID_QUIRK_NO_INIT_REPORTS
      in hiddev. When somebody starts calling ioctls that needs an initial
      update, the hiddev device will fetch the initial state of the reports
      to mimic the current behavior. This adds a small amount of time during
      the first HIDIOCGUSAGE(S), but it should be acceptable in
      most cases. To keep the currently known broken devices, we have to
      keep around HID_QUIRK_NO_INIT_REPORTS, but the scope will only be
      for hiddev.
      
      Note that I don't think hidraw would be affected and I checked that
      the FF drivers that need to interact with the report fields are all
      using output reports, which are not initialized by
      usbhid_init_reports().
      
      NO_INIT_INPUT_REPORTS is then replaced by HID_QUIRK_NO_INIT_REPORTS:
      there is no point keeping it for just one device.
      Signed-off-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      9143059f
  6. 06 3月, 2017 2 次提交
  7. 06 1月, 2017 1 次提交
  8. 09 12月, 2016 1 次提交
  9. 24 3月, 2016 1 次提交
    • A
      HID: usbhid: fix inconsistent reset/resume/reset-resume behavior · 972e6a99
      Alan Stern 提交于
      The usbhid driver has inconsistently duplicated code in its post-reset,
      resume, and reset-resume pathways.
      
      	reset-resume doesn't check HID_STARTED before trying to
      	restart the I/O queues.
      
      	resume fails to clear the HID_SUSPENDED flag if HID_STARTED
      	isn't set.
      
      	resume calls usbhid_restart_queues() with usbhid->lock held
      	and the others call it without holding the lock.
      
      The first item in particular causes a problem following a reset-resume
      if the driver hasn't started up its I/O.  URB submission fails because
      usbhid->urbin is NULL, and this triggers an unending reset-retry loop.
      
      This patch fixes the problem by creating a new subroutine,
      hid_restart_io(), to carry out all the common activities.  It also
      adds some checks that were missing in the original code:
      
      	After a reset, there's no need to clear any halted endpoints.
      
      	After a resume, if a reset is pending there's no need to
      	restart any I/O until the reset is finished.
      
      	After a resume, if the interrupt-IN endpoint is halted there's
      	no need to submit the input URB until the halt has been
      	cleared.
      Signed-off-by: NAlan Stern <stern@rowland.harvard.edu>
      Reported-by: NDaniel Fraga <fragabr@gmail.com>
      Tested-by: NDaniel Fraga <fragabr@gmail.com>
      CC: <stable@vger.kernel.org>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      972e6a99
  10. 02 12月, 2015 1 次提交
    • I
      HID: usbhid: fix recursive deadlock · e470127e
      Ioan-Adrian Ratiu 提交于
      The critical section protected by usbhid->lock in hid_ctrl() is too
      big and because of this it causes a recursive deadlock. "Too big" means
      the case statement and the call to hid_input_report() do not need to be
      protected by the spinlock (no URB operations are done inside them).
      
      The deadlock happens because in certain rare cases drivers try to grab
      the lock while handling the ctrl irq which grabs the lock before them
      as described above. For example newer wacom tablets like 056a:033c try
      to reschedule proximity reads from wacom_intuos_schedule_prox_event()
      calling hid_hw_request() -> usbhid_request() -> usbhid_submit_report()
      which tries to grab the usbhid lock already held by hid_ctrl().
      
      There are two ways to get out of this deadlock:
          1. Make the drivers work "around" the ctrl critical region, in the
          wacom case for ex. by delaying the scheduling of the proximity read
          request itself to a workqueue.
          2. Shrink the critical region so the usbhid lock protects only the
          instructions which modify usbhid state, calling hid_input_report()
          with the spinlock unlocked, allowing the device driver to grab the
          lock first, finish and then grab the lock afterwards in hid_ctrl().
      
      This patch implements the 2nd solution.
      Signed-off-by: NIoan-Adrian Ratiu <adi@adirat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      e470127e
  11. 23 11月, 2015 1 次提交
  12. 19 8月, 2015 1 次提交
    • D
      HID: usbhid: Fix the check for HID_RESET_PENDING in hid_io_error · 3af4e5a9
      Don Zickus 提交于
      It was reported that after 10-20 reboots, a usb keyboard plugged
      into a docking station would not work unless it was replugged in.
      
      Using usbmon, it turns out the interrupt URBs were streaming with
      callback errors of -71 for some reason.  The hid-core.c::hid_io_error was
      supposed to retry and then reset, but the reset wasn't really happening.
      
      The check for HID_NO_BANDWIDTH was inverted.  Fix was simple.
      
      Tested by reporter and locally by me by unplugging a keyboard halfway until I
      could recreate a stream of errors but no disconnect.
      Signed-off-by: NDon Zickus <dzickus@redhat.com>
      Cc: stable@vger.kernel.org
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      3af4e5a9
  13. 08 7月, 2015 1 次提交
  14. 02 12月, 2014 1 次提交
  15. 29 10月, 2014 1 次提交
    • B
      HID: usbhid: prevent unwanted events to be sent when re-opening the device · b905811a
      Benjamin Tissoires 提交于
      When events occurs while no one is listening to the node (hid->open == 0
      and usb_kill_urb() called) some events are still stacked somewhere in
      the USB (kernel or device?) stack. When the node gets reopened, these
      events are drained, and this results in spurious touch down/up, or mouse
      button clicks.
      
      The problem was spotted with touchscreens in fdo bug #81781 [1], but it
      actually occurs with any mouse using hid-generic or touchscreen.
      
      A way to reproduce it is to call:
      
      $ xinput disable 9 ; sleep 5 ; xinput enable 9
      
      With 9 being the device ID for the touchscreen/mouse. During the "sleep",
      produce some touch events or click events. When "xinput enable" is called,
      at least one click is generated.
      
      This patch tries to fix this by draining the queue for 50 msec and
      during this time frame, not forwarding these old events to the hid layer.
      
      Hans completed the explanation:
      """
      Devices like mice (basically any hid device) will have a fifo
      on the device side, when we stop submitting urbs to get hid reports from
      it, that fifo will fill up, and when we resume we will get whatever
      is there in that fifo.
      """
      
      [1] https://bugs.freedesktop.org/show_bug.cgi?id=81781Signed-off-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      b905811a
  16. 08 9月, 2014 1 次提交
  17. 04 9月, 2014 1 次提交
    • A
      HID: usbhid: improve handling of Clear-Halt and reset · 8f507ef5
      Alan Stern 提交于
      This patch changes the way usbhid carries out Clear-Halt and reset.
      
      Currently, after a Clear-Halt on the interrupt-IN endpoint, the driver
      immediately restarts the interrupt URB, even if the Clear-Halt failed.
      This doesn't work out well when the reason for the failure was that
      the device was disconnected (when a low- or full-speed device is
      connected through a hub to an EHCI controller, transfer errors caused
      by disconnection are reported as stalls by the hub).  Instead now the
      driver will attempt a reset after a failed Clear-Halt.
      
      The way resets are carried out is also changed.  Now the driver will
      call usb_queue_reset_device() instead of calling usb_reset_device()
      directly.  This avoids a deadlock that would arise when a device is
      unplugged: The hid_reset() routine runs as a workqueue item, a reset
      attempt after the device has been unplugged will fail, failure will
      cause usbhid to be unbound, and the disconnect routine will try to do
      cancel_work_sync().  The usb_queue_reset_device() implementation is
      carefully written to handle scenarios like this one properly.
      Signed-off-by: NAlan Stern <stern@rowland.harvard.edu>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      8f507ef5
  18. 29 7月, 2014 1 次提交
    • R
      HID: usbhid: Use flag HID_DISCONNECTED when a usb device is removed · 46df9ded
      Reyad Attiyat 提交于
      Set disconnected flag in struct usbhid when a usb device is removed. Check for
      disconnected flag before sending urb requests. This prevents a kernel panic
      when a hid driver calls hid_hw_request() after removing a usb device.
      
       BUG: unable to handle kernel NULL pointer dereference at 0000000000000058
       IP: [<ffffffff8161746f>] hid_submit_ctrl+0x7f/0x290
       PGD 0
       Oops: 0002 [#1] PREEMPT SMP
       CPU: 2 PID: 39 Comm: khubd Tainted: G          IO  3.16.0-rc5+ #112
       Hardware name: Microsoft Corporation Surface Pro 2/Surface Pro 2, BIOS 2.03.0250 09/06/2013
       task: ffff880118aba6e0 ti: ffff8800daf80000 task.ti: ffff8800daf80000
       RIP: 0010:[<ffffffff8161746f>]  [<ffffffff8161746f>] hid_submit_ctrl+0x7f/0x290
       RSP: 0018:ffff8800daf83750  EFLAGS: 00010086
       RAX: 0000000080000300 RBX: ffff88003f60c000 RCX: 0000000000000000
       RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff880117f78000
       RBP: ffff8800daf83788 R08: 0000000000000001 R09: 0000000000000001
       R10: 0000000000000001 R11: 0000000000000000 R12: ffff880117f78000
       R13: ffff88003f11a290 R14: 000000000000000c R15: ffff880091cb3ab8
       FS:  0000000000000000(0000) GS:ffff88011b000000(0000) knlGS:0000000000000000
       CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
       CR2: 0000000000000058 CR3: 0000000001c11000 CR4: 00000000001407e0
       Stack:
        ffff880117f3dcd0 ffff880117f78000 ffff88003f60c000 ffff880117f78000
        ffff880117f78000 ffff88003f11a290 0000000000000000 ffff8800daf837b0
        ffffffff81617707 ffff880117f78000 ffff88003f60c000 0000000000000013
       Call Trace:
        [<ffffffff81617707>] usbhid_restart_ctrl_queue+0x87/0x140
        [<ffffffff81617a88>] usbhid_submit_report+0x2c8/0x370
        [<ffffffff81617b4a>] usbhid_request+0x1a/0x30
        [<ffffffffa020edfb>] sensor_hub_set_feature+0x8b/0xd0 [hid_sensor_hub]
        [<ffffffffa02d9084>] hid_sensor_power_state+0x84/0x110 [hid_sensor_trigger]
        [<ffffffffa02d9129>] hid_sensor_data_rdy_trigger_set_state+0x19/0x20 [hid_sensor_trigger]
        [<ffffffffa034d5b7>] iio_triggered_buffer_predisable+0xa7/0xb0 [industrialio]
        [<ffffffffa034cc4a>] iio_disable_all_buffers+0x3a/0xc0 [industrialio]
        [<ffffffffa03487d3>] iio_device_unregister+0x53/0x80 [industrialio]
        [<ffffffffa026c06a>] hid_accel_3d_remove+0x2a/0x50 [hid_sensor_accel_3d]
        [<ffffffff814f433d>] platform_drv_remove+0x1d/0x40
        [<ffffffff814f18bf>] __device_release_driver+0x7f/0xf0
        [<ffffffff814f1955>] device_release_driver+0x25/0x40
        [<ffffffff814f121c>] bus_remove_device+0x11c/0x1a0
        [<ffffffff814ed7d6>] device_del+0x136/0x1e0
        [<ffffffff81512190>] ? mfd_cell_disable+0x80/0x80
        [<ffffffff814f41d1>] platform_device_del+0x21/0xc0
        [<ffffffff814f4282>] platform_device_unregister+0x12/0x30
        [<ffffffff815121d3>] mfd_remove_devices_fn+0x43/0x50
        [<ffffffff814ed3e3>] device_for_each_child+0x43/0x70
        [<ffffffff81512105>] mfd_remove_devices+0x25/0x30
        [<ffffffffa020ebd7>] sensor_hub_remove+0x87/0x140 [hid_sensor_hub]
        [<ffffffff81607c5b>] hid_device_remove+0x6b/0xd0
        [<ffffffff814f18bf>] __device_release_driver+0x7f/0xf0
        [<ffffffff814f1955>] device_release_driver+0x25/0x40
        [<ffffffff814f121c>] bus_remove_device+0x11c/0x1a0
        [<ffffffff814ed7d6>] device_del+0x136/0x1e0
        [<ffffffff81607d47>] hid_destroy_device+0x27/0x60
        [<ffffffff81616972>] usbhid_disconnect+0x22/0x50
        [<ffffffff81568597>] usb_unbind_interface+0x77/0x2b0
        [<ffffffff814f18bf>] __device_release_driver+0x7f/0xf0
        [<ffffffff814f1955>] device_release_driver+0x25/0x40
        [<ffffffff814f121c>] bus_remove_device+0x11c/0x1a0
        [<ffffffff814ed7d6>] device_del+0x136/0x1e0
        [<ffffffff81565cd1>] usb_disable_device+0x91/0x2a0
        [<ffffffff8155b046>] usb_disconnect+0x96/0x2e0
        [<ffffffff8155d74a>] hub_thread+0xb5a/0x1840
      Signed-off-by: NReyad Attiyat <reyad.attiyat@gmail.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      46df9ded
  19. 10 6月, 2014 1 次提交
  20. 14 3月, 2014 2 次提交
  21. 17 2月, 2014 3 次提交
  22. 29 1月, 2014 1 次提交
  23. 27 8月, 2013 1 次提交
  24. 31 7月, 2013 3 次提交
    • D
      HID: usbhid: use generic hidinput_input_event() · bfde79cb
      David Herrmann 提交于
      HID core provides the same functionality as we do, so drop the custom
      hidinput_input_event() handler.
      Signed-off-by: NDavid Herrmann <dh.herrmann@gmail.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      bfde79cb
    • D
      HID: usbhid: update LED fields unlocked · 60682284
      David Herrmann 提交于
      Report fields can be updated from HID drivers unlocked via
      hid_set_field(). It is protected by input_lock in HID core so only a
      single input event is handled at a time. USBHID can thus update the field
      unlocked and doesn't conflict with any HID vendor/device drivers. Note,
      many HID drivers make heavy use of hid_set_field() in that way.
      
      But usbhid also schedules a work to gather multiple LED changes in a
      single report. Hence, we used to lock the LED field update so the work can
      read a consistent state. However, hid_set_field() only writes a single
      integer field, which is guaranteed to be allocated all the time. So the
      worst possible race-condition is a garbage read on the LED field.
      
      Therefore, there is no need to protect the update. In fact, the only thing
      that is prevented by locking hid_set_field(), is an LED update while the
      scheduled work currently writes an older LED update out. However, this
      means, a new work is scheduled directly when the old one is done writing
      the new state to the device. So we actually _win_ by not protecting the
      write and allowing the write to be combined with the current write. A new
      worker is still scheduled, but will not write any new state. So the LED
      will not blink unnecessarily on the device.
      
      Assume we have the LED set to 0. Two request come in which enable the LED
      and immediately disable it. The current situation with two CPUs would be:
      
        usb_hidinput_input_event()       |      hid_led()
        ---------------------------------+----------------------------------
          spin_lock(&usbhid->lock);
          hid_set_field(1);
          spin_unlock(&usbhid->lock);
          schedule_work(...);
                                            spin_lock(&usbhid->lock);
                                            __usbhid_submit_report(..1..);
                                            spin_unlock(&usbhid->lock);
          spin_lock(&usbhid->lock);
          hid_set_field(0);
          spin_unlock(&usbhid->lock);
          schedule_work(...);
                                            spin_lock(&usbhid->lock);
                                            __usbhid_submit_report(..0..);
                                            spin_unlock(&usbhid->lock);
      
      With the locking removed, we _might_ end up with (look at the changed
      __usbhid_submit_report() parameters in the first try!):
      
        usb_hidinput_input_event()       |      hid_led()
        ---------------------------------+----------------------------------
          hid_set_field(1);
          schedule_work(...);
                                            spin_lock(&usbhid->lock);
          hid_set_field(0);
          schedule_work(...);
                                            __usbhid_submit_report(..0..);
                                            spin_unlock(&usbhid->lock);
      
                                            ... next work ...
      
                                            spin_lock(&usbhid->lock);
                                            __usbhid_submit_report(..0..);
                                            spin_unlock(&usbhid->lock);
      
      As one can see, we no longer send the "LED ON" signal as it is disabled
      immediately afterwards and the following "LED OFF" request overwrites the
      pending "LED ON".
      
      It is important to note that hid_set_field() is not atomic, so we might
      also end up with any other value. But that doesn't matter either as we
      _always_ schedule the next work with a correct value and schedule_work()
      acts as memory barrier, anyways. So in the worst case, we run
      __usbhid_submit_report(..<garbage>..) in the first case and the following
      __usbhid_submit_report() will write the correct value. But LED states are
      booleans so any garbage will be converted to either 0 or 1 and the remote
      device will never see invalid requests.
      
      Why all this? It avoids any custom locking around hid_set_field() in
      usbhid and finally allows us to provide a generic hidinput_input_event()
      handler for all HID transport drivers.
      Signed-off-by: NDavid Herrmann <dh.herrmann@gmail.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      60682284
    • D
      HID: usbhid: make usbhid_set_leds() static · ddf64a3c
      David Herrmann 提交于
      usbhid_set_leds() is only used inside of usbhid/hid-core.c so no need to
      export it.
      Signed-off-by: NDavid Herrmann <dh.herrmann@gmail.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      ddf64a3c
  25. 22 7月, 2013 1 次提交
    • J
      HID: fix data access in implement() · 27ce4050
      Jiri Kosina 提交于
      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: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Acked-by: NGustavo Padovan <gustavo.padovan@collabora.co.uk>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      27ce4050
  26. 26 3月, 2013 1 次提交
  27. 07 3月, 2013 1 次提交
  28. 25 2月, 2013 4 次提交