Re: Bad ext3/nfs DoS bug

Neil Brown
2006-07-25T02:37:37Z

On Monday July 24, akpm@osdl.org wrote:
>
> <then looks at ext2>

Yeh.... this patch is somewhat different to the others, yet similar...

I didn't bother changing ext2_get_inode at all, but just defined a
get_dentry export_op so that bad inode numbers never get to
ext2_get_inode via nfsd.

So in this case I had to test for the upper bound as well as the lower
bound.

Putting it another way,
ext3_get_dentry reject certain inums that are known to be a problem.
ext2_get_dentry allows only those inums that could possibly be ok.

So if you (anyone) prefer one approach over the other, making the
change so they both fs take the same approach would be trivial.

Compile tested only

NeilBrown

------------------------------------
Have ext2 reject file handles with bad inode numbers early.

This prevents bad inode numbers from triggering errors in
ext2_get_inode.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
./fs/ext2/super.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff .prev/fs/ext2/super.c ./fs/ext2/super.c
--- .prev/fs/ext2/super.c 2006-07-25 12:29:10.000000000 +1000
+++ ./fs/ext2/super.c 2006-07-25 12:31:04.000000000 +1000
@@ -251,6 +251,20 @@ static struct super_operations ext2_sops
#endif
};

+static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
+{
+ __u32 *objp = vobjp;
+ unsigned long ino = objp[0];
+ __u32 generation = objp[1];
+
+ if (ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb))
+ return ERR_PTR(-ESTALE);
+ if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
+ return ERR_PTR(-ESTALE);
+
+ return export_iget(sb, ino, generation);
+}
+
/* Yes, most of these are left as NULL!!
* A NULL value implies the default, which works with ext2-like file
* systems, but can be improved upon.
@@ -258,6 +272,7 @@ static struct super_operations ext2_sops
*/
static struct export_operations ext2_export_ops = {
.get_parent = ext2_get_parent,
+ .get_dentry = ext2_get_dentry,
};

static unsigned long get_sb_block(void **data)