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 /fs | |
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>
Diffstat (limited to 'fs')
-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) |