diff options
| author | NeilBrown <neilb@suse.de> | 2006-09-16 15:15:37 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-16 15:54:30 -0400 |
| commit | ecaff756ff540f3821e2b00b8fa19aca07c7c3e5 (patch) | |
| tree | 80c40b24ad9228dcd7cf48c798250a9ccc74887a | |
| parent | 55ebcc38a5f6d40e4c41447e413ef842b803980f (diff) | |
[PATCH] knfsd: Have ext2 reject file handles with bad inode numbers early
This prevents bad inode numbers from triggering errors in ext2_get_inode.
[akpm@osdl.org: speedup, cleanup]
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | fs/ext2/super.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 681dea8f9532..ca5bfb6914d2 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -251,6 +251,44 @@ static struct super_operations ext2_sops = { | |||
| 251 | #endif | 251 | #endif |
| 252 | }; | 252 | }; |
| 253 | 253 | ||
| 254 | static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) | ||
| 255 | { | ||
| 256 | __u32 *objp = vobjp; | ||
| 257 | unsigned long ino = objp[0]; | ||
| 258 | __u32 generation = objp[1]; | ||
| 259 | struct inode *inode; | ||
| 260 | struct dentry *result; | ||
| 261 | |||
| 262 | if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) | ||
| 263 | return ERR_PTR(-ESTALE); | ||
| 264 | if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) | ||
| 265 | return ERR_PTR(-ESTALE); | ||
| 266 | |||
| 267 | /* iget isn't really right if the inode is currently unallocated!! | ||
| 268 | * ext2_read_inode currently does appropriate checks, but | ||
| 269 | * it might be "neater" to call ext2_get_inode first and check | ||
| 270 | * if the inode is valid..... | ||
| 271 | */ | ||
| 272 | inode = iget(sb, ino); | ||
| 273 | if (inode == NULL) | ||
| 274 | return ERR_PTR(-ENOMEM); | ||
| 275 | if (is_bad_inode(inode) || | ||
| 276 | (generation && inode->i_generation != generation)) { | ||
| 277 | /* we didn't find the right inode.. */ | ||
| 278 | iput(inode); | ||
| 279 | return ERR_PTR(-ESTALE); | ||
| 280 | } | ||
| 281 | /* now to find a dentry. | ||
| 282 | * If possible, get a well-connected one | ||
| 283 | */ | ||
| 284 | result = d_alloc_anon(inode); | ||
| 285 | if (!result) { | ||
| 286 | iput(inode); | ||
| 287 | return ERR_PTR(-ENOMEM); | ||
| 288 | } | ||
| 289 | return result; | ||
| 290 | } | ||
| 291 | |||
| 254 | /* Yes, most of these are left as NULL!! | 292 | /* Yes, most of these are left as NULL!! |
| 255 | * A NULL value implies the default, which works with ext2-like file | 293 | * A NULL value implies the default, which works with ext2-like file |
| 256 | * systems, but can be improved upon. | 294 | * systems, but can be improved upon. |
| @@ -258,6 +296,7 @@ static struct super_operations ext2_sops = { | |||
| 258 | */ | 296 | */ |
| 259 | static struct export_operations ext2_export_ops = { | 297 | static struct export_operations ext2_export_ops = { |
| 260 | .get_parent = ext2_get_parent, | 298 | .get_parent = ext2_get_parent, |
| 299 | .get_dentry = ext2_get_dentry, | ||
| 261 | }; | 300 | }; |
| 262 | 301 | ||
| 263 | static unsigned long get_sb_block(void **data) | 302 | static unsigned long get_sb_block(void **data) |
