diff options
author | Bob Copeland <me@bobcopeland.com> | 2008-09-06 17:51:53 -0400 |
---|---|---|
committer | Bob Copeland <me@bobcopeland.com> | 2010-07-10 14:37:06 -0400 |
commit | f068272cb2f134a194b93e94a8e0672bfce48cd8 (patch) | |
tree | c6a2a67951646eee3d040b732b384fa5c98fe78c /fs/omfs/dir.c | |
parent | 70d9e384aa7df681cfffd65947af72b22e86690e (diff) |
omfs: check bounds on block numbers before passing to sb_bread
In case of filesystem corruption, passing unchecked block numbers into
sb_bread can result in an infinite loop in __getblk(). Introduce a wrapper
function omfs_sbread() to check the block numbers and to also perform the
clus_to_blk() scaling.
Signed-off-by: Bob Copeland <me@bobcopeland.com>
Diffstat (limited to 'fs/omfs/dir.c')
-rw-r--r-- | fs/omfs/dir.c | 22 |
1 files changed, 8 insertions, 14 deletions
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index b42d62419034..393f3f659da7 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
@@ -25,11 +25,10 @@ static struct buffer_head *omfs_get_bucket(struct inode *dir, | |||
25 | const char *name, int namelen, int *ofs) | 25 | const char *name, int namelen, int *ofs) |
26 | { | 26 | { |
27 | int nbuckets = (dir->i_size - OMFS_DIR_START)/8; | 27 | int nbuckets = (dir->i_size - OMFS_DIR_START)/8; |
28 | int block = clus_to_blk(OMFS_SB(dir->i_sb), dir->i_ino); | ||
29 | int bucket = omfs_hash(name, namelen, nbuckets); | 28 | int bucket = omfs_hash(name, namelen, nbuckets); |
30 | 29 | ||
31 | *ofs = OMFS_DIR_START + bucket * 8; | 30 | *ofs = OMFS_DIR_START + bucket * 8; |
32 | return sb_bread(dir->i_sb, block); | 31 | return omfs_bread(dir->i_sb, dir->i_ino); |
33 | } | 32 | } |
34 | 33 | ||
35 | static struct buffer_head *omfs_scan_list(struct inode *dir, u64 block, | 34 | static struct buffer_head *omfs_scan_list(struct inode *dir, u64 block, |
@@ -42,8 +41,7 @@ static struct buffer_head *omfs_scan_list(struct inode *dir, u64 block, | |||
42 | *prev_block = ~0; | 41 | *prev_block = ~0; |
43 | 42 | ||
44 | while (block != ~0) { | 43 | while (block != ~0) { |
45 | bh = sb_bread(dir->i_sb, | 44 | bh = omfs_bread(dir->i_sb, block); |
46 | clus_to_blk(OMFS_SB(dir->i_sb), block)); | ||
47 | if (!bh) { | 45 | if (!bh) { |
48 | err = -EIO; | 46 | err = -EIO; |
49 | goto err; | 47 | goto err; |
@@ -86,11 +84,10 @@ static struct buffer_head *omfs_find_entry(struct inode *dir, | |||
86 | int omfs_make_empty(struct inode *inode, struct super_block *sb) | 84 | int omfs_make_empty(struct inode *inode, struct super_block *sb) |
87 | { | 85 | { |
88 | struct omfs_sb_info *sbi = OMFS_SB(sb); | 86 | struct omfs_sb_info *sbi = OMFS_SB(sb); |
89 | int block = clus_to_blk(sbi, inode->i_ino); | ||
90 | struct buffer_head *bh; | 87 | struct buffer_head *bh; |
91 | struct omfs_inode *oi; | 88 | struct omfs_inode *oi; |
92 | 89 | ||
93 | bh = sb_bread(sb, block); | 90 | bh = omfs_bread(sb, inode->i_ino); |
94 | if (!bh) | 91 | if (!bh) |
95 | return -ENOMEM; | 92 | return -ENOMEM; |
96 | 93 | ||
@@ -134,7 +131,7 @@ static int omfs_add_link(struct dentry *dentry, struct inode *inode) | |||
134 | brelse(bh); | 131 | brelse(bh); |
135 | 132 | ||
136 | /* now set the sibling and parent pointers on the new inode */ | 133 | /* now set the sibling and parent pointers on the new inode */ |
137 | bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb), inode->i_ino)); | 134 | bh = omfs_bread(dir->i_sb, inode->i_ino); |
138 | if (!bh) | 135 | if (!bh) |
139 | goto out; | 136 | goto out; |
140 | 137 | ||
@@ -190,8 +187,7 @@ static int omfs_delete_entry(struct dentry *dentry) | |||
190 | if (prev != ~0) { | 187 | if (prev != ~0) { |
191 | /* found in middle of list, get list ptr */ | 188 | /* found in middle of list, get list ptr */ |
192 | brelse(bh); | 189 | brelse(bh); |
193 | bh = sb_bread(dir->i_sb, | 190 | bh = omfs_bread(dir->i_sb, prev); |
194 | clus_to_blk(OMFS_SB(dir->i_sb), prev)); | ||
195 | if (!bh) | 191 | if (!bh) |
196 | goto out; | 192 | goto out; |
197 | 193 | ||
@@ -224,8 +220,7 @@ static int omfs_dir_is_empty(struct inode *inode) | |||
224 | u64 *ptr; | 220 | u64 *ptr; |
225 | int i; | 221 | int i; |
226 | 222 | ||
227 | bh = sb_bread(inode->i_sb, clus_to_blk(OMFS_SB(inode->i_sb), | 223 | bh = omfs_bread(inode->i_sb, inode->i_ino); |
228 | inode->i_ino)); | ||
229 | 224 | ||
230 | if (!bh) | 225 | if (!bh) |
231 | return 0; | 226 | return 0; |
@@ -353,8 +348,7 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir, | |||
353 | 348 | ||
354 | /* follow chain in this bucket */ | 349 | /* follow chain in this bucket */ |
355 | while (fsblock != ~0) { | 350 | while (fsblock != ~0) { |
356 | bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb), | 351 | bh = omfs_bread(dir->i_sb, fsblock); |
357 | fsblock)); | ||
358 | if (!bh) | 352 | if (!bh) |
359 | goto out; | 353 | goto out; |
360 | 354 | ||
@@ -466,7 +460,7 @@ static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
466 | hchain = (filp->f_pos >> 20) - 1; | 460 | hchain = (filp->f_pos >> 20) - 1; |
467 | hindex = filp->f_pos & 0xfffff; | 461 | hindex = filp->f_pos & 0xfffff; |
468 | 462 | ||
469 | bh = sb_bread(dir->i_sb, clus_to_blk(OMFS_SB(dir->i_sb), dir->i_ino)); | 463 | bh = omfs_bread(dir->i_sb, dir->i_ino); |
470 | if (!bh) | 464 | if (!bh) |
471 | goto out; | 465 | goto out; |
472 | 466 | ||