From patchwork Fri Jan 11 19:13:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Zabel X-Patchwork-Id: 10760559 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 686821390 for ; Fri, 11 Jan 2019 19:13:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56B8728488 for ; Fri, 11 Jan 2019 19:13:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 49226284E4; Fri, 11 Jan 2019 19:13:56 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 C545428488 for ; Fri, 11 Jan 2019 19:13:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390317AbfAKTNz (ORCPT ); Fri, 11 Jan 2019 14:13:55 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:38698 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729364AbfAKTNy (ORCPT ); Fri, 11 Jan 2019 14:13:54 -0500 Received: by mail-wr1-f66.google.com with SMTP id v13so16352078wrw.5 for ; Fri, 11 Jan 2019 11:13:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=t1RD7quhXev/7Nr9uClXNDLh5kIk5MxAeyGFxMW13i4=; b=kA4iEB1zvJFWPFd98n8Bdkclxt/d2UX6+CWFULxTMTwJtTft89xLF+8Vvp6dYJcxx9 J0JFcAGkpW72S/VP74EHT/ejthG+qjl/OLksPpu7JRyQPemReBT7KYWSIEfoe36F8KFU UBsPDg+ce1Q5sYLnePmqevEutTjgzMJIsP7Usz+UzxW1iRgUzZbqvWNrFSpTXEs76OpJ IaTMG1+93iEC0eeGY+f9uzagFEEm89tnwVaDljJVL1chkB145x+HPfTg32C+oOVsAs52 k6jmICDpz8fhTjwu7xbaevm4KwHxUe4qA+whI5qpzAMioJGQ+TTo9N3idMYREjJJqfUK 81KQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=t1RD7quhXev/7Nr9uClXNDLh5kIk5MxAeyGFxMW13i4=; b=ZuVZ2ei2wVSsjAHBI4kZ0+fNqSEdHU8p0OD0UN2S7d3ZoPMRfc6SHtH1su2bCyTnEp Fv2PznYiSvs9cNSM+qZQK8j5WNFXDm8e34IhFVJsa0LMyaT3p9/O55MFkJoWdC60KrZW RcZsYuqnUvXXRJNBmJ9Yt1BU9kofMKIDKZ8jGR6d+pgtQS6itCZ4X9WjSy6eDds7mAPW ISlBsNfoOGrtKB4vf2KOGWZVCk3sV9vgQeBJYLQIpzrHRnQ8fh1JJJKcMzMvCHv6FPF1 5bN8Q6itM63bNnnG/J4coAgXi/rYCEl9X0/Ffm+1PafnPO/q0OPKmosTYk2PhbFr6QOG r7yA== X-Gm-Message-State: AJcUukem9IJExGOTAiBglXus6bMKBCjy7adBDQ+oWkoBfibPLFHUIWZN cRWkTKmPWRzl5z+waItNbPQ= X-Google-Smtp-Source: ALg8bN4vR3m8rjlmkpLpxEKu4b52hAxf29+RAuD8C9G6kEG/z7sq553zl/eul9THUobGSMrdbnFvcg== X-Received: by 2002:adf:b608:: with SMTP id f8mr14228323wre.120.1547234032081; Fri, 11 Jan 2019 11:13:52 -0800 (PST) Received: from ped.lan (ip5f5abcd2.dynamic.kabel-deutschland.de. [95.90.188.210]) by smtp.googlemail.com with ESMTPSA id c8sm54743557wrx.42.2019.01.11.11.13.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 11 Jan 2019 11:13:51 -0800 (PST) From: Philipp Zabel To: Jiri Kosina , Benjamin Tissoires , Peter Hutterer Cc: linux-input@vger.kernel.org, Philipp Zabel Subject: [PATCH 1/2] HID: core: fix collection parent pointer handling Date: Fri, 11 Jan 2019 20:13:31 +0100 Message-Id: <20190111191332.13448-1-philipp.zabel@gmail.com> X-Mailer: git-send-email 2.20.1 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 Storing HID collection parents as direct pointers while parsing HID report descriptors only works as long as the collection array is not reallocated, which happens for descriptors with a large number of collections. Then all stored pointers are invalidated in the middle of parsing, which results in invalid memory accesses. Instead of storing pointers, just store array indices, which stay valid across array reallocation. Store UINT_MAX for "no parent". Fixes: c53431eb696f ("HID: core: store the collections as a basic tree") Fixes: 5a4abb36f312 ("HID: core: process the Resolution Multiplier") Signed-off-by: Philipp Zabel --- drivers/hid/hid-core.c | 24 ++++++++++++++++-------- include/linux/hid.h | 4 ++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f41d5fe51abe..5424f7f59680 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -168,12 +168,12 @@ static int open_collection(struct hid_parser *parser, unsigned type) parser->device->maxcollection; collection = parser->device->collection + - parser->device->maxcollection++; + parser->device->maxcollection; collection->type = type; collection->usage = usage; collection->level = parser->collection_stack_ptr - 1; collection->parent = parser->active_collection; - parser->active_collection = collection; + parser->active_collection = parser->device->maxcollection++; if (type == HID_COLLECTION_APPLICATION) parser->device->maxapplication++; @@ -192,8 +192,9 @@ static int close_collection(struct hid_parser *parser) return -EINVAL; } parser->collection_stack_ptr--; - if (parser->active_collection) - parser->active_collection = parser->active_collection->parent; + if (parser->active_collection != UINT_MAX) + parser->active_collection = + parser->device->collection[parser->active_collection].parent; return 0; } @@ -819,6 +820,7 @@ static int hid_scan_report(struct hid_device *hid) return -ENOMEM; parser->device = hid; + parser->active_collection = UINT_MAX; hid->group = HID_GROUP_GENERIC; /* @@ -1006,8 +1008,10 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid, usage = &field->usage[i]; collection = &hid->collection[usage->collection_index]; - while (collection && collection != multiplier_collection) - collection = collection->parent; + while (collection && collection != multiplier_collection) { + collection = (collection->parent == UINT_MAX) ? NULL : + &hid->collection[collection->parent]; + } if (collection || multiplier_collection == NULL) usage->resolution_multiplier = effective_multiplier; @@ -1045,8 +1049,11 @@ static void hid_apply_multiplier(struct hid_device *hid, */ multiplier_collection = &hid->collection[multiplier->usage->collection_index]; while (multiplier_collection && - multiplier_collection->type != HID_COLLECTION_LOGICAL) - multiplier_collection = multiplier_collection->parent; + multiplier_collection->type != HID_COLLECTION_LOGICAL) { + multiplier_collection = + (multiplier_collection->parent == UINT_MAX) ? NULL : + &hid->collection[multiplier_collection->parent]; + } effective_multiplier = hid_calculate_multiplier(hid, multiplier); @@ -1170,6 +1177,7 @@ int hid_open_report(struct hid_device *device) } parser->device = device; + parser->active_collection = UINT_MAX; end = start + size; diff --git a/include/linux/hid.h b/include/linux/hid.h index d99287327ef2..e7b1b388a990 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -430,7 +430,7 @@ struct hid_local { */ struct hid_collection { - struct hid_collection *parent; + unsigned int parent; unsigned type; unsigned usage; unsigned level; @@ -658,7 +658,7 @@ struct hid_parser { unsigned int *collection_stack; unsigned int collection_stack_ptr; unsigned int collection_stack_size; - struct hid_collection *active_collection; + unsigned int active_collection; struct hid_device *device; unsigned int scan_flags; };