diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 6add6ebfef89..2f00f03e29de 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -55,7 +55,7 @@ u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off) return data; } -void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) +int hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) { struct hfs_btree *tree; int key_len; @@ -67,7 +67,13 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) else key_len = tree->max_key_len + 1; + if (key_len > tree->max_key_len + 1) { + pr_err("key_len %d too large\n", key_len); + return -EINVAL; + } + hfs_bnode_read(node, key, off, key_len); + return 0; } void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len) diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c index 896396554bcc..b3eed02f8679 100644 --- a/fs/hfs/brec.c +++ b/fs/hfs/brec.c @@ -70,6 +70,7 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) int data_off, end_off; int idx_rec_off, data_rec_off, end_rec_off; __be32 cnid; + int res; tree = fd->tree; if (!fd->bnode) { @@ -138,7 +139,10 @@ skip: * at the start of the node and it is not the new node */ if (!rec && new_node != node) { - hfs_bnode_read_key(node, fd->search_key, data_off + size); + res = hfs_bnode_read_key(node, fd->search_key, data_off + size); + if (res < 0) + return res; + hfs_brec_update_parent(fd); } @@ -156,7 +160,10 @@ skip: entry_len = sizeof(cnid); /* get index key */ - hfs_bnode_read_key(new_node, fd->search_key, 14); + res = hfs_bnode_read_key(new_node, fd->search_key, 14); + if (res < 0) + return res; + __hfs_brec_find(fd->bnode, fd); hfs_bnode_put(new_node); @@ -356,6 +363,7 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) int newkeylen, diff; int rec, rec_off, end_rec_off; int start_off, end_off; + int res; tree = fd->tree; node = fd->bnode; @@ -431,7 +439,10 @@ skip: } fd->bnode = hfs_bnode_find(tree, new_node->parent); /* create index key and entry */ - hfs_bnode_read_key(new_node, fd->search_key, 14); + res = hfs_bnode_read_key(new_node, fd->search_key, 14); + if (res < 0) + return res; + cnid = cpu_to_be32(new_node->this); __hfs_brec_find(fd->bnode, fd); @@ -443,7 +454,9 @@ skip: if (new_node == node) goto out; /* restore search_key */ - hfs_bnode_read_key(node, fd->search_key, 14); + res = hfs_bnode_read_key(node, fd->search_key, 14); + if (res < 0) + return res; } new_node = NULL; } diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h index 0e6baee93245..dc2cb559efaa 100644 --- a/fs/hfs/btree.h +++ b/fs/hfs/btree.h @@ -97,7 +97,7 @@ extern void hfs_bmap_free(struct hfs_bnode *node); extern void hfs_bnode_read(struct hfs_bnode *, void *, int, int); extern u16 hfs_bnode_read_u16(struct hfs_bnode *, int); extern u8 hfs_bnode_read_u8(struct hfs_bnode *, int); -extern void hfs_bnode_read_key(struct hfs_bnode *, void *, int); +extern int hfs_bnode_read_key(struct hfs_bnode *, void *, int); extern void hfs_bnode_write(struct hfs_bnode *, void *, int, int); extern void hfs_bnode_write_u16(struct hfs_bnode *, int, u16); extern void hfs_bnode_write_u8(struct hfs_bnode *, int, u8); diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 87974d5e6791..9d9efa7bc97b 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -54,7 +54,7 @@ u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off) return data; } -void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) +int hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) { struct hfs_btree *tree; int key_len; @@ -67,7 +67,13 @@ void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off) else key_len = tree->max_key_len + 2; + if (key_len > tree->max_key_len + 2) { + pr_err("key_len %d too large\n", key_len); + return -EINVAL; + } + hfs_bnode_read(node, key, off, key_len); + return 0; } void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len) diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c index 1918544a7871..4db1fd0cf5e9 100644 --- a/fs/hfsplus/brec.c +++ b/fs/hfsplus/brec.c @@ -68,6 +68,7 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len) int data_off, end_off; int idx_rec_off, data_rec_off, end_rec_off; __be32 cnid; + int res; tree = fd->tree; if (!fd->bnode) { @@ -138,7 +139,10 @@ skip: * at the start of the node and it is not the new node */ if (!rec && new_node != node) { - hfs_bnode_read_key(node, fd->search_key, data_off + size); + res = hfs_bnode_read_key(node, fd->search_key, data_off + size); + if (res < 0) + return res; + hfs_brec_update_parent(fd); } @@ -156,7 +160,10 @@ skip: entry_len = sizeof(cnid); /* get index key */ - hfs_bnode_read_key(new_node, fd->search_key, 14); + res = hfs_bnode_read_key(new_node, fd->search_key, 14); + if (res < 0) + return res; + __hfs_brec_find(fd->bnode, fd, hfs_find_rec_by_key); hfs_bnode_put(new_node); @@ -360,6 +367,7 @@ static int hfs_brec_update_parent(struct hfs_find_data *fd) int newkeylen, diff; int rec, rec_off, end_rec_off; int start_off, end_off; + int res; tree = fd->tree; node = fd->bnode; @@ -435,7 +443,10 @@ skip: } fd->bnode = hfs_bnode_find(tree, new_node->parent); /* create index key and entry */ - hfs_bnode_read_key(new_node, fd->search_key, 14); + res = hfs_bnode_read_key(new_node, fd->search_key, 14); + if (res < 0) + return res; + cnid = cpu_to_be32(new_node->this); __hfs_brec_find(fd->bnode, fd, hfs_find_rec_by_key); @@ -447,7 +458,9 @@ skip: if (new_node == node) goto out; /* restore search_key */ - hfs_bnode_read_key(node, fd->search_key, 14); + res = hfs_bnode_read_key(node, fd->search_key, 14); + if (res < 0) + return res; } new_node = NULL; } diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 9e78f181c24f..9f4b5221ead2 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -396,7 +396,7 @@ void hfs_bmap_free(struct hfs_bnode *node); void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len); u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off); u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off); -void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off); +int hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off); void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len); void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data); void hfs_bnode_clear(struct hfs_bnode *node, int off, int len);