From patchwork Tue Dec 6 20:48:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jo=C3=A3o_Paulo_Rechi_Vita?= X-Patchwork-Id: 9463263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5E29E60231 for ; Tue, 6 Dec 2016 20:49:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50085284DA for ; Tue, 6 Dec 2016 20:49:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 438D9284DD; Tue, 6 Dec 2016 20:49:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2FCB7284DA for ; Tue, 6 Dec 2016 20:49:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751266AbcLFUtW (ORCPT ); Tue, 6 Dec 2016 15:49:22 -0500 Received: from mail-qk0-f193.google.com ([209.85.220.193]:33331 "EHLO mail-qk0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750813AbcLFUtU (ORCPT ); Tue, 6 Dec 2016 15:49:20 -0500 Received: by mail-qk0-f193.google.com with SMTP id x190so45501910qkb.0; Tue, 06 Dec 2016 12:49:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=GAntP7YbskOFVgMnjRS0pzoGyc47Wbz1J6EKoJJG3P4=; b=v9a+68y2X5dUHhApfzLS7X45PfY46zqpGOqOPn0uTM4OXEMzOpLCDvl8kdD6RWvDds bt1wdKDmVZKLzt/Bu/oLqMopSgkrvmNIbaDUSPqDLPsawh89Re7DWKtDgIP1G94hM7S/ TpdNyxIfuPc7GT2I93FVwL2XpPbkcetLH5H7BGjpZpF1nPhvWAFDrSEyFDk9FZSpxkJ1 25pxtRw04Kn6v05XnAZOx6cWdvHcphcnOfg7XEHfEFUhw8R0g906x1E/fQBU2oKBZxAR rRdi7RaUwyp9BuUEc63nPlZ63JOq2zAXs6juMKdGGfGUQ/SERwFmapqe7ZAUst5Qp4hc E3Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=GAntP7YbskOFVgMnjRS0pzoGyc47Wbz1J6EKoJJG3P4=; b=a1HLDtMMsWznuKE6Os3lbj1traOkWPcOxGNKbPpSmKNIe/IxOix2j05ezyJW660rPg TYeOOoJFuK5//FmfjcOCVfVpEgM+P7+hunErrqVYEA+mNsEmcqT//OCruQqNrbvJdawS gqz1/ByTYKgtW/hoLT4gsG/McNkBYOLlAQ8zNMQLNz94sPbyQWWpTCOg2JR83tXS8vJw zl8zAsu9jPYzXR8HHnnrLlARvW8aw0hnuXsRwGi9u4XZaISaHWcrsPgmMC0GCpSkw/ay 6OL8Ay9ZUeO3WKRo65JrORUjyaKdEhId8lFNQ1YkgTPo8DabumQ4OBBmmUUlcyEN7ElM jgKQ== X-Gm-Message-State: AKaTC02lsxa+Zdhbr7f2Cxlf6vjwI/bgM/3Nx9QPfowbbdlihKe8S5nH+xMafAX3v8h+CQ== X-Received: by 10.55.5.149 with SMTP id 143mr54230952qkf.236.1481057359398; Tue, 06 Dec 2016 12:49:19 -0800 (PST) Received: from kiddo.hsd1.wv.comcast.net ([2601:545:c001:9c20:a181:e8a2:9de3:630e]) by smtp.gmail.com with ESMTPSA id 21sm12996324qkh.4.2016.12.06.12.49.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 06 Dec 2016 12:49:18 -0800 (PST) From: "=?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?=" X-Google-Original-From: =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= To: Jiri Kosina , Benjamin Tissoires Cc: linux@endlessm.com, =?UTF-8?q?Jo=C3=A3o=20Paulo=20Rechi=20Vita?= , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] i2c-hid: Disable IRQ before freeing buffers Date: Tue, 6 Dec 2016 15:48:35 -0500 Message-Id: <20161206204835.7665-1-jprvita@endlessm.com> X-Mailer: git-send-email 2.10.2 MIME-Version: 1.0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The HID report buffers that are initially allocated on i2c_hid_probe() might not be big enough to hold the HID reports from a specific device, in which case they will be freed and new ones will be allocated in i2c_hid_start(), at point which the device's report size is known. But at this point ihid->irq is already running, and may call i2c_hid_get_input() which passes ihid->inbuf to i2c_master_recv(). Since this handler runs in a separate thread, ihid->inbuf may be freed at this very moment, and i2c_master_recv() will write on memory which may be already owned by a different part of the kernel, corrupting its data. This problem has been observed on an Asus UX360UA laptop which has an I2C touchpad, and results in a complete system freeze or an unusable slowness with a lof of "BUG: unable to handle kernel paging request at
" warnings. Enabling SLUB debugging shows a use-after-free warning on memory allocated in i2c_hid_alloc_buffers() and freed in i2c_hid_free_buffers(): Reviewed-by: Benjamin Tissoires ============================================================================= BUG kmalloc-64 (Not tainted): Poison overwritten ----------------------------------------------------------------------------- Disabling lock debugging due to kernel taint INFO: 0xffff880264083273-0xffff88026408329e. first byte 0x0 instead of 0x6b INFO: Allocated in i2c_hid_alloc_buffers+0x25/0xa0 [i2c_hid] age=35793 cpu=2 pid=430 ___slab_alloc+0x41e/0x460 __slab_alloc+0x20/0x40 __kmalloc+0x210/0x280 i2c_hid_alloc_buffers+0x25/0xa0 [i2c_hid] i2c_hid_probe+0x12f/0x5e0 [i2c_hid] i2c_device_probe+0x10a/0x1b0 driver_probe_device+0x220/0x4a0 __device_attach_driver+0x71/0xa0 bus_for_each_drv+0x67/0xb0 __device_attach+0xdc/0x170 device_initial_probe+0x13/0x20 bus_probe_device+0x92/0xa0 device_add+0x4aa/0x670 device_register+0x1a/0x20 i2c_new_device+0x18e/0x230 acpi_i2c_add_device+0x1a0/0x210 INFO: Freed in i2c_hid_free_buffers+0x16/0x60 [i2c_hid] age=7552 cpu=1 pid=1473 __slab_free+0x221/0x330 kfree+0x139/0x160 i2c_hid_free_buffers+0x16/0x60 [i2c_hid] i2c_hid_start+0x2a9/0x2df [i2c_hid] mt_probe+0x160/0x22e [hid_multitouch] hid_device_probe+0xd7/0x150 [hid] driver_probe_device+0x220/0x4a0 __driver_attach+0x84/0x90 bus_for_each_dev+0x6c/0xc0 driver_attach+0x1e/0x20 bus_add_driver+0x1c3/0x280 driver_register+0x60/0xe0 __hid_register_driver+0x53/0x90 [hid] 0xffffffffc004f01e do_one_initcall+0xb3/0x1f0 do_init_module+0x5f/0x1d0 INFO: Slab 0xffffea0009902080 objects=20 used=20 fp=0x (null) flags=0x17fff8000004080 INFO: Object 0xffff880264083260 @offset=4704 fp=0x (null) Bytes b4 ffff880264083250: 8d e6 fe ff 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ Object ffff880264083260: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b kkkkkkkkkkkkkkkk Object ffff880264083270: 6b 6b 6b 00 00 00 00 00 00 00 00 00 00 00 00 00 kkk............. Object ffff880264083280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Object ffff880264083290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Redzone ffff8802640832a0: bb bb bb bb bb bb bb bb ........ Padding ffff8802640833e0: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ CPU: 1 PID: 1503 Comm: python3 Tainted: G B 4.4.21+ #10 Hardware name: ASUSTeK COMPUTER INC. UX360UA/UX360UA, BIOS UX360UA.200 05/05/2016 0000000000000086 00000000622d48a2 ffff88026061ba38 ffffffff813f6044 ffff880264082010 ffff880264083260 ffff88026061ba78 ffffffff811e8eab 0000000000000008 ffff880200000001 ffff88026408329f ffff88026a007700 Call Trace: [] dump_stack+0x63/0x8f [] print_trailer+0x14b/0x1f0 [] check_bytes_and_report+0xc1/0x100 [] check_object+0x1c4/0x240 [] ? ext4_htree_store_dirent+0x3e/0x120 [] alloc_debug_processing+0x104/0x180 [] ___slab_alloc+0x41e/0x460 [] ? ext4_htree_store_dirent+0x3e/0x120 [] ? __getblk_gfp+0x2b/0x60 [] ? ext4_getblk+0xa9/0x190 [] __slab_alloc+0x20/0x40 [] __kmalloc+0x210/0x280 [] ? ext4_htree_store_dirent+0x3e/0x120 [] ? ext4fs_dirhash+0xc2/0x2a0 [] ext4_htree_store_dirent+0x3e/0x120 [] htree_dirblock_to_tree+0x187/0x1b0 [] ext4_htree_fill_tree+0xb2/0x2e0 [] ? kmem_cache_alloc_trace+0x1fa/0x220 [] ? ext4_readdir+0x775/0x8b0 [] ext4_readdir+0x5e1/0x8b0 [] iterate_dir+0x92/0x120 [] SyS_getdents+0x98/0x110 [] ? iterate_dir+0x120/0x120 [] entry_SYSCALL_64_fastpath+0x16/0x71 FIX kmalloc-64: Restoring 0xffff880264083273-0xffff88026408329e=0x6b FIX kmalloc-64: Marking all objects used Signed-off-by: João Paulo Rechi Vita --- drivers/hid/i2c-hid/i2c-hid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index b3ec4f2..d4c2f2d 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -716,9 +716,11 @@ static int i2c_hid_start(struct hid_device *hid) i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); if (bufsize > ihid->bufsize) { + disable_irq(ihid->irq); i2c_hid_free_buffers(ihid); ret = i2c_hid_alloc_buffers(ihid, bufsize); + enable_irq(ihid->irq); if (ret) return ret;