From owner-svn-src-releng@freebsd.org Tue Jun 9 16:13:56 2020 Return-Path: Delivered-To: svn-src-releng@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 4C23D331D75; Tue, 9 Jun 2020 16:13:56 +0000 (UTC) (envelope-from gordon@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 "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49hFYJ1MJjz3yXt; Tue, 9 Jun 2020 16:13:56 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2A055182F0; Tue, 9 Jun 2020 16:13:56 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 059GDu2k089114; Tue, 9 Jun 2020 16:13:56 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 059GDssL089108; Tue, 9 Jun 2020 16:13:54 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <202006091613.059GDssL089108@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Tue, 9 Jun 2020 16:13:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r361972 - in releng: 11.3/lib/libusbhid 11.3/sys/dev/usb 11.4/lib/libusbhid 11.4/sys/dev/usb 12.1/lib/libusbhid 12.1/sys/dev/usb X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: in releng: 11.3/lib/libusbhid 11.3/sys/dev/usb 11.4/lib/libusbhid 11.4/sys/dev/usb 12.1/lib/libusbhid 12.1/sys/dev/usb X-SVN-Commit-Revision: 361972 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Jun 2020 16:13:56 -0000 Author: gordon Date: Tue Jun 9 16:13:54 2020 New Revision: 361972 URL: https://svnweb.freebsd.org/changeset/base/361972 Log: Fix USB HID descriptor parsing error. Approved by: so Approved by: re (implicit) Security: FreeBSD-SA-20:17.usb Security: CVE-2020-7456 Modified: releng/11.3/lib/libusbhid/parse.c releng/11.3/sys/dev/usb/usb_hid.c releng/11.4/lib/libusbhid/parse.c releng/11.4/sys/dev/usb/usb_hid.c releng/12.1/lib/libusbhid/parse.c releng/12.1/sys/dev/usb/usb_hid.c Modified: releng/11.3/lib/libusbhid/parse.c ============================================================================== --- releng/11.3/lib/libusbhid/parse.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/11.3/lib/libusbhid/parse.c Tue Jun 9 16:13:54 2020 (r361972) @@ -401,26 +401,28 @@ hid_get_item_raw(hid_data_t s, hid_item_t *h) s->loc_count = dval & mask; break; case 10: /* Push */ + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) + return (0); s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->report_size = s->loc_size; - c->report_count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->report_size = s->loc_size; + c->report_count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) + return (0); s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->report_size; - s->loc_count = c->report_count; - c->report_size = 0; - c->report_count = 0; - } + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->report_size; + s->loc_count = c->report_count; + c->report_size = 0; + c->report_count = 0; break; default: break; Modified: releng/11.3/sys/dev/usb/usb_hid.c ============================================================================== --- releng/11.3/sys/dev/usb/usb_hid.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/11.3/sys/dev/usb/usb_hid.c Tue Jun 9 16:13:54 2020 (r361972) @@ -434,36 +434,36 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->loc_count = dval & mask; break; case 10: /* Push */ - s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->loc.size = s->loc_size; - c->loc.count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } else { - DPRINTFN(0, "Cannot push " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) { + DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); + return (0); } + s->pushlevel ++; + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->loc.size = s->loc_size; + c->loc.count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ - s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - /* preserve position */ - oldpos = c->loc.pos; - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->loc.size; - s->loc_count = c->loc.count; - /* set default item location */ - c->loc.pos = oldpos; - c->loc.size = 0; - c->loc.count = 0; - } else { - DPRINTFN(0, "Cannot pop " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) { + DPRINTFN(0, "Cannot pop item @ 0\n"); + return (0); } + s->pushlevel --; + /* preserve position */ + oldpos = c->loc.pos; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->loc.size; + s->loc_count = c->loc.count; + /* set default item location */ + c->loc.pos = oldpos; + c->loc.size = 0; + c->loc.count = 0; break; default: DPRINTFN(0, "Global bTag=%d\n", bTag); Modified: releng/11.4/lib/libusbhid/parse.c ============================================================================== --- releng/11.4/lib/libusbhid/parse.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/11.4/lib/libusbhid/parse.c Tue Jun 9 16:13:54 2020 (r361972) @@ -401,26 +401,28 @@ hid_get_item_raw(hid_data_t s, hid_item_t *h) s->loc_count = dval & mask; break; case 10: /* Push */ + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) + return (0); s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->report_size = s->loc_size; - c->report_count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->report_size = s->loc_size; + c->report_count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) + return (0); s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->report_size; - s->loc_count = c->report_count; - c->report_size = 0; - c->report_count = 0; - } + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->report_size; + s->loc_count = c->report_count; + c->report_size = 0; + c->report_count = 0; break; default: break; Modified: releng/11.4/sys/dev/usb/usb_hid.c ============================================================================== --- releng/11.4/sys/dev/usb/usb_hid.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/11.4/sys/dev/usb/usb_hid.c Tue Jun 9 16:13:54 2020 (r361972) @@ -434,36 +434,36 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->loc_count = dval & mask; break; case 10: /* Push */ - s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->loc.size = s->loc_size; - c->loc.count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } else { - DPRINTFN(0, "Cannot push " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) { + DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); + return (0); } + s->pushlevel ++; + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->loc.size = s->loc_size; + c->loc.count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ - s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - /* preserve position */ - oldpos = c->loc.pos; - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->loc.size; - s->loc_count = c->loc.count; - /* set default item location */ - c->loc.pos = oldpos; - c->loc.size = 0; - c->loc.count = 0; - } else { - DPRINTFN(0, "Cannot pop " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) { + DPRINTFN(0, "Cannot pop item @ 0\n"); + return (0); } + s->pushlevel --; + /* preserve position */ + oldpos = c->loc.pos; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->loc.size; + s->loc_count = c->loc.count; + /* set default item location */ + c->loc.pos = oldpos; + c->loc.size = 0; + c->loc.count = 0; break; default: DPRINTFN(0, "Global bTag=%d\n", bTag); Modified: releng/12.1/lib/libusbhid/parse.c ============================================================================== --- releng/12.1/lib/libusbhid/parse.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/12.1/lib/libusbhid/parse.c Tue Jun 9 16:13:54 2020 (r361972) @@ -403,26 +403,28 @@ hid_get_item_raw(hid_data_t s, hid_item_t *h) s->loc_count = dval & mask; break; case 10: /* Push */ + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) + return (0); s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->report_size = s->loc_size; - c->report_count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->report_size = s->loc_size; + c->report_count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) + return (0); s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->report_size; - s->loc_count = c->report_count; - c->report_size = 0; - c->report_count = 0; - } + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->report_size; + s->loc_count = c->report_count; + c->report_size = 0; + c->report_count = 0; break; default: break; Modified: releng/12.1/sys/dev/usb/usb_hid.c ============================================================================== --- releng/12.1/sys/dev/usb/usb_hid.c Tue Jun 9 16:11:54 2020 (r361971) +++ releng/12.1/sys/dev/usb/usb_hid.c Tue Jun 9 16:13:54 2020 (r361972) @@ -436,36 +436,36 @@ hid_get_item(struct hid_data *s, struct hid_item *h) s->loc_count = dval & mask; break; case 10: /* Push */ - s->pushlevel ++; - if (s->pushlevel < MAXPUSH) { - s->cur[s->pushlevel] = *c; - /* store size and count */ - c->loc.size = s->loc_size; - c->loc.count = s->loc_count; - /* update current item pointer */ - c = &s->cur[s->pushlevel]; - } else { - DPRINTFN(0, "Cannot push " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if ((s->pushlevel + 1) >= MAXPUSH) { + DPRINTFN(0, "Cannot push item @ %d\n", s->pushlevel); + return (0); } + s->pushlevel ++; + s->cur[s->pushlevel] = *c; + /* store size and count */ + c->loc.size = s->loc_size; + c->loc.count = s->loc_count; + /* update current item pointer */ + c = &s->cur[s->pushlevel]; break; case 11: /* Pop */ - s->pushlevel --; - if (s->pushlevel < MAXPUSH) { - /* preserve position */ - oldpos = c->loc.pos; - c = &s->cur[s->pushlevel]; - /* restore size and count */ - s->loc_size = c->loc.size; - s->loc_count = c->loc.count; - /* set default item location */ - c->loc.pos = oldpos; - c->loc.size = 0; - c->loc.count = 0; - } else { - DPRINTFN(0, "Cannot pop " - "item @ %d\n", s->pushlevel); + /* stop parsing, if invalid push level */ + if (s->pushlevel == 0) { + DPRINTFN(0, "Cannot pop item @ 0\n"); + return (0); } + s->pushlevel --; + /* preserve position */ + oldpos = c->loc.pos; + c = &s->cur[s->pushlevel]; + /* restore size and count */ + s->loc_size = c->loc.size; + s->loc_count = c->loc.count; + /* set default item location */ + c->loc.pos = oldpos; + c->loc.size = 0; + c->loc.count = 0; break; default: DPRINTFN(0, "Global bTag=%d\n", bTag);