From nobody Sun Dec 22 03:17:53 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YG5v5312Lz5hvkr; Sun, 22 Dec 2024 03:17:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YG5v51pGmz4BGB; Sun, 22 Dec 2024 03:17:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734837473; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7hVhombS8Ld1b3Bk/PQBUVp8vwd8k54LYkYVsb7vNU8=; b=RAQ2uYvXDFMWTYYC/UkF5XT1SvNN/Ijm6KPitQjOiWfOXtP9cLcqSV13WaHgTygqq3oW4F 9XS8vdUwEh8SBDArvKQ9DtOU3Nx0Vq1f9iWQDSI9zJwjTy1D5JsE9duEkpnmtSaXRnEPdW FpafaGTJsotZdmbRVA4+Y43b7yWZpxXzmxReYvOqHm30xVjrBd5AMICYtpjDyZw5WLQOEO TcBdxTvQrhKAFRgxxDkkfzbRV63qOd9i8mznvCSxqK+2bKmFa8AFgl687js01IZCws91up q5//uBG0gqv3z72Ze4WCvxgFCkW9QrVm1FTAOrnuyptSwOvFxX+Sd/fD5Cazsg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734837473; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=7hVhombS8Ld1b3Bk/PQBUVp8vwd8k54LYkYVsb7vNU8=; b=a7otNMxLFUpypyQoUEa1ztVllKOPz2NUT3pGCPWbiSzcyTZCpnO2ociO1nP5Rr9waRVmFe egPEwrkfQGxZuqsUucGE8M1VqfTaeNBfmF4585ehvmHIltbCUdsQoMRjRbmycebDZE/zhh qo4tq6POii0sLw17YjZHS+vmJCuRBjNFpr/u0enqB9LPwyKefNAUb7SUIeCOUtpbaZloo1 ywmZ8rH526czf3Zb4PVeDh6LnV9gPhl+elEKzDt2YhJj824zC0NDe/ohRjAgGcbMkPyVgE tG4ZRACZFAMY51QzsIdhZgNI1Lcg2E/WGCZIeSsUag6Lj9JkIUagTbdjiUqm6Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1734837473; a=rsa-sha256; cv=none; b=WCcHk5JGe9LN5nE0Nq1DbeUKyPSl0ORhNOmyb4UxSMpdfGlJ1ny0F1k7LfJpiOWnQXO42Z dvCkkwJa/YYVNhGHu9a12lNVYxTSE7c9vtI9XYU6G4DWMH6cWfOkqBfwI4lOqbNZ2KcHPu Whb8/atR8l0b8QO1bf7jyPw4rNUPeL/jMJVaejCn6WEd/w9ObRz5ETus5y3eV24bh7BLJl uFaigUPh/bhRaws8uwT6K85gf9WMHE6uYpMRe+B+maO1qYkzOU0WEoAbr2XVl2Tj75J3MR x9eTCbchytLUh+V79CcfZBA3fSoqTqGSTjtpTEUNm0kjCLnI2MaJ+0xJgBP0ZA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YG5v51PlLzr9h; Sun, 22 Dec 2024 03:17:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4BM3HrhA015201; Sun, 22 Dec 2024 03:17:53 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4BM3HrMM015198; Sun, 22 Dec 2024 03:17:53 GMT (envelope-from git) Date: Sun, 22 Dec 2024 03:17:53 GMT Message-Id: <202412220317.4BM3HrMM015198@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Vladimir Kondratyev Subject: git: 38b67578fb4b - main - hid: Correctly handle signed/unsigned quantities in kernel HID parser. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: wulf X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 38b67578fb4bbf568f7012ca3921a4d15cfe7c5d Auto-Submitted: auto-generated The branch main has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=38b67578fb4bbf568f7012ca3921a4d15cfe7c5d commit 38b67578fb4bbf568f7012ca3921a4d15cfe7c5d Author: Vladimir Kondratyev AuthorDate: 2024-12-22 03:16:11 +0000 Commit: Vladimir Kondratyev CommitDate: 2024-12-22 03:16:11 +0000 hid: Correctly handle signed/unsigned quantities in kernel HID parser. Wrong signedness of usage value results in inverted range check in hmt(4) driver that allows out of bound array access leading to panic. Reported by: many Sponsored by: Future Crew, LLC Obtained from: NetBSD NetBSD PR: kern/53605 PR: 274014, 282592 --- sys/dev/hid/hid.c | 91 +++++++++++++++++++++++++++++-------------------------- sys/dev/hid/hid.h | 32 +++++++++---------- 2 files changed, 64 insertions(+), 59 deletions(-) diff --git a/sys/dev/hid/hid.c b/sys/dev/hid/hid.c index 4b5d4a81b51e..453c37d806fc 100644 --- a/sys/dev/hid/hid.c +++ b/sys/dev/hid/hid.c @@ -69,7 +69,7 @@ hid_test_quirk_t *hid_test_quirk_p = &hid_test_quirk_w; #define MAXLOCCNT 2048 struct hid_pos_data { - int32_t rid; + uint32_t rid; uint32_t pos; }; @@ -79,9 +79,9 @@ struct hid_data { const uint8_t *p; struct hid_item cur[MAXPUSH]; struct hid_pos_data last_pos[MAXID]; - int32_t usages_min[MAXUSAGE]; - int32_t usages_max[MAXUSAGE]; - int32_t usage_last; /* last seen usage */ + uint32_t usages_min[MAXUSAGE]; + uint32_t usages_max[MAXUSAGE]; + uint32_t usage_last; /* last seen usage */ uint32_t loc_size; /* last seen size */ uint32_t loc_count; /* last seen count */ uint32_t ncount; /* end usage item count */ @@ -117,7 +117,7 @@ hid_clear_local(struct hid_item *c) } static void -hid_switch_rid(struct hid_data *s, struct hid_item *c, int32_t next_rID) +hid_switch_rid(struct hid_data *s, struct hid_item *c, uint32_t next_rID) { uint8_t i; @@ -242,6 +242,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) uint32_t oldpos; int32_t mask; int32_t dval; + uint32_t uval; if (s == NULL) return (0); @@ -253,10 +254,10 @@ hid_get_item(struct hid_data *s, struct hid_item *h) if (s->icount < s->ncount) { /* get current usage */ if (s->iusage < s->nusage) { - dval = s->usages_min[s->iusage] + s->ousage; - c->usage = dval; - s->usage_last = dval; - if (dval == s->usages_max[s->iusage]) { + uval = s->usages_min[s->iusage] + s->ousage; + c->usage = uval; + s->usage_last = uval; + if (uval == s->usages_max[s->iusage]) { s->iusage ++; s->ousage = 0; } else { @@ -264,7 +265,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) } } else { DPRINTFN(1, "Using last usage\n"); - dval = s->usage_last; + uval = s->usage_last; } c->nusages = 1; /* array type HID item may have multiple usages */ @@ -318,28 +319,32 @@ hid_get_item(struct hid_data *s, struct hid_item *h) } switch (bSize) { case 0: - dval = 0; + uval = 0; + dval = uval; mask = 0; break; case 1: - dval = (int8_t)hid_get_byte(s, 1); + uval = hid_get_byte(s, 1); + dval = (int8_t)uval; mask = 0xFF; break; case 2: - dval = hid_get_byte(s, 1); - dval |= hid_get_byte(s, 1) << 8; - dval = (int16_t)dval; + uval = hid_get_byte(s, 1); + uval |= hid_get_byte(s, 1) << 8; + dval = (int16_t)uval; mask = 0xFFFF; break; case 4: - dval = hid_get_byte(s, 1); - dval |= hid_get_byte(s, 1) << 8; - dval |= hid_get_byte(s, 1) << 16; - dval |= hid_get_byte(s, 1) << 24; + uval = hid_get_byte(s, 1); + uval |= hid_get_byte(s, 1) << 8; + uval |= hid_get_byte(s, 1) << 16; + uval |= hid_get_byte(s, 1) << 24; + dval = uval; mask = 0xFFFFFFFF; break; default: - dval = hid_get_byte(s, bSize); + uval = hid_get_byte(s, bSize); + dval = uval; DPRINTFN(0, "bad length %u (data=0x%02x)\n", bSize, dval); continue; @@ -351,7 +356,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) case 8: /* Input */ c->kind = hid_input; ret: - c->flags = dval; + c->flags = uval; c->loc.count = s->loc_count; c->loc.size = s->loc_size; @@ -381,7 +386,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) goto ret; case 10: /* Collection */ c->kind = hid_collection; - c->collection = dval; + c->collection = uval; c->collevel++; c->usage = s->usage_last; c->nusages = 1; @@ -407,7 +412,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h) case 1: /* Global */ switch (bTag) { case 0: - c->_usage_page = dval << 16; + c->_usage_page = uval << 16; break; case 1: c->logical_minimum = dval; @@ -422,21 +427,21 @@ hid_get_item(struct hid_data *s, struct hid_item *h) c->physical_maximum = dval; break; case 5: - c->unit_exponent = dval; + c->unit_exponent = uval; break; case 6: - c->unit = dval; + c->unit = uval; break; case 7: /* mask because value is unsigned */ - s->loc_size = dval & mask; + s->loc_size = uval & mask; break; case 8: - hid_switch_rid(s, c, dval & mask); + hid_switch_rid(s, c, uval & mask); break; case 9: /* mask because value is unsigned */ - s->loc_count = dval & mask; + s->loc_count = uval & mask; break; case 10: /* Push */ /* stop parsing, if invalid push level */ @@ -479,14 +484,14 @@ hid_get_item(struct hid_data *s, struct hid_item *h) switch (bTag) { case 0: if (bSize != 4) - dval = (dval & mask) | c->_usage_page; + uval = (uval & mask) | c->_usage_page; /* set last usage, in case of a collection */ - s->usage_last = dval; + s->usage_last = uval; if (s->nusage < MAXUSAGE) { - s->usages_min[s->nusage] = dval; - s->usages_max[s->nusage] = dval; + s->usages_min[s->nusage] = uval; + s->usages_max[s->nusage] = uval; s->nusage ++; } else { DPRINTFN(0, "max usage reached\n"); @@ -499,16 +504,16 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->susage |= 1; if (bSize != 4) - dval = (dval & mask) | c->_usage_page; - c->usage_minimum = dval; + uval = (uval & mask) | c->_usage_page; + c->usage_minimum = uval; goto check_set; case 2: s->susage |= 2; if (bSize != 4) - dval = (dval & mask) | c->_usage_page; - c->usage_maximum = dval; + uval = (uval & mask) | c->_usage_page; + c->usage_maximum = uval; check_set: if (s->susage != 3) @@ -529,25 +534,25 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->susage = 0; break; case 3: - c->designator_index = dval; + c->designator_index = uval; break; case 4: - c->designator_minimum = dval; + c->designator_minimum = uval; break; case 5: - c->designator_maximum = dval; + c->designator_maximum = uval; break; case 7: - c->string_index = dval; + c->string_index = uval; break; case 8: - c->string_minimum = dval; + c->string_minimum = uval; break; case 9: - c->string_maximum = dval; + c->string_maximum = uval; break; case 10: - c->set_delimiter = dval; + c->set_delimiter = uval; break; default: DPRINTFN(0, "Local bTag=%d\n", bTag); diff --git a/sys/dev/hid/hid.h b/sys/dev/hid/hid.h index 09fad96c9559..aeb0da98b181 100644 --- a/sys/dev/hid/hid.h +++ b/sys/dev/hid/hid.h @@ -233,31 +233,31 @@ struct hid_location { struct hid_item { /* Global */ - int32_t _usage_page; + uint32_t _usage_page; int32_t logical_minimum; int32_t logical_maximum; int32_t physical_minimum; int32_t physical_maximum; - int32_t unit_exponent; - int32_t unit; - int32_t report_ID; + uint32_t unit_exponent; + uint32_t unit; + uint32_t report_ID; /* Local */ int nusages; union { - int32_t usage; - int32_t usages[HID_ITEM_MAXUSAGE]; + uint32_t usage; + uint32_t usages[HID_ITEM_MAXUSAGE]; }; - int32_t usage_minimum; - int32_t usage_maximum; - int32_t designator_index; - int32_t designator_minimum; - int32_t designator_maximum; - int32_t string_index; - int32_t string_minimum; - int32_t string_maximum; - int32_t set_delimiter; + uint32_t usage_minimum; + uint32_t usage_maximum; + uint32_t designator_index; + uint32_t designator_minimum; + uint32_t designator_maximum; + uint32_t string_index; + uint32_t string_minimum; + uint32_t string_maximum; + uint32_t set_delimiter; /* Misc */ - int32_t collection; + uint32_t collection; int collevel; enum hid_kind kind; uint32_t flags;