proc corruption 2.2.16pre1

From: Andrea Arcangeli (andrea@suse.de)
Date: Wed May 03 2000 - 13:14:03 EST


The fix in 2.2.16pre1 for the /proc corruption issues is not complete. I
also suggest to use my approch at least in the serial case where I just
spent the time to rewrite it, since it will make sure to not get corrupted
lines due the serial port that changes state from under us while we
returned from the rs_proc_read and where we don't hold any lock and it
will be also more efficient and simpler. The only downside of my approch
is that lseeks will work in units of lines and not of bytes but who runs
lseek in /proc/tty/driver/serial and how many instead reads such file and
want to see it not corrupted?

diff -urN 2.2.16pre1/drivers/char/nvram.c serial-proc/drivers/char/nvram.c
--- 2.2.16pre1/drivers/char/nvram.c Mon Jan 17 16:44:37 2000
+++ serial-proc/drivers/char/nvram.c Wed May 3 20:02:39 2000
@@ -373,7 +373,7 @@
 
     if (offset >= begin + len)
                 return( 0 );
- *start = buffer + (begin - offset);
+ *start = buffer + (offset - begin);
     return( size < begin + len - offset ? size : begin + len - offset );
         
 }
diff -urN 2.2.16pre1/drivers/char/serial.c serial-proc/drivers/char/serial.c
--- 2.2.16pre1/drivers/char/serial.c Wed May 3 19:58:36 2000
+++ serial-proc/drivers/char/serial.c Wed May 3 20:03:43 2000
@@ -2782,29 +2782,31 @@
         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\n", serial_version);
- for (i = 0; i < NR_PORTS && len < 3900; 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\n", serial_version);
+ 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.2.16pre1/fs/proc/generic.c serial-proc/fs/proc/generic.c
--- 2.2.16pre1/fs/proc/generic.c Mon Jan 17 16:44:43 2000
+++ serial-proc/fs/proc/generic.c Wed May 3 20:02:39 2000
@@ -198,9 +198,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:
diff -urN 2.2.16pre1/net/irda/ircomm/ircomm_tty.c serial-proc/net/irda/ircomm/ircomm_tty.c
--- 2.2.16pre1/net/irda/ircomm/ircomm_tty.c Fri Apr 21 15:59:25 2000
+++ serial-proc/net/irda/ircomm/ircomm_tty.c Wed May 3 20:02:40 2000
@@ -1347,7 +1347,7 @@
 done:
         if (offset >= count+begin)
                 return 0;
- *start = buf + (begin-offset);
+ *start = buf + (offset-begin);
         return ((len < begin+count-offset) ? len : begin+count-offset);
 }
 

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 May 07 2000 - 21:00:12 EST