diff options
Diffstat (limited to 'fs/btrfs/dir-item.c')
-rw-r--r-- | fs/btrfs/dir-item.c | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index f0cad5ae5be7..c62f02f6ae69 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -151,7 +151,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
151 | ret = PTR_ERR(dir_item); | 151 | ret = PTR_ERR(dir_item); |
152 | if (ret == -EEXIST) | 152 | if (ret == -EEXIST) |
153 | goto second_insert; | 153 | goto second_insert; |
154 | goto out; | 154 | goto out_free; |
155 | } | 155 | } |
156 | 156 | ||
157 | leaf = path->nodes[0]; | 157 | leaf = path->nodes[0]; |
@@ -170,7 +170,7 @@ second_insert: | |||
170 | /* FIXME, use some real flag for selecting the extra index */ | 170 | /* FIXME, use some real flag for selecting the extra index */ |
171 | if (root == root->fs_info->tree_root) { | 171 | if (root == root->fs_info->tree_root) { |
172 | ret = 0; | 172 | ret = 0; |
173 | goto out; | 173 | goto out_free; |
174 | } | 174 | } |
175 | btrfs_release_path(root, path); | 175 | btrfs_release_path(root, path); |
176 | 176 | ||
@@ -180,7 +180,7 @@ second_insert: | |||
180 | name, name_len); | 180 | name, name_len); |
181 | if (IS_ERR(dir_item)) { | 181 | if (IS_ERR(dir_item)) { |
182 | ret2 = PTR_ERR(dir_item); | 182 | ret2 = PTR_ERR(dir_item); |
183 | goto out; | 183 | goto out_free; |
184 | } | 184 | } |
185 | leaf = path->nodes[0]; | 185 | leaf = path->nodes[0]; |
186 | btrfs_cpu_key_to_disk(&disk_key, location); | 186 | btrfs_cpu_key_to_disk(&disk_key, location); |
@@ -192,7 +192,9 @@ second_insert: | |||
192 | name_ptr = (unsigned long)(dir_item + 1); | 192 | name_ptr = (unsigned long)(dir_item + 1); |
193 | write_extent_buffer(leaf, name, name_ptr, name_len); | 193 | write_extent_buffer(leaf, name, name_ptr, name_len); |
194 | btrfs_mark_buffer_dirty(leaf); | 194 | btrfs_mark_buffer_dirty(leaf); |
195 | out: | 195 | |
196 | out_free: | ||
197 | |||
196 | btrfs_free_path(path); | 198 | btrfs_free_path(path); |
197 | if (ret) | 199 | if (ret) |
198 | return ret; | 200 | return ret; |
@@ -377,6 +379,9 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | |||
377 | 379 | ||
378 | leaf = path->nodes[0]; | 380 | leaf = path->nodes[0]; |
379 | dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); | 381 | dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); |
382 | if (verify_dir_item(root, leaf, dir_item)) | ||
383 | return NULL; | ||
384 | |||
380 | total_len = btrfs_item_size_nr(leaf, path->slots[0]); | 385 | total_len = btrfs_item_size_nr(leaf, path->slots[0]); |
381 | while (cur < total_len) { | 386 | while (cur < total_len) { |
382 | this_len = sizeof(*dir_item) + | 387 | this_len = sizeof(*dir_item) + |
@@ -429,3 +434,35 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, | |||
429 | } | 434 | } |
430 | return ret; | 435 | return ret; |
431 | } | 436 | } |
437 | |||
438 | int verify_dir_item(struct btrfs_root *root, | ||
439 | struct extent_buffer *leaf, | ||
440 | struct btrfs_dir_item *dir_item) | ||
441 | { | ||
442 | u16 namelen = BTRFS_NAME_LEN; | ||
443 | u8 type = btrfs_dir_type(leaf, dir_item); | ||
444 | |||
445 | if (type >= BTRFS_FT_MAX) { | ||
446 | printk(KERN_CRIT "btrfs: invalid dir item type: %d\n", | ||
447 | (int)type); | ||
448 | return 1; | ||
449 | } | ||
450 | |||
451 | if (type == BTRFS_FT_XATTR) | ||
452 | namelen = XATTR_NAME_MAX; | ||
453 | |||
454 | if (btrfs_dir_name_len(leaf, dir_item) > namelen) { | ||
455 | printk(KERN_CRIT "btrfS: invalid dir item name len: %u\n", | ||
456 | (unsigned)btrfs_dir_data_len(leaf, dir_item)); | ||
457 | return 1; | ||
458 | } | ||
459 | |||
460 | /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */ | ||
461 | if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) { | ||
462 | printk(KERN_CRIT "btrfs: invalid dir item data len: %u\n", | ||
463 | (unsigned)btrfs_dir_data_len(leaf, dir_item)); | ||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | return 0; | ||
468 | } | ||