aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2008-03-16 18:48:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-03-17 12:46:55 -0400
commit3d10a15d6919488204bdb264050d156ced20d9aa (patch)
treec5a230680cb2745c94137e354d66f7734266a009 /fs
parenta978b30af3bab0dd9af9350eeda25e76123fa28e (diff)
hfs_bnode_find() can fail, resulting in hfs_bnode_split() breakage
oops and fs corruption; the latter can happen even on valid fs in case of oom. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/hfs/brec.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 878bf25dbc6a..92fb358ce824 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -229,7 +229,7 @@ skip:
229static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) 229static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
230{ 230{
231 struct hfs_btree *tree; 231 struct hfs_btree *tree;
232 struct hfs_bnode *node, *new_node; 232 struct hfs_bnode *node, *new_node, *next_node;
233 struct hfs_bnode_desc node_desc; 233 struct hfs_bnode_desc node_desc;
234 int num_recs, new_rec_off, new_off, old_rec_off; 234 int num_recs, new_rec_off, new_off, old_rec_off;
235 int data_start, data_end, size; 235 int data_start, data_end, size;
@@ -248,6 +248,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
248 new_node->type = node->type; 248 new_node->type = node->type;
249 new_node->height = node->height; 249 new_node->height = node->height;
250 250
251 if (node->next)
252 next_node = hfs_bnode_find(tree, node->next);
253 else
254 next_node = NULL;
255
256 if (IS_ERR(next_node)) {
257 hfs_bnode_put(node);
258 hfs_bnode_put(new_node);
259 return next_node;
260 }
261
251 size = tree->node_size / 2 - node->num_recs * 2 - 14; 262 size = tree->node_size / 2 - node->num_recs * 2 - 14;
252 old_rec_off = tree->node_size - 4; 263 old_rec_off = tree->node_size - 4;
253 num_recs = 1; 264 num_recs = 1;
@@ -261,6 +272,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
261 /* panic? */ 272 /* panic? */
262 hfs_bnode_put(node); 273 hfs_bnode_put(node);
263 hfs_bnode_put(new_node); 274 hfs_bnode_put(new_node);
275 if (next_node)
276 hfs_bnode_put(next_node);
264 return ERR_PTR(-ENOSPC); 277 return ERR_PTR(-ENOSPC);
265 } 278 }
266 279
@@ -315,8 +328,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
315 hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); 328 hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
316 329
317 /* update next bnode header */ 330 /* update next bnode header */
318 if (new_node->next) { 331 if (next_node) {
319 struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
320 next_node->prev = new_node->this; 332 next_node->prev = new_node->this;
321 hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); 333 hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
322 node_desc.prev = cpu_to_be32(next_node->prev); 334 node_desc.prev = cpu_to_be32(next_node->prev);