From patchwork Mon Mar 8 20:05:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Gardner X-Patchwork-Id: 1449385 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DvTqm2Jyxz9sWY; Tue, 9 Mar 2021 07:06:12 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lJM8m-0002tu-Ms; Mon, 08 Mar 2021 20:06:08 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lJM8l-0002t2-5p for kernel-team@lists.ubuntu.com; Mon, 08 Mar 2021 20:06:07 +0000 Received: from mail-pf1-f197.google.com ([209.85.210.197]) by youngberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lJM8k-0006Pi-PX for kernel-team@lists.ubuntu.com; Mon, 08 Mar 2021 20:06:06 +0000 Received: by mail-pf1-f197.google.com with SMTP id a24so7120877pfn.6 for ; Mon, 08 Mar 2021 12:06:06 -0800 (PST) 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:in-reply-to :references; bh=e9tQsFNCZHvofyU0vqC6cYmK8UxkViSWLOxJK2460Ig=; b=Sbv267EBoxu0nqRSxnErl1FmWAJPnv4JXr2gZmHMOc2vUXMaqcjjBC1vSR/8icRaNE S5XsC0YccdOyT51+FuI3kJLuUdQKvjnuYBH60oyU9K6ZsaLErvZ5ShVSv3Zt2tNbNb5E OpyYMNndc23BLcjRDTaVtZNbqYLtevmoMO/KIwE1qh1Ex0EdRe6r3e2XHbNRlpX3rPBq mTK7w+rKjSCFSvN9lzJguvze0T4mw1OPl+QkA9CZ2MARYokdo5pY5WF6DenyGteW16eD Qqk4azUaNWe3TZ71VBnPXM2JOB7JTP8qQ1zf5JAi8gC+9SwdvFNGbZWYgrHI1pTg5Zcb +aZA== X-Gm-Message-State: AOAM531JNRI37KuNi/mi1YFGVE/EDs44vyirmmaVN3K/p8MsZY3S8Ci8 oxPIsLTBEl/eBPHMaCl6HASm70IgLb5glifm3O/zhA9axRX68OY5E15ETB6J9zqqJGE/k/MSqeb BukoNwvn28Ii0ReU/8HNX5DQsK+Rkm7h+QK1ygJDtPA== X-Received: by 2002:a62:ea09:0:b029:1ee:3bac:8012 with SMTP id t9-20020a62ea090000b02901ee3bac8012mr22324105pfh.35.1615233964834; Mon, 08 Mar 2021 12:06:04 -0800 (PST) X-Google-Smtp-Source: ABdhPJxGVGd5CvA/sr8tD+a8SAf2R9ZHZlNjGaHoikGKEGQV0itBhBWX8Fjsq7PD9w8i1/9J92ZoyA== X-Received: by 2002:a62:ea09:0:b029:1ee:3bac:8012 with SMTP id t9-20020a62ea090000b02901ee3bac8012mr22324091pfh.35.1615233964619; Mon, 08 Mar 2021 12:06:04 -0800 (PST) Received: from localhost.localdomain ([69.163.84.166]) by smtp.gmail.com with ESMTPSA id s4sm211585pji.2.2021.03.08.12.06.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Mar 2021 12:06:03 -0800 (PST) From: Tim Gardner To: kernel-team@lists.ubuntu.com Subject: [PATCH 2/2] HID: core: Sanitize event code and type when mapping input Date: Mon, 8 Mar 2021 13:05:58 -0700 Message-Id: <20210308200558.23387-3-tim.gardner@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210308200558.23387-1-tim.gardner@canonical.com> References: <20210308200558.23387-1-tim.gardner@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Marc Zyngier CVE-2020-0465 When calling into hid_map_usage(), the passed event code is blindly stored as is, even if it doesn't fit in the associated bitmap. This event code can come from a variety of sources, including devices masquerading as input devices, only a bit more "programmable". Instead of taking the event code at face value, check that it actually fits the corresponding bitmap, and if it doesn't: - spit out a warning so that we know which device is acting up - NULLify the bitmap pointer so that we catch unexpected uses Code paths that can make use of untrusted inputs can now check that the mapping was indeed correct and bail out if not. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Signed-off-by: Benjamin Tissoires (cherry picked from commit 35556bed836f8dc07ac55f69c8d17dce3e7f0e25) Signed-off-by: Tim Gardner --- drivers/hid/hid-input.c | 4 ++++ drivers/hid/hid-multitouch.c | 2 ++ include/linux/hid.h | 42 +++++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index dea9cc65bf80..0eceb5b27637 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1132,6 +1132,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } mapped: + /* Mapping failed, bail out */ + if (!bit) + return; + if (device->driver->input_mapped && device->driver->input_mapped(device, hidinput, field, usage, &bit, &max) < 0) { diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 39e4da7468e1..128d8f4319b9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -864,6 +864,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, code = BTN_0 + ((usage->hid - 1) & HID_USAGE); hid_map_usage(hi, usage, bit, max, EV_KEY, code); + if (!*bit) + return -1; input_set_capability(hi->input, EV_KEY, code); return 1; diff --git a/include/linux/hid.h b/include/linux/hid.h index 875f71132b14..c7044a14200e 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -959,34 +959,49 @@ static inline void hid_device_io_stop(struct hid_device *hid) { * @max: maximal valid usage->code to consider later (out parameter) * @type: input event type (EV_KEY, EV_REL, ...) * @c: code which corresponds to this usage and type + * + * The value pointed to by @bit will be set to NULL if either @type is + * an unhandled event type, or if @c is out of range for @type. This + * can be used as an error condition. */ static inline void hid_map_usage(struct hid_input *hidinput, struct hid_usage *usage, unsigned long **bit, int *max, - __u8 type, __u16 c) + __u8 type, unsigned int c) { struct input_dev *input = hidinput->input; - - usage->type = type; - usage->code = c; + unsigned long *bmap = NULL; + unsigned int limit = 0; switch (type) { case EV_ABS: - *bit = input->absbit; - *max = ABS_MAX; + bmap = input->absbit; + limit = ABS_MAX; break; case EV_REL: - *bit = input->relbit; - *max = REL_MAX; + bmap = input->relbit; + limit = REL_MAX; break; case EV_KEY: - *bit = input->keybit; - *max = KEY_MAX; + bmap = input->keybit; + limit = KEY_MAX; break; case EV_LED: - *bit = input->ledbit; - *max = LED_MAX; + bmap = input->ledbit; + limit = LED_MAX; break; } + + if (unlikely(c > limit || !bmap)) { + pr_warn_ratelimited("%s: Invalid code %d type %d\n", + input->name, c, type); + *bit = NULL; + return; + } + + usage->type = type; + usage->code = c; + *max = limit; + *bit = bmap; } /** @@ -1000,7 +1015,8 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput, __u8 type, __u16 c) { hid_map_usage(hidinput, usage, bit, max, type, c); - clear_bit(c, *bit); + if (*bit) + clear_bit(usage->code, *bit); } /**