Re: [PATCH] tty proc bugfix

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


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 : Sun Apr 23 2000 - 21:00:19 EST