When reading out name from inode_ref, dir_item, it's possible that
corrupted name_len lead to read beyond boundary.
Since there are already patches for btrfs-progs, this is for btrfs.
Introduce function btrfs_check_namelen, it should be called before reading
name from extent_buffer.
The function compares arg @namelen with boundary then returns 'proper'
namelen.
Signed-off-by: Su Yue <suy.fnst@xxxxxxxxxxxxxx>
---
fs/btrfs/ctree.h | 2 ++
fs/btrfs/dir-item.c | 22 ++++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 643c70d2b2e6..f49e04e7612b 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3074,6 +3074,8 @@ int btrfs_find_name_in_ext_backref(struct btrfs_path *path,
int name_len,
struct btrfs_inode_extref **extref_ret);
+u16 btrfs_check_namelen(struct extent_buffer *leaf, int slot,
+ unsigned long start, u32 namelen);
/* file-item.c */
struct btrfs_dio_private;
int btrfs_del_csums(struct btrfs_trans_handle *trans,
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index c24d615e3d7f..7af5ad8e9a3c 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -484,3 +484,25 @@ int verify_dir_item(struct btrfs_fs_info *fs_info,
return 0;
}
+
+/*
+ * Returns >0: the value @namelen after cut according item boundary
+ * Returns 0: on error
+ */
+u16 btrfs_check_namelen(struct extent_buffer *leaf, int slot,
+ unsigned long start, u32 namelen)
+{
+ u32 end;
+ u64 ret = namelen;
+
+ end = btrfs_leaf_data(leaf) + btrfs_item_end_nr(leaf, slot);
+
+ if (start > end)
+ return 0;
+ if (start + namelen > end) {
+ ret = end - start;
+ if (ret > U16_MAX)
+ ret = 0;
+ }
+ return ret;
+}
--
2.13.0
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html