Re: [PATCH] drivers/usb/host/uhci-* : check buffer length to avoid memory overflow
Gang: I apologize for taking so long to respond to your patch. I didn't get much work done during the holidays... Overall it looks pretty good. There are a few things that I would prefer to change. On Thu, 20 Dec 2012, Chen Gang wrote: reason (why): for function uhci_sprint_schedule: the buffer len is MAX_OUTPUT: 64 * 1024 the buffer may not be enough: may loop UHCI_NUMFRAMES times (UHCI_NUMFRAMES is 1024) each time of loop may get more than 64 bytes so need check the buffer length to avoid memory overflow goal (what): this patch fixes this correctness issue. design (and why): at first, we make enough room for buffering the exceeding contents judge the contents which we have written whether bigger than buffer length if bigger (the exceeding contents will be in the exceeding buffer) break current work flow, and return test: plan: let MAX_OUTPUT as various values: some values which are enough for use, then can get full contents. some values which small enough, so can truncate in various locations. check the result: cat the contents from the /sys/kernel/debug/usb/uhci/* use wc -c to get the count of output contents (match the MAX_OUTPUT) result: make the buffer size in different size: (1024 is the room for exceeding) 63 * 1024 + 1024 1st (debug == 3) pass 2nd (debug == 3) pass 3rd (debug == 1) pass 4rd (not define DEBUG) pass 1689 + 1024 (debug == 3) pass (1689 is full contents length of my test) 1688 + 1024 (debug == 3) pass 1024 + 1024 (debug == 3) pass 512 + 1024 (debug == 3) pass 30 + 1024 (debug == 3) pass left: not test it by calling from uhci-q.c and uhci-hcd.c not test the dump objects which already have rich data contents if testing them are necessary: please tell me, I will try. and it is better to tell me how to test them. Can you rewrite this using ordinary English sentences? Describe what you changed and why you changed it. You don't have to include the details of your tests. --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -16,6 +16,8 @@ #include uhci-hcd.h +#define LEFT_OUTPUT (1024) A better name would be EXTRA_SPACE. @@ -90,7 +90,11 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, spid); out += sprintf(out, (buf=%08x)\n, hc32_to_cpu(uhci, td-buffer)); +tail: return out - buf; +truncate: + out += sprintf(out, (%s truncated)\n, __FUNCTION__); + goto tail; } Here and in all the other functions, it would be better to do this: + done: + if (out - buf len) + out += sprintf(out, ...\n); return out - buf; } You don't need to write the word truncated all the time. A simple ... will let people know what happened. Have all the goto statements jump to done. The reason for doing it this way is... @@ -135,6 +142,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, %*s%d: , space + 2, , i); out += uhci_show_td(uhci, td, out, len - (out - buf), 0); + if (out - buf len) + goto truncate; ... here you can jump directly to the return statement and avoid printing out a duplicate ... line. @@ -211,9 +224,12 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, ); i = nurbs = 0; list_for_each_entry(urbp, qh-queue, node) { - if (++i = 10) + if (++i = 10) { out += uhci_show_urbp(uhci, urbp, out, len - (out - buf), space + 2); + if (out - buf len) + goto truncate; Same here. @@ -222,24 +238,25 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, , nurbs); } + if (out - buf len) + goto truncate; + if (qh-dummy_td) { out += sprintf(out, %*s Dummy TD\n, space, ); out += uhci_show_td(uhci, qh-dummy_td, out, len - (out - buf), 0); And here. @@ -360,9 +383,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) int8, int4, int2, async, term }; - out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); + out += uhci_show_root_hub_state(uhci, out); + if (out - buf len) + goto truncate; And here. out += sprintf(out, HC status\n); out += uhci_show_status(uhci, out, len -
Re: [PATCH] drivers/usb/host/uhci-* : check buffer length to avoid memory overflow
于 2013年01月09日 04:53, Alan Stern 写道: Gang: I apologize for taking so long to respond to your patch. I didn't get much work done during the holidays... I understand. it is necessary to have a rest, so can keep our contributes (work), with efficiency and sustainable. :-) Can you rewrite this using ordinary English sentences? Describe what you changed and why you changed it. You don't have to include the details of your tests. ok, thanks. +#define LEFT_OUTPUT (1024) A better name would be EXTRA_SPACE. ok, thanks. @@ -90,7 +90,11 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, spid); out += sprintf(out, (buf=%08x)\n, hc32_to_cpu(uhci, td-buffer)); +tail: return out - buf; +truncate: +out += sprintf(out, (%s truncated)\n, __FUNCTION__); +goto tail; } Here and in all the other functions, it would be better to do this: + done: + if (out - buf len) + out += sprintf(out, ...\n); return out - buf; } ok, thanks. You don't need to write the word truncated all the time. A simple ... will let people know what happened. Have all the goto statements jump to done. The reason for doing it this way is... ok, thanks. @@ -135,6 +142,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, %*s%d: , space + 2, , i); out += uhci_show_td(uhci, td, out, len - (out - buf), 0); +if (out - buf len) +goto truncate; .. here you can jump directly to the return statement and avoid printing out a duplicate ... line. ok, thanks. I think your meaning is: use goto tail; instead of goto truncate; and the return area like this: + done: + if (out - buf len) + out += sprintf(out, ...\n); + tail: return out - buf; } if I misunderstanding, please reply. (no reply means I am not misunderstanding) @@ -375,14 +402,19 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) uhci_to_hcd(uhci)-self.bandwidth_int_reqs, uhci_to_hcd(uhci)-self.bandwidth_isoc_reqs); if (debug = 1) -return out - buf; +goto tail; out += sprintf(out, Frame List\n); +if (out - buf len) +goto truncate; This test isn't needed because there's another test inside the loop below. ok, thanks. I will send patch v2 within 4 days (execuse me, today and tommorrow, I have to do another things) -- Chen Gang Asianux Corporation -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drivers/usb/host/uhci-* : check buffer length to avoid memory overflow
reason (why): for function uhci_sprint_schedule: the buffer len is MAX_OUTPUT: 64 * 1024 the buffer may not be enough: may loop UHCI_NUMFRAMES times (UHCI_NUMFRAMES is 1024) each time of loop may get more than 64 bytes so need check the buffer length to avoid memory overflow goal (what): this patch fixes this correctness issue. design (and why): at first, we make enough room for buffering the exceeding contents judge the contents which we have written whether bigger than buffer length if bigger (the exceeding contents will be in the exceeding buffer) break current work flow, and return test: plan: let MAX_OUTPUT as various values: some values which are enough for use, then can get full contents. some values which small enough, so can truncate in various locations. check the result: cat the contents from the /sys/kernel/debug/usb/uhci/* use wc -c to get the count of output contents (match the MAX_OUTPUT) result: make the buffer size in different size: (1024 is the room for exceeding) 63 * 1024 + 1024 1st (debug == 3) pass 2nd (debug == 3) pass 3rd (debug == 1) pass 4rd (not define DEBUG) pass 1689 + 1024 (debug == 3) pass (1689 is full contents length of my test) 1688 + 1024 (debug == 3) pass 1024 + 1024 (debug == 3) pass 512 + 1024 (debug == 3) pass 30 + 1024 (debug == 3) pass left: not test it by calling from uhci-q.c and uhci-hcd.c not test the dump objects which already have rich data contents if testing them are necessary: please tell me, I will try. and it is better to tell me how to test them. Signed-off-by: Chen Gang gang.c...@asianux.com --- drivers/usb/host/uhci-debug.c | 140 + drivers/usb/host/uhci-hcd.c |4 +- drivers/usb/host/uhci-q.c |2 +- 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index fc0b0da..4951a1c 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -16,6 +16,8 @@ #include uhci-hcd.h +#define LEFT_OUTPUT(1024) + static struct dentry *uhci_debugfs_root; #ifdef DEBUG @@ -44,10 +46,6 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, char *spid; u32 status, token; - /* Try to make sure there's enough memory */ - if (len 160) - return 0; - status = td_status(uhci, td); out += sprintf(out, %*s[%p] link (%08x) , space, , td, hc32_to_cpu(uhci, td-link)); @@ -64,6 +62,8 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, (status TD_CTRL_CRCTIMEO) ? CRC/Timeo : , (status TD_CTRL_BITSTUFF) ? BitStuff : , status 0x7ff); + if (out - buf len) + goto truncate; token = td_token(uhci, td); switch (uhci_packetid(token)) { @@ -90,7 +90,11 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, spid); out += sprintf(out, (buf=%08x)\n, hc32_to_cpu(uhci, td-buffer)); +tail: return out - buf; +truncate: + out += sprintf(out, (%s truncated)\n, __FUNCTION__); + goto tail; } static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, @@ -101,8 +105,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, int i, nactive, ninactive; char *ptype; - if (len 200) - return 0; out += sprintf(out, urb_priv [%p] , urbp); out += sprintf(out, urb [%p] , urbp-urb); @@ -110,6 +112,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, Dev=%d , usb_pipedevice(urbp-urb-pipe)); out += sprintf(out, EP=%x(%s) , usb_pipeendpoint(urbp-urb-pipe), (usb_pipein(urbp-urb-pipe) ? IN : OUT)); + if (out - buf len) + goto truncate; switch (usb_pipetype(urbp-urb-pipe)) { case PIPE_ISOCHRONOUS: ptype = ISO; break; @@ -128,6 +132,9 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, Unlinked=%d, urbp-urb-unlinked); out += sprintf(out, \n); + if (out - buf len) + goto truncate; + i = nactive = ninactive = 0; list_for_each_entry(td, urbp-td_list, list) { if (urbp-qh-type != USB_ENDPOINT_XFER_ISOC @@ -135,6 +142,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, %*s%d: , space + 2, , i); out += uhci_show_td(uhci, td, out, len - (out - buf), 0);