aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/dir.c16
-rw-r--r--fs/ext4/ext4.h7
-rw-r--r--fs/ext4/namei.c13
3 files changed, 21 insertions, 15 deletions
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 8e07d2a5a13..7c9d08b0f2f 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -72,7 +72,7 @@ static int is_dx_dir(struct inode *inode)
72int __ext4_check_dir_entry(const char *function, unsigned int line, 72int __ext4_check_dir_entry(const char *function, unsigned int line,
73 struct inode *dir, struct file *filp, 73 struct inode *dir, struct file *filp,
74 struct ext4_dir_entry_2 *de, 74 struct ext4_dir_entry_2 *de,
75 struct buffer_head *bh, 75 struct buffer_head *bh, char *buf, int size,
76 unsigned int offset) 76 unsigned int offset)
77{ 77{
78 const char *error_msg = NULL; 78 const char *error_msg = NULL;
@@ -85,9 +85,8 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
85 error_msg = "rec_len % 4 != 0"; 85 error_msg = "rec_len % 4 != 0";
86 else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) 86 else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
87 error_msg = "rec_len is too small for name_len"; 87 error_msg = "rec_len is too small for name_len";
88 else if (unlikely(((char *) de - bh->b_data) + rlen > 88 else if (unlikely(((char *) de - buf) + rlen > size))
89 dir->i_sb->s_blocksize)) 89 error_msg = "directory entry across range";
90 error_msg = "directory entry across blocks";
91 else if (unlikely(le32_to_cpu(de->inode) > 90 else if (unlikely(le32_to_cpu(de->inode) >
92 le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) 91 le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
93 error_msg = "inode out of bounds"; 92 error_msg = "inode out of bounds";
@@ -98,14 +97,14 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
98 ext4_error_file(filp, function, line, bh->b_blocknr, 97 ext4_error_file(filp, function, line, bh->b_blocknr,
99 "bad entry in directory: %s - offset=%u(%u), " 98 "bad entry in directory: %s - offset=%u(%u), "
100 "inode=%u, rec_len=%d, name_len=%d", 99 "inode=%u, rec_len=%d, name_len=%d",
101 error_msg, (unsigned) (offset % bh->b_size), 100 error_msg, (unsigned) (offset % size),
102 offset, le32_to_cpu(de->inode), 101 offset, le32_to_cpu(de->inode),
103 rlen, de->name_len); 102 rlen, de->name_len);
104 else 103 else
105 ext4_error_inode(dir, function, line, bh->b_blocknr, 104 ext4_error_inode(dir, function, line, bh->b_blocknr,
106 "bad entry in directory: %s - offset=%u(%u), " 105 "bad entry in directory: %s - offset=%u(%u), "
107 "inode=%u, rec_len=%d, name_len=%d", 106 "inode=%u, rec_len=%d, name_len=%d",
108 error_msg, (unsigned) (offset % bh->b_size), 107 error_msg, (unsigned) (offset % size),
109 offset, le32_to_cpu(de->inode), 108 offset, le32_to_cpu(de->inode),
110 rlen, de->name_len); 109 rlen, de->name_len);
111 110
@@ -221,8 +220,9 @@ revalidate:
221 while (!error && filp->f_pos < inode->i_size 220 while (!error && filp->f_pos < inode->i_size
222 && offset < sb->s_blocksize) { 221 && offset < sb->s_blocksize) {
223 de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); 222 de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
224 if (ext4_check_dir_entry(inode, filp, de, 223 if (ext4_check_dir_entry(inode, filp, de, bh,
225 bh, offset)) { 224 bh->b_data, bh->b_size,
225 offset)) {
226 /* 226 /*
227 * On error, skip the f_pos to the next block 227 * On error, skip the f_pos to the next block
228 */ 228 */
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index cf840146ce8..59cbf498fd5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1960,10 +1960,11 @@ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
1960extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, 1960extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *,
1961 struct file *, 1961 struct file *,
1962 struct ext4_dir_entry_2 *, 1962 struct ext4_dir_entry_2 *,
1963 struct buffer_head *, unsigned int); 1963 struct buffer_head *, char *, int,
1964#define ext4_check_dir_entry(dir, filp, de, bh, offset) \ 1964 unsigned int);
1965#define ext4_check_dir_entry(dir, filp, de, bh, buf, size, offset) \
1965 unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \ 1966 unlikely(__ext4_check_dir_entry(__func__, __LINE__, (dir), (filp), \
1966 (de), (bh), (offset))) 1967 (de), (bh), (buf), (size), (offset)))
1967extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, 1968extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
1968 __u32 minor_hash, 1969 __u32 minor_hash,
1969 struct ext4_dir_entry_2 *dirent); 1970 struct ext4_dir_entry_2 *dirent);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index edb9f10c145..10da2d50a5d 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -892,6 +892,7 @@ static int htree_dirblock_to_tree(struct file *dir_file,
892 EXT4_DIR_REC_LEN(0)); 892 EXT4_DIR_REC_LEN(0));
893 for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { 893 for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) {
894 if (ext4_check_dir_entry(dir, NULL, de, bh, 894 if (ext4_check_dir_entry(dir, NULL, de, bh,
895 bh->b_data, bh->b_size,
895 (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) 896 (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb))
896 + ((char *)de - bh->b_data))) { 897 + ((char *)de - bh->b_data))) {
897 /* On error, skip the f_pos to the next block. */ 898 /* On error, skip the f_pos to the next block. */
@@ -1130,7 +1131,8 @@ static inline int search_dirblock(struct buffer_head *bh,
1130 if ((char *) de + namelen <= dlimit && 1131 if ((char *) de + namelen <= dlimit &&
1131 ext4_match (namelen, name, de)) { 1132 ext4_match (namelen, name, de)) {
1132 /* found a match - just to be sure, do a full check */ 1133 /* found a match - just to be sure, do a full check */
1133 if (ext4_check_dir_entry(dir, NULL, de, bh, offset)) 1134 if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
1135 bh->b_size, offset))
1134 return -1; 1136 return -1;
1135 *res_dir = de; 1137 *res_dir = de;
1136 return 1; 1138 return 1;
@@ -1643,7 +1645,8 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
1643 de = (struct ext4_dir_entry_2 *)bh->b_data; 1645 de = (struct ext4_dir_entry_2 *)bh->b_data;
1644 top = bh->b_data + (blocksize - csum_size) - reclen; 1646 top = bh->b_data + (blocksize - csum_size) - reclen;
1645 while ((char *) de <= top) { 1647 while ((char *) de <= top) {
1646 if (ext4_check_dir_entry(dir, NULL, de, bh, offset)) 1648 if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
1649 bh->b_size, offset))
1647 return -EIO; 1650 return -EIO;
1648 if (ext4_match(namelen, name, de)) 1651 if (ext4_match(namelen, name, de))
1649 return -EEXIST; 1652 return -EEXIST;
@@ -2076,7 +2079,8 @@ static int ext4_delete_entry(handle_t *handle,
2076 pde = NULL; 2079 pde = NULL;
2077 de = (struct ext4_dir_entry_2 *) bh->b_data; 2080 de = (struct ext4_dir_entry_2 *) bh->b_data;
2078 while (i < bh->b_size - csum_size) { 2081 while (i < bh->b_size - csum_size) {
2079 if (ext4_check_dir_entry(dir, NULL, de, bh, i)) 2082 if (ext4_check_dir_entry(dir, NULL, de, bh,
2083 bh->b_data, bh->b_size, i))
2080 return -EIO; 2084 return -EIO;
2081 if (de == de_del) { 2085 if (de == de_del) {
2082 BUFFER_TRACE(bh, "get_write_access"); 2086 BUFFER_TRACE(bh, "get_write_access");
@@ -2439,7 +2443,8 @@ static int empty_dir(struct inode *inode)
2439 set_buffer_verified(bh); 2443 set_buffer_verified(bh);
2440 de = (struct ext4_dir_entry_2 *) bh->b_data; 2444 de = (struct ext4_dir_entry_2 *) bh->b_data;
2441 } 2445 }
2442 if (ext4_check_dir_entry(inode, NULL, de, bh, offset)) { 2446 if (ext4_check_dir_entry(inode, NULL, de, bh,
2447 bh->b_data, bh->b_size, offset)) {
2443 de = (struct ext4_dir_entry_2 *)(bh->b_data + 2448 de = (struct ext4_dir_entry_2 *)(bh->b_data +
2444 sb->s_blocksize); 2449 sb->s_blocksize);
2445 offset = (offset | (sb->s_blocksize - 1)) + 1; 2450 offset = (offset | (sb->s_blocksize - 1)) + 1;