[PATCH] minix_clear_inode fix

From: Andries.Brouwer
Date: Sat Nov 06 2004 - 18:36:53 EST


The patch below fixes two flaws in minix_clear_inode.

The first is that it tests bh which is never initialized.
(&bh is a parameter of minix_V1_raw_inode, but that routine
can fail and return before it has set bh)

The second is that generic_delete_inode() goes BUG()
in case inode->i_state != I_CLEAR. Clearly, it is expected
that inode->i_sb->s_op->delete_inode does a clear_inode()
at some point. But minix_delete_inode() calls minix_free_inode()
and that routine can print an error and return early, before
calling clear_inode().

Andries


diff -uprN -X /linux/dontdiff a/fs/minix/bitmap.c b/fs/minix/bitmap.c
--- a/fs/minix/bitmap.c 2003-12-18 03:59:16.000000000 +0100
+++ b/fs/minix/bitmap.c 2004-11-06 17:40:47.000000000 +0100
@@ -160,7 +160,8 @@ minix_V2_raw_inode(struct super_block *s

static void minix_clear_inode(struct inode *inode)
{
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
+
if (INODE_VERSION(inode) == MINIX_V1) {
struct minix_inode *raw_inode;
raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
@@ -188,24 +189,26 @@ void minix_free_inode(struct inode * ino
struct buffer_head * bh;
unsigned long ino;

- if (inode->i_ino < 1 || inode->i_ino > sbi->s_ninodes) {
- printk("free_inode: inode 0 or nonexistent inode\n");
- return;
- }
ino = inode->i_ino;
+ if (ino < 1 || ino > sbi->s_ninodes) {
+ printk("minix_free_inode: inode 0 or nonexistent inode\n");
+ goto out;
+ }
if ((ino >> 13) >= sbi->s_imap_blocks) {
- printk("free_inode: nonexistent imap in superblock\n");
- return;
+ printk("minix_free_inode: nonexistent imap in superblock\n");
+ goto out;
}

+ minix_clear_inode(inode); /* clear on-disk copy */
+
bh = sbi->s_imap[ino >> 13];
- minix_clear_inode(inode);
- clear_inode(inode);
lock_kernel();
if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
- printk("free_inode: bit %lu already cleared.\n",ino);
+ printk("minix_free_inode: bit %lu already cleared.\n", ino);
unlock_kernel();
mark_buffer_dirty(bh);
+ out:
+ clear_inode(inode); /* clear in-memory copy */
}

struct inode * minix_new_inode(const struct inode * dir, int * error)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/