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
Gordon Tetlow
gordon at FreeBSD.org
Tue Jun 9 16:13:56 UTC 2020
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);
More information about the svn-src-all
mailing list