Re: [PATCH] tty proc bugfix

From: Andrea Arcangeli (andrea@suse.de)
Date: Fri Apr 21 2000 - 14:24:49 EDT

  • Next message: Rafal Boni: "2.2.14 buffer/page cache leak?"

    On Thu, 20 Apr 2000, Manfred Spraul wrote:

    >The patch seems obviously correct (tm), could you add it to the next
    >kernel?

    I spotted a few other places (btw by reading the code it's fun because it
    seems the sg.c developer noticed something was not fully right and he
    right kept the safe approch because things wasn't clear), and I replaced
    the serial-proc fix with my one (that I'd like if it would be duplicated
    in the other places in the long run since it's faster, safer and cleaner),
    plus I fixed lseek to avoid setting the offset to negative values and
    causing weird errno on userspace instead of a proper -EINVAL (it looks not
    exploitable at least, i.e. I can't make the read proc to go out of control
    by changing randomly the f_pos, also the stuff /proc/net/raw can get such
    offset negative). This patch is incremental with your previous patch:

    diff -urN 2.3.99-pre6-pre3-manfred/drivers/char/serial.c 2.3.99-pre6-pre3-read-proc/drivers/char/serial.c
    --- 2.3.99-pre6-pre3-manfred/drivers/char/serial.c Fri Apr 21 19:17:19 2000
    +++ 2.3.99-pre6-pre3-read-proc/drivers/char/serial.c Fri Apr 21 19:21:44 2000
    @@ -3137,30 +3137,32 @@
             return ret;
     }
     
    -int rs_read_proc(char *page, char **start, off_t off, int count,
    +int rs_read_proc(char *page, char **start, off_t idx, ssize_t count,
                      int *eof, void *data)
     {
    - int i, len = 0, l;
    - off_t begin = 0;
    + int n;
     
    - len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
    - serial_version, LOCAL_VERSTRING, serial_revdate);
    - for (i = 0; i < NR_PORTS && len < 4000; i++) {
    - l = line_info(page + len, &rs_table[i]);
    - len += l;
    - if (len+begin > off+count)
    - goto done;
    - if (len+begin < off) {
    - begin += len;
    - len = 0;
    - }
    + *start = (char *) 1L;
    +
    + if (!idx) {
    + n = sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
    + serial_version, LOCAL_VERSTRING, serial_revdate);
    + goto out;
             }
    - *eof = 1;
    -done:
    - if (off >= len+begin)
    - return 0;
    - *start = page + (off-begin);
    - return ((count < begin+len-off) ? count : begin+len-off);
    + idx--;
    +
    + n = 0;
    + if (idx >= NR_PORTS || idx < 0)
    + goto out;
    +
    + n = line_info(page, &rs_table[idx]);
    + if (idx + 1 == NR_PORTS)
    + *eof = 1;
    +
    + out:
    + if (n > count)
    + n = 0;
    + return n;
     }
     
     /*
    diff -urN 2.3.99-pre6-pre3-manfred/drivers/isdn/avmb1/kcapi.c 2.3.99-pre6-pre3-read-proc/drivers/isdn/avmb1/kcapi.c
    --- 2.3.99-pre6-pre3-manfred/drivers/isdn/avmb1/kcapi.c Fri Apr 21 19:17:19 2000
    +++ 2.3.99-pre6-pre3-read-proc/drivers/isdn/avmb1/kcapi.c Fri Apr 21 19:19:06 2000
    @@ -320,7 +320,7 @@
                     *eof = 1;
             if (off >= len+begin)
                     return 0;
    - *start = page + (begin-off);
    + *start = page + (off-begin);
             return ((count < begin+len-off) ? count : begin+len-off);
     }
     
    diff -urN 2.3.99-pre6-pre3-manfred/drivers/scsi/sg.c 2.3.99-pre6-pre3-read-proc/drivers/scsi/sg.c
    --- 2.3.99-pre6-pre3-manfred/drivers/scsi/sg.c Tue Apr 18 16:11:40 2000
    +++ 2.3.99-pre6-pre3-read-proc/drivers/scsi/sg.c Fri Apr 21 19:37:35 2000
    @@ -2429,8 +2429,7 @@
             *eof = infofp(buffer, &len, &begin, offset, size); \
             if (offset >= (begin + len)) \
                 return 0; \
    - *start = buffer + ((begin > offset) ? \
    - (begin - offset) : (offset - begin)); \
    + *start = buffer + offset - begin; \
             return (size < (begin + len - offset)) ? \
                                     size : begin + len - offset; \
         } while(0)
    diff -urN 2.3.99-pre6-pre3-manfred/fs/proc/generic.c 2.3.99-pre6-pre3-read-proc/fs/proc/generic.c
    --- 2.3.99-pre6-pre3-manfred/fs/proc/generic.c Tue Apr 18 16:11:41 2000
    +++ 2.3.99-pre6-pre3-read-proc/fs/proc/generic.c Fri Apr 21 19:33:36 2000
    @@ -140,9 +140,13 @@
     {
         switch (orig) {
         case 0:
    + if (offset < 0)
    + return -EINVAL;
             file->f_pos = offset;
             return(file->f_pos);
         case 1:
    + if (offset + file->f_pos < 0)
    + return -EINVAL;
             file->f_pos += offset;
             return(file->f_pos);
         case 2:

    A full patch against 2.3.99-pre6-pre3 that is your patch plus the above
    patch is here:

            ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.3/2.3.99-pre6-pre3/serial-proc-3

    A full backport to 2.2.15pre19 is here:

            ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.2/2.2.15pre19/serial-proc-3

    (a few things aren't included in the backport because they were not
    present in 2.2.x in first place)

    Andrea

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu
    Please read the FAQ at http://www.tux.org/lkml/



    This archive was generated by hypermail 2b29 : Fri Apr 21 2000 - 14:33:56 EDT