Date: Tue, 9 Jun 2020 16:13:54 +0000 (UTC) From: Gordon Tetlow <gordon@FreeBSD.org> 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 Message-ID: <202006091613.059GDssL089108@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006091613.059GDssL089108>