[PATCH] Fix for write to an array past its size

Juan Perez-Sanchez <[email protected]>
Newsgroups gmane.linux.ports.x8086
Message-ID <CAD6VGuaqg9=0aFqSBnYVbNcuGx9i+pGwtp2ZvEPE2D0JPnCO_w@mail.gmail.com>
Hi,

This patch fixes a bug in file fs/devices.c, function kdevname(),
where it overwrites the memory location following the end of static
array "buffer".

In file fs/minix/dir.c, function minix_dir_read(), changed its
declaration from using traditional C to ansi C.

Several improvements to code in fs and fs/minix directories

Code size was reduced by 176 bytes and data size reduced in 96 bytes.

Greetings,

Juan
elks-2i.patch (text/x-patch, 8.8 KB)
diff -Nur elks.orig/fs/buffer.c elks/fs/buffer.c
--- elks.orig/fs/buffer.c	2014-12-01 14:07:00.000000000 -0600
+++ elks/fs/buffer.c	2014-12-01 15:41:32.000000000 -0600
@@ -167,12 +167,12 @@
 
 static struct buffer_head *find_buffer(kdev_t dev, block_t block)
 {
-    register struct buffer_head *tmp;
+    register struct buffer_head *bh;
 
-    for (tmp = bh_chain; tmp != NULL; tmp = tmp->b_next)
-	if (tmp->b_blocknr == block && tmp->b_dev == dev)
+    for (bh = bh_chain; bh != NULL; bh = bh->b_next)
+	if (bh->b_blocknr == block && bh->b_dev == dev)
 	    break;
-    return tmp;
+    return bh;
 }
 
 static struct buffer_head *get_free_buffer(void)
@@ -521,8 +521,10 @@
 
 #ifdef CONFIG_FS_EXTERNAL_BUFFER
     _buf_ds = mm_alloc(NR_BUFFERS * 0x40);
-    for (i = 0; i < NR_MAPBUFS; i++)
+    i = 0;
+    do {
 	bufmem_map[i] = NULL;
+    } while(++i < NR_MAPBUFS);
 #endif
 
     buffers[0].b_prev_lru = NULL;
diff -Nur elks.orig/fs/devices.c elks/fs/devices.c
--- elks.orig/fs/devices.c	2014-11-27 10:53:27.000000000 -0600
+++ elks/fs/devices.c	2014-12-01 15:48:49.000000000 -0600
@@ -241,7 +241,7 @@
 {
 #if (MINORBITS == 8) && (MINORMASK == 255)
     static char buffer[5];
-    register char *bp = buffer + 5;
+    register char *bp = buffer + 4;
     *bp = 0;
     do {
 	*--bp = hex_string[dev & 0xf];
diff -Nur elks.orig/fs/exec.c elks/fs/exec.c
--- elks.orig/fs/exec.c	2014-11-27 10:53:27.000000000 -0600
+++ elks/fs/exec.c	2014-12-01 16:18:20.000000000 -0600
@@ -66,7 +66,6 @@
     gid_t effgid;
     lsize_t len;
     size_t result;
-    char load_code = 0;
 
     /*
      *      Open the image
@@ -183,7 +182,18 @@
         if (!cseg) {
             goto error_exec2;
         }
-        load_code = 1;
+        tregs->ds = cseg;
+        result = filp->f_op->read(inode, filp, 0, mh.tseg);
+        tregs->ds = ds;
+        if (result != mh.tseg) {
+            debug2("EXEC(tseg read): bad result %u, expected %u\n",
+	       result, mh.tseg);
+	    retval = -ENOEXEC;
+	    goto error_exec3;
+        }
+    }
+    else {
+        filp->f_pos += mh.tseg;
     }
 
     /*
@@ -210,19 +220,6 @@
     debug2("EXEC: Malloc succeeded - cs=%x ds=%x\n", cseg, dseg);
 
     retval = -ENOEXEC;
-    if(load_code){
-        tregs->ds = cseg;
-        result = filp->f_op->read(inode, filp, 0, mh.tseg);
-        tregs->ds = ds;
-        if (result != mh.tseg) {
-            debug2("EXEC(tseg read): bad result %u, expected %u\n",
-	       result, mh.tseg);
-	    goto error_exec4;
-        }
-    } else {
-        filp->f_pos += mh.tseg;
-    }
-
     tregs->ds = dseg;
     result = filp->f_op->read(inode, filp, (char *)stack_top, mh.dseg);
     tregs->ds = ds;
diff -Nur elks.orig/fs/minix/dir.c elks/fs/minix/dir.c
--- elks.orig/fs/minix/dir.c	2014-11-27 10:53:27.000000000 -0600
+++ elks/fs/minix/dir.c	2014-12-01 15:46:09.000000000 -0600
@@ -16,11 +16,7 @@
 
 #include <arch/segment.h>
 
-static int minix_dir_read(inode, filp, buf, count)
-     struct inode *inode;
-     struct file *filp;
-     char *buf;
-     int count;
+static int minix_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
 {
     return -EISDIR;
 }
diff -Nur elks.orig/fs/minix/inode.c elks/fs/minix/inode.c
--- elks.orig/fs/minix/inode.c	2014-12-01 14:07:00.000000000 -0600
+++ elks/fs/minix/inode.c	2014-12-01 15:29:52.000000000 -0600
@@ -30,7 +30,7 @@
 
 /* Function definitions */
 
-void minix_put_inode(register struct inode *inode)
+static void minix_put_inode(register struct inode *inode)
 {
     if (!inode->i_nlink) {
 	inode->i_size = 0;
@@ -420,50 +420,59 @@
 }
 
 /*
- * The minix V1 function to read an inode.
+ * The minix V1 function to read an inode into a buffer.
  */
 
-static void minix_read_inode(register struct inode *inode)
+static struct buffer_head *minix_get_inode(register struct inode *inode,
+					   struct minix_inode **raw_inode)
 {
-    struct buffer_head *bh;
-    struct minix_inode *raw_inode;
+    register struct buffer_head *bh = NULL;
     unsigned short block;
     unsigned int ino;
 
     ino = inode->i_ino;
-    inode->i_op = NULL;
-    inode->i_mode = 0;
-    {
-	/* Isolate register variable */
-	register struct super_block *isb = inode->i_sb;
-
-	if (!ino || ino > isb->u.minix_sb.s_ninodes) {
-	    printk("Bad inode number on dev %s: %d is out of range\n",
-		   kdevname(inode->i_dev), ino);
-	    return;
-	}
-	block = isb->u.minix_sb.s_imap_blocks + 2 +
-	    isb->u.minix_sb.s_zmap_blocks + (ino - 1) / MINIX_INODES_PER_BLOCK;
+    if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
+	printk("Bad inode number on dev %s: %d is out of range\n",
+		kdevname(inode->i_dev), ino);
     }
-    if (!(bh = bread(inode->i_dev, (block_t) block))) {
-	printk("Major problem: unable to read inode from dev %s\n",
-	       kdevname(inode->i_dev));
-	return;
+    else {
+	block = inode->i_sb->u.minix_sb.s_imap_blocks + 2 +
+	    inode->i_sb->u.minix_sb.s_zmap_blocks + (ino - 1) / MINIX_INODES_PER_BLOCK;
+	if (!(bh = bread(inode->i_dev, (block_t) block))) {
+	    printk("unable to read i-node block\n");
+	}
+	else {
+	    map_buffer(bh);
+	    *raw_inode = ((struct minix_inode *) bh->b_data) +
+		(ino - 1) % MINIX_INODES_PER_BLOCK;
+	}
     }
-    map_buffer(bh);
-    raw_inode = ((struct minix_inode *) bh->b_data) +
-	(ino - 1) % MINIX_INODES_PER_BLOCK;
-    memcpy(inode, raw_inode, sizeof(struct minix_inode));
-    inode->i_ctime = inode->i_atime = inode->i_mtime;
+    return bh;
+}
+
+/*
+ * The minix V1 function to read an inode.
+ */
+
+static void minix_read_inode(register struct inode *inode)
+{
+    register struct buffer_head *bh;
+    struct minix_inode *raw_inode;
+
+    bh = minix_get_inode(inode, &raw_inode);
+    if(bh) {
+	memcpy(inode, raw_inode, sizeof(struct minix_inode));
+	inode->i_ctime = inode->i_atime = inode->i_mtime;
 
 #ifdef BLOAT_FS
-    inode->i_blocks = inode->i_blksize = 0;
+	inode->i_blocks = inode->i_blksize = 0;
 #endif
 
-    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-	inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
-    unmap_brelse(bh);
-    minix_set_ops(inode);
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+	    inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
+	unmap_brelse(bh);
+	minix_set_ops(inode);
+    }
 }
 
 /*
@@ -472,36 +481,17 @@
 
 static struct buffer_head *minix_update_inode(register struct inode *inode)
 {
-    register struct buffer_head *bh;
+    register struct buffer_head *bh = NULL;
     struct minix_inode *raw_inode;
-    unsigned int ino;
-    unsigned short block;
 
-    ino = inode->i_ino;
-    if (!ino || ino > inode->i_sb->u.minix_sb.s_ninodes) {
-	printk("Bad inode number on dev %s: %d is out of range\n",
-	       kdevname(inode->i_dev), ino);
+    bh = minix_get_inode(inode, &raw_inode);
+    if(bh) {
+	memcpy(raw_inode, inode, sizeof(struct minix_inode));
+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+	    raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
 	inode->i_dirt = 0;
-	bh = 0;
-    } else {
-	block = inode->i_sb->u.minix_sb.s_imap_blocks + 2 +
-	    inode->i_sb->u.minix_sb.s_zmap_blocks + (ino - 1)
-	    / MINIX_INODES_PER_BLOCK;
-
-	if (!(bh = bread(inode->i_dev, (block_t) block))) {
-	    printk("unable to read i-node block\n");
-	    inode->i_dirt = 0;
-	} else {
-	    map_buffer(bh);
-	    raw_inode = ((struct minix_inode *) bh->b_data) +
-		(ino - 1) % MINIX_INODES_PER_BLOCK;
-	    memcpy(raw_inode, inode, sizeof(struct minix_inode));
-	    if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev);
-	    inode->i_dirt = 0;
-	    mark_buffer_dirty(bh, 1);
-	    unmap_buffer(bh);
-	}
+	mark_buffer_dirty(bh, 1);
+	unmap_buffer(bh);
     }
     return bh;
 }
diff -Nur elks.orig/fs/read_write.c elks/fs/read_write.c
--- elks.orig/fs/read_write.c	2014-11-27 10:53:27.000000000 -0600
+++ elks/fs/read_write.c	2014-12-01 17:26:57.000000000 -0600
@@ -19,7 +19,7 @@
 {
     register struct file *file;
     register struct file_operations *fop;
-    loff_t offset, tmp;
+    loff_t offset;
 
     offset = (loff_t) get_user_long(p_offset);
     if (fd >= NR_OPEN || !(file = current->files.fd[fd])
@@ -33,27 +33,23 @@
 
     /* this is the default handler if no lseek handler is present */
     /* Note: We already determined above that origin is in range. */
-    if (origin == 2) {
-	if (!file->f_inode)
-	    return -EINVAL;
-	tmp = file->f_inode->i_size + offset;
-    } else {
-	tmp = (!origin) ? offset : file->f_pos + offset;
-    }
+    if(origin == 1)
+	offset += file->f_pos;
+    else if(origin == 2)
+	offset += file->f_inode->i_size;
 
-    if (tmp < 0)
+    if(offset < 0)
 	return -EINVAL;
-    if (tmp != file->f_pos) {
-	file->f_pos = tmp;
 
 #ifdef BLOAT_FS
+    if(offset != file->f_pos) {
 	file->f_reada = 0;
 	file->f_version = ++event;
-#endif
-
     }
+#endif
 
-    put_user_long((unsigned long int)tmp, (void *)p_offset);
+    file->f_pos = offset;
+    put_user_long((unsigned long int)offset, (void *)p_offset);
 
     return 0;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.