diff options
author | Colin Cross <ccross@android.com> | 2010-08-05 11:56:38 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2010-08-05 14:38:47 -0700 |
commit | 6bd2b5d80db5630cb73e3e5a4be3b38afa241c5a (patch) | |
tree | eb95b397af1cbfc69091324f65173f88862b81af /ext4_utils | |
parent | 7eb4165b83ca3724b64c8925fa530362b6072bc2 (diff) | |
download | extras-6bd2b5d80db5630cb73e3e5a4be3b38afa241c5a.tar.gz |
Fix calculation of dentry size
The PAD_TO function was incorrectly handling values that were already
aligned, which could lead to overruns of the dentry block. Fix the
function, rename it to ALIGN, move it to ext4_utils.h, and use it
everywhere the dentry size is calculated.
Change-Id: Ie9778d2c6f72d3db9a3162e52882377a71b8420a
Diffstat (limited to 'ext4_utils')
-rw-r--r-- | ext4_utils/contents.c | 22 | ||||
-rw-r--r-- | ext4_utils/ext4_utils.h | 1 |
2 files changed, 14 insertions, 9 deletions
diff --git a/ext4_utils/contents.c b/ext4_utils/contents.c index 9fcd3b30..0ecdfd43 100644 --- a/ext4_utils/contents.c +++ b/ext4_utils/contents.c @@ -30,10 +30,10 @@ static u32 dentry_size(u32 entries, struct dentry *dentries) { u32 len = 24; unsigned int i; + unsigned int dentry_len; for (i = 0; i < entries; i++) { - unsigned int dentry_len = 8 + 4 * - DIV_ROUND_UP(strlen(dentries[i].filename), 4); + dentry_len = 8 + ALIGN(strlen(dentries[i].filename), 4); if (len % info.block_size + dentry_len > info.block_size) len += info.block_size - (len % info.block_size); len += dentry_len; @@ -42,14 +42,12 @@ static u32 dentry_size(u32 entries, struct dentry *dentries) return len; } -#define PAD_TO(x, y) (x + (y - (x % y))) - static struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset, struct ext4_dir_entry_2 *prev, u32 inode, const char *name, u8 file_type) { u8 name_len = strlen(name); - u16 rec_len = 8 + PAD_TO(name_len, 4); + u16 rec_len = 8 + ALIGN(name_len, 4); struct ext4_dir_entry_2 *dentry; u32 start_block = *offset / info.block_size; @@ -84,14 +82,17 @@ u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries, u32 dirs) { struct ext4_inode *inode; - u32 blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size); - u64 len = (u64)blocks * info.block_size; + u32 blocks; + u32 len; u32 offset = 0; u32 inode_num; u8 *data; unsigned int i; struct ext4_dir_entry_2 *dentry; + blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size); + len = blocks * info.block_size; + if (dir_inode_num) { inode_num = allocate_inode(info); } else { @@ -137,8 +138,11 @@ u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries, } for (i = 0; i < entries; i++) { - dentry = add_dentry(data, &offset, dentry, 0, dentries[i].filename, - dentries[i].file_type); + dentry = add_dentry(data, &offset, dentry, 0, + dentries[i].filename, dentries[i].file_type); + if (offset > len || (offset == len && i != entries - 1)) + critical_error("internal error: dentry for %s ends at %d, past %d\n", + dentries[i].filename, offset, len); dentries[i].inode = &dentry->inode; if (!dentry) { error("failed to add directory"); diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h index 294c8c5e..0a2b542a 100644 --- a/ext4_utils/ext4_utils.h +++ b/ext4_utils/ext4_utils.h @@ -38,6 +38,7 @@ extern int force; #define min(a, b) ((a) < (b) ? (a) : (b)) #define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y)) +#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y))) #define __le64 u64 #define __le32 u32 |