Page MenuHomeFreeBSD

D33375.diff
No OneTemporary

D33375.diff

diff --git a/sys/fs/ext2fs/ext2_extents.c b/sys/fs/ext2fs/ext2_extents.c
--- a/sys/fs/ext2fs/ext2_extents.c
+++ b/sys/fs/ext2fs/ext2_extents.c
@@ -61,8 +61,10 @@
#ifdef EXT2FS_PRINT_EXTENTS
static const bool print_extents_walk = true;
-static int ext4_ext_check_header(struct inode *, struct ext4_extent_header *);
-static int ext4_ext_walk_header(struct inode *, struct ext4_extent_header *);
+static int ext4_ext_check_header(struct inode *, struct ext4_extent_header *,
+ int);
+static int ext4_ext_walk_header(struct inode *, struct ext4_extent_header *,
+ int);
static inline e4fs_daddr_t ext4_ext_index_pblock(struct ext4_extent_index *);
static inline e4fs_daddr_t ext4_ext_extent_pblock(struct ext4_extent *);
@@ -80,7 +82,8 @@
}
static int
-ext4_ext_walk_index(struct inode *ip, struct ext4_extent_index *ex, bool do_walk)
+ext4_ext_walk_index(struct inode *ip, struct ext4_extent_index *ex, int depth,
+ bool do_walk)
{
struct m_ext2fs *fs;
struct buf *bp;
@@ -91,7 +94,8 @@
if (print_extents_walk)
printf(" index %p => (blk %u pblk %ju)\n", ex,
- le32toh(ex->ei_blk), (uint64_t)le16toh(ex->ei_leaf_hi) << 32 |
+ le32toh(ex->ei_blk),
+ (uint64_t)le16toh(ex->ei_leaf_hi) << 32 |
le32toh(ex->ei_leaf_lo));
if(!do_walk)
@@ -108,7 +112,8 @@
return (error);
}
- error = ext4_ext_walk_header(ip, (struct ext4_extent_header *)bp->b_data);
+ error = ext4_ext_walk_header(ip,
+ (struct ext4_extent_header *)bp->b_data, depth);
brelse(bp);
@@ -135,42 +140,62 @@
}
static int
-ext4_ext_walk_header(struct inode *ip, struct ext4_extent_header *eh)
+ext4_ext_walk_header(struct inode *ip, struct ext4_extent_header *eh, int depth)
{
int i, error = 0;
- error = ext4_ext_check_header(ip, eh);
+ error = ext4_ext_check_header(ip, eh, depth);
if (error)
return (error);
if (print_extents_walk)
printf("header %p => (entries %d max %d depth %d gen %d)\n",
eh, le16toh(eh->eh_ecount),
- le16toh(eh->eh_max), le16toh(eh->eh_depth), le32toh(eh->eh_gen));
+ le16toh(eh->eh_max), le16toh(eh->eh_depth),
+ le32toh(eh->eh_gen));
for (i = 0; i < le16toh(eh->eh_ecount) && error == 0; i++)
if (eh->eh_depth != 0)
error = ext4_ext_walk_index(ip,
- (struct ext4_extent_index *)(eh + 1 + i), true);
+ (struct ext4_extent_index *)(eh + 1 + i), depth - 1,
+ true);
else
- error = ext4_ext_walk_extent(ip, (struct ext4_extent *)(eh + 1 + i));
+ error = ext4_ext_walk_extent(ip,
+ (struct ext4_extent *)(eh + 1 + i));
return (error);
}
+int
+ext4_ext_walk(struct inode *ip)
+{
+ struct ext4_extent_header *ehp;
+
+ ehp = (struct ext4_extent_header *)ip->i_db;
+
+ if (print_extents_walk)
+ printf("Extent status:ip=%ju\n", ip->i_number);
+
+ if (!(ip->i_flag & IN_E4EXTENTS))
+ return (0);
+
+ return (ext4_ext_walk_header(ip, ehp, 0));
+}
+
static int
ext4_ext_print_path(struct inode *ip, struct ext4_extent_path *path)
{
- int k, l, error = 0;
+ int k, depth, error = 0;
- l = path->ep_depth;
+ depth = path->ep_depth;
if (print_extents_walk)
printf("ip=%ju, Path:\n", ip->i_number);
- for (k = 0; k <= l && error == 0; k++, path++) {
+ for (k = 0; k <= depth && error == 0; k++, path++) {
if (path->ep_index) {
- error = ext4_ext_walk_index(ip, path->ep_index, false);
+ error = ext4_ext_walk_index(ip, path->ep_index,
+ depth - 1, false);
} else if (path->ep_ext) {
error = ext4_ext_walk_extent(ip, path->ep_ext);
}
@@ -178,22 +203,6 @@
return (error);
}
-
-int
-ext4_ext_walk(struct inode *ip)
-{
- struct ext4_extent_header *ehp;
-
- ehp = (struct ext4_extent_header *)ip->i_db;
-
- if (print_extents_walk)
- printf("Extent status:ip=%ju\n", ip->i_number);
-
- if (!(ip->i_flag & IN_E4EXTENTS))
- return (0);
-
- return (ext4_ext_walk_header(ip, ehp));
-}
#endif
static inline struct ext4_extent_header *
@@ -277,8 +286,168 @@
return (ret);
}
+static inline int
+ext4_ext_space_root(struct inode *ip)
+{
+ int size;
+
+ size = sizeof(ip->i_data);
+ size -= sizeof(struct ext4_extent_header);
+ size /= sizeof(struct ext4_extent);
+
+ return (size);
+}
+
+static inline int
+ext4_ext_space_block(struct inode *ip)
+{
+ struct m_ext2fs *fs;
+ int size;
+
+ fs = ip->i_e2fs;
+
+ size = (fs->e2fs_bsize - sizeof(struct ext4_extent_header)) /
+ sizeof(struct ext4_extent);
+
+ return (size);
+}
+
+static inline int
+ext4_ext_space_root_idx(struct inode *ip)
+{
+ int size;
+
+ size = sizeof(ip->i_data);
+ size -= sizeof(struct ext4_extent_header);
+ size /= sizeof(struct ext4_extent_index);
+
+ return (size);
+}
+
+static inline int
+ext4_ext_space_block_idx(struct inode *ip)
+{
+ struct m_ext2fs *fs;
+ int size;
+
+ fs = ip->i_e2fs;
+
+ size = (fs->e2fs_bsize - sizeof(struct ext4_extent_header)) /
+ sizeof(struct ext4_extent_index);
+
+ return (size);
+}
+
static int
-ext4_ext_check_header(struct inode *ip, struct ext4_extent_header *eh)
+ext4_ext_max_entries(struct inode *ip, int depth)
+{
+
+ if (depth == ext4_ext_inode_depth(ip)) {
+ if (depth == 0)
+ return (ext4_ext_space_root(ip));
+ else
+ return (ext4_ext_space_root_idx(ip));
+ } else {
+ if (depth == 0)
+ return (ext4_ext_space_block(ip));
+ else
+ return (ext4_ext_space_block_idx(ip));
+ }
+}
+
+static inline uint16_t
+ext4_ext_get_actual_len(struct ext4_extent *ext)
+{
+
+ return (le16toh(ext->e_len) <= EXT_INIT_MAX_LEN ?
+ le16toh(ext->e_len) : (le16toh(ext->e_len) - EXT_INIT_MAX_LEN));
+}
+
+
+static int
+ext4_inode_block_validate(struct inode *ip, e4fs_daddr_t start_blk,
+ unsigned int count)
+{
+ struct m_ext2fs *fs;
+
+ fs = ip->i_e2fs;
+
+ if ((start_blk <= le32toh(fs->e2fs->e2fs_first_dblock)) ||
+ (start_blk + count < start_blk) ||
+ (start_blk + count > fs->e2fs_bcount))
+ return (EIO);
+
+ return (0);
+}
+
+static int
+ext4_validate_extent(struct inode *ip, struct ext4_extent *ext)
+{
+ e4fs_daddr_t blk = ext4_ext_extent_pblock(ext);
+ uint32_t lblk = le32toh(ext->e_blk);
+ int len = ext4_ext_get_actual_len(ext);
+
+ if (lblk + len <= lblk)
+ return (EIO);
+
+ return (ext4_inode_block_validate(ip, blk, len));
+}
+
+static int
+ext4_validate_extent_idx(struct inode *ip, struct ext4_extent_index *ext_idx)
+{
+ e4fs_daddr_t blk = ext4_ext_index_pblock(ext_idx);
+
+ return (ext4_inode_block_validate(ip, blk, 1));
+}
+
+static int
+ext4_validate_extent_entries(struct inode *ip, struct ext4_extent_header *eh,
+ int depth)
+{
+ unsigned int count;
+
+ count = le16toh(eh->eh_ecount);
+ if (count == 0)
+ return (0);
+
+ if (depth == 0) {
+ struct ext4_extent *ext = EXT_FIRST_EXTENT(eh);
+ uint32_t lblk = 0;
+ uint32_t prev = 0;
+ int len = 0;
+ while (count) {
+ /* leaf entries */
+ if (ext4_validate_extent(ip, ext))
+ return (EIO);
+
+ /* Check for overlapping extents */
+ lblk = le32toh(ext->e_blk);
+ len = ext4_ext_get_actual_len(ext);
+ if ((lblk <= prev) && prev)
+ return (EIO);
+
+ ext++;
+ count--;
+ prev = lblk + len - 1;
+ }
+ } else {
+ struct ext4_extent_index *ext_idx = EXT_FIRST_INDEX(eh);
+ while (count) {
+ if (ext4_validate_extent_idx(ip, ext_idx))
+ return (EIO);
+
+ ext_idx++;
+ count--;
+ }
+ }
+
+ return (0);
+}
+
+static int
+ext4_ext_check_header(struct inode *ip, struct ext4_extent_header *eh,
+ int depth)
{
char *error_msg;
@@ -286,18 +455,32 @@
error_msg = "header: invalid magic";
goto corrupted;
}
+ if (le16toh(eh->eh_depth) != depth ||
+ le16toh(eh->eh_depth) > EXT4_EXT_DEPTH_MAX)
+ {
+ error_msg = "header: invalid eh_depth";
+ goto corrupted;
+ }
if (eh->eh_max == 0) {
error_msg = "header: invalid eh_max";
goto corrupted;
}
+ if (le16toh(eh->eh_max) > ext4_ext_max_entries(ip, depth)) {
+ error_msg = "header: too large eh_max";
+ goto corrupted;
+ }
if (le16toh(eh->eh_ecount) > le16toh(eh->eh_max)) {
error_msg = "header: invalid eh_entries";
goto corrupted;
}
- if (eh->eh_depth > 5) {
+ if (le16toh(eh->eh_depth) > EXT4_EXT_DEPTH_MAX) {
error_msg = "header: invalid eh_depth";
goto corrupted;
}
+ if (ext4_validate_extent_entries(ip, eh, depth)) {
+ error_msg = "header: invalid extent entries";
+ goto corrupted;
+ }
return (0);
@@ -426,7 +609,7 @@
ppos = 0;
alloc = 0;
- error = ext4_ext_check_header(ip, eh);
+ error = ext4_ext_check_header(ip, eh, depth);
if (error)
return (error);
@@ -472,7 +655,7 @@
bqrelse(bp);
eh = ext4_ext_block_header(path[ppos].ep_data);
- if (ext4_ext_check_header(ip, eh) ||
+ if (ext4_ext_check_header(ip, eh, i - 1) ||
ext2_extent_blk_csum_verify(ip, path[ppos].ep_data)) {
error = EIO;
goto error;
@@ -483,7 +666,7 @@
i--;
}
- error = ext4_ext_check_header(ip, eh);
+ error = ext4_ext_check_header(ip, eh, 0);
if (error)
goto error;
@@ -505,32 +688,6 @@
return (error);
}
-static inline int
-ext4_ext_space_root(struct inode *ip)
-{
- int size;
-
- size = sizeof(ip->i_data);
- size -= sizeof(struct ext4_extent_header);
- size /= sizeof(struct ext4_extent);
-
- return (size);
-}
-
-static inline int
-ext4_ext_space_block(struct inode *ip)
-{
- struct m_ext2fs *fs;
- int size;
-
- fs = ip->i_e2fs;
-
- size = (fs->e2fs_bsize - sizeof(struct ext4_extent_header)) /
- sizeof(struct ext4_extent);
-
- return (size);
-}
-
static inline int
ext4_ext_space_block_index(struct inode *ip)
{
@@ -1339,14 +1496,6 @@
return (error);
}
-static inline uint16_t
-ext4_ext_get_actual_len(struct ext4_extent *ext)
-{
-
- return (le16toh(ext->e_len) <= EXT_INIT_MAX_LEN ?
- le16toh(ext->e_len) : (le16toh(ext->e_len) - EXT_INIT_MAX_LEN));
-}
-
static inline struct ext4_extent_header *
ext4_ext_header(struct inode *ip)
{
@@ -1503,7 +1652,7 @@
goto err;
}
- error = ext4_ext_check_header(ip, eh);
+ error = ext4_ext_check_header(ip, eh, depth);
if (error)
goto err;
@@ -1544,7 +1693,7 @@
ehp = (struct ext4_extent_header *)ip->i_db;
depth = ext4_ext_inode_depth(ip);
- error = ext4_ext_check_header(ip, ehp);
+ error = ext4_ext_check_header(ip, ehp, depth);
if(error)
return (error);
diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c
--- a/sys/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -65,11 +65,11 @@
in->i_uid, in->i_gid, (uintmax_t)in->i_size);
printf("Links: %3d Blockcount: %ju\n",
in->i_nlink, (uintmax_t)in->i_blocks);
- printf("ctime: 0x%x ", in->i_ctime);
- printf("atime: 0x%x ", in->i_atime);
- printf("mtime: 0x%x ", in->i_mtime);
+ printf("ctime: 0x%llx ", (unsigned long long)in->i_ctime);
+ printf("atime: 0x%llx ", (unsigned long long)in->i_atime);
+ printf("mtime: 0x%llx ", (unsigned long long)in->i_mtime);
if (E2DI_HAS_XTIME(in))
- printf("crtime %#x\n", in->i_birthtime);
+ printf("crtime %llx\n", (unsigned long long)in->i_birthtime);
else
printf("\n");
if (in->i_flag & IN_E4EXTENTS) {

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 25, 10:06 PM (11 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15598937
Default Alt Text
D33375.diff (10 KB)

Event Timeline