[PATCH] Fix for write to an array past its size
Juan Perez-Sanchez <[email protected]> Sat, 6 Dec 2014 12:48:34 -0600
| Newsgroups | org.kernel.vger.linux-8086 |
|---|---|
| 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;
}