Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7084191d53b224b953c8e1db525ea6c31aca5fc7
Commit:     7084191d53b224b953c8e1db525ea6c31aca5fc7
Parent:     274399d14f121d7676ecb75a461cfed6cf9e4cdb
Author:     Alan Stern <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 20 14:15:58 2008 -0500
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Thu Feb 21 15:38:55 2008 -0800

    USB: usb-storage: don't access beyond the end of the sg buffer
    
    This patch (as1035) fixes a bug in usb_stor_access_xfer_buf() (the bug
    was originally found by Boaz Harrosh): The routine must not attempt to
    write beyond the end of a scatter-gather list or beyond the number of
    bytes requested.  It also fixes up the formatting of a few comments
    and similar whitespace issues.
    
    Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/storage/protocol.c |   27 +++++++++++++++------------
 1 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index a41ce21..958f5b1 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -150,13 +150,14 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd 
*srb,
 
 /* Copy a buffer of length buflen to/from the srb's transfer buffer.
  * Update the **sgptr and *offset variables so that the next copy will
- * pick up from where this one left off. */
-
+ * pick up from where this one left off.
+ */
 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
        unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
        unsigned int *offset, enum xfer_buf_dir dir)
 {
        unsigned int cnt;
+       struct scatterlist *sg = *sgptr;
 
        /* We have to go through the list one entry
         * at a time.  Each s-g entry contains some number of pages, and
@@ -164,22 +165,23 @@ unsigned int usb_stor_access_xfer_buf(unsigned char 
*buffer,
         * in kernel-addressable memory then kmap() will return its address.
         * If the page is not directly accessible -- such as a user buffer
         * located in high memory -- then kmap() will map it to a temporary
-        * position in the kernel's virtual address space. */
-       struct scatterlist *sg = *sgptr;
+        * position in the kernel's virtual address space.
+        */
 
        if (!sg)
                sg = scsi_sglist(srb);
+       buflen = min(buflen, scsi_bufflen(srb));
 
        /* This loop handles a single s-g list entry, which may
-               * include multiple pages.  Find the initial page structure
-               * and the starting offset within the page, and update
-               * the *offset and **sgptr values for the next loop. */
+        * include multiple pages.  Find the initial page structure
+        * and the starting offset within the page, and update
+        * the *offset and **sgptr values for the next loop.
+        */
        cnt = 0;
-       while (cnt < buflen) {
+       while (cnt < buflen && sg) {
                struct page *page = sg_page(sg) +
                                ((sg->offset + *offset) >> PAGE_SHIFT);
-               unsigned int poff =
-                               (sg->offset + *offset) & (PAGE_SIZE-1);
+               unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
                unsigned int sglen = sg->length - *offset;
 
                if (sglen > buflen - cnt) {
@@ -222,14 +224,15 @@ unsigned int usb_stor_access_xfer_buf(unsigned char 
*buffer,
 }
 
 /* Store the contents of buffer into srb's transfer buffer and set the
- * SCSI residue. */
+ * SCSI residue.
+ */
 void usb_stor_set_xfer_buf(unsigned char *buffer,
        unsigned int buflen, struct scsi_cmnd *srb)
 {
        unsigned int offset = 0;
        struct scatterlist *sg = NULL;
 
-       usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
+       buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
                        TO_XFER_BUF);
        if (buflen < scsi_bufflen(srb))
                scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to