The JBD2 naming cleanups patch was missing a definition of JBD2_POISON_FREE
[ext4-patch-queue.git] / ext2_rec_len_overflow_with_64kblk_fix.patch
blob6c14d9aff93718bb1d915f5bf9750d8fa7195a08
1 ext2: fix rec_len overflow
3 From: Takashi Sato <sho@tnes.nec.co.jp>
5 prevent rec_len from overflow with 64KB blocksize
8 Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
9 ---
11 fs/ext2/dir.c | 56 +++++++++++++++++++++++++++++++++++++++---------
12 include/linux/ext2_fs.h | 13 +++++++++++
13 2 files changed, 59 insertions(+), 10 deletions(-)
16 Index: linux-2.6.23-rc5/fs/ext2/dir.c
17 ===================================================================
18 --- linux-2.6.23-rc5.orig/fs/ext2/dir.c 2007-09-12 16:16:57.000000000 -0700
19 +++ linux-2.6.23-rc5/fs/ext2/dir.c 2007-09-12 16:33:10.000000000 -0700
20 @@ -94,9 +94,9 @@ static void ext2_check_page(struct page
21 goto out;
23 for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
24 + offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
25 p = (ext2_dirent *)(kaddr + offs);
26 rec_len = le16_to_cpu(p->rec_len);
28 if (rec_len < EXT2_DIR_REC_LEN(1))
29 goto Eshort;
30 if (rec_len & 3)
31 @@ -108,6 +108,7 @@ static void ext2_check_page(struct page
32 if (le32_to_cpu(p->inode) > max_inumber)
33 goto Einumber;
35 + offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
36 if (offs != limit)
37 goto Eend;
38 out:
39 @@ -283,6 +284,8 @@ ext2_readdir (struct file * filp, void *
40 de = (ext2_dirent *)(kaddr+offset);
41 limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
42 for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
43 + de = EXT2_DIR_ADJUST_TAIL_ADDR(kaddr,
44 + de, sb->s_blocksize);
45 if (de->rec_len == 0) {
46 ext2_error(sb, __FUNCTION__,
47 "zero-length directory entry");
48 @@ -305,8 +308,12 @@ ext2_readdir (struct file * filp, void *
49 return 0;
52 + filp->f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp->f_pos,
53 + sb->s_blocksize);
54 filp->f_pos += le16_to_cpu(de->rec_len);
56 + filp->f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp->f_pos,
57 + sb->s_blocksize);
58 ext2_put_page(page);
60 return 0;
61 @@ -343,13 +350,16 @@ struct ext2_dir_entry_2 * ext2_find_entr
62 start = 0;
63 n = start;
64 do {
65 - char *kaddr;
66 + char *kaddr, *page_start;
67 page = ext2_get_page(dir, n);
68 if (!IS_ERR(page)) {
69 - kaddr = page_address(page);
70 + page_start = page_address(page);
71 + kaddr = page_start;
72 de = (ext2_dirent *) kaddr;
73 kaddr += ext2_last_byte(dir, n) - reclen;
74 while ((char *) de <= kaddr) {
75 + de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start,
76 + de, dir->i_sb->s_blocksize);
77 if (de->rec_len == 0) {
78 ext2_error(dir->i_sb, __FUNCTION__,
79 "zero-length directory entry");
80 @@ -416,6 +426,7 @@ void ext2_set_link(struct inode *dir, st
81 unsigned to = from + le16_to_cpu(de->rec_len);
82 int err;
84 + to = EXT2_DIR_ADJUST_TAIL_OFFS(to, inode->i_sb->s_blocksize);
85 lock_page(page);
86 err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
87 BUG_ON(err);
88 @@ -446,6 +457,7 @@ int ext2_add_link (struct dentry *dentry
89 char *kaddr;
90 unsigned from, to;
91 int err;
92 + char *page_start = NULL;
95 * We take care of directory expansion in the same loop.
96 @@ -460,16 +472,30 @@ int ext2_add_link (struct dentry *dentry
97 if (IS_ERR(page))
98 goto out;
99 lock_page(page);
100 - kaddr = page_address(page);
101 + page_start = page_address(page);
102 + kaddr = page_start;
103 dir_end = kaddr + ext2_last_byte(dir, n);
104 de = (ext2_dirent *)kaddr;
105 - kaddr += PAGE_CACHE_SIZE - reclen;
106 + if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
107 + kaddr += PAGE_CACHE_SIZE - reclen;
108 + } else {
109 + kaddr += PAGE_CACHE_SIZE -
110 + (chunk_size - EXT2_DIR_MAX_REC_LEN) - reclen;
112 while ((char *)de <= kaddr) {
113 + de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de,
114 + chunk_size);
115 if ((char *)de == dir_end) {
116 /* We hit i_size */
117 name_len = 0;
118 - rec_len = chunk_size;
119 - de->rec_len = cpu_to_le16(chunk_size);
120 + if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
121 + rec_len = chunk_size;
122 + de->rec_len = cpu_to_le16(chunk_size);
123 + } else {
124 + rec_len = EXT2_DIR_MAX_REC_LEN;
125 + de->rec_len =
126 + cpu_to_le16(EXT2_DIR_MAX_REC_LEN);
128 de->inode = 0;
129 goto got_it;
131 @@ -499,6 +525,7 @@ int ext2_add_link (struct dentry *dentry
132 got_it:
133 from = (char*)de - (char*)page_address(page);
134 to = from + rec_len;
135 + to = EXT2_DIR_ADJUST_TAIL_OFFS(to, chunk_size);
136 err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
137 if (err)
138 goto out_unlock;
139 @@ -541,6 +568,7 @@ int ext2_delete_entry (struct ext2_dir_e
140 ext2_dirent * de = (ext2_dirent *) (kaddr + from);
141 int err;
143 + to = EXT2_DIR_ADJUST_TAIL_OFFS(to, inode->i_sb->s_blocksize);
144 while ((char*)de < (char*)dir) {
145 if (de->rec_len == 0) {
146 ext2_error(inode->i_sb, __FUNCTION__,
147 @@ -598,7 +626,12 @@ int ext2_make_empty(struct inode *inode,
149 de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
150 de->name_len = 2;
151 - de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
152 + if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
153 + de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
154 + } else {
155 + de->rec_len = cpu_to_le16(EXT2_DIR_MAX_REC_LEN
156 + - EXT2_DIR_REC_LEN(1));
158 de->inode = cpu_to_le32(parent->i_ino);
159 memcpy (de->name, "..\0", 4);
160 ext2_set_de_type (de, inode);
161 @@ -618,18 +651,21 @@ int ext2_empty_dir (struct inode * inode
162 unsigned long i, npages = dir_pages(inode);
164 for (i = 0; i < npages; i++) {
165 - char *kaddr;
166 + char *kaddr, *page_start;
167 ext2_dirent * de;
168 page = ext2_get_page(inode, i);
170 if (IS_ERR(page))
171 continue;
173 - kaddr = page_address(page);
174 + page_start = page_address(page);
175 + kaddr = page_start;
176 de = (ext2_dirent *)kaddr;
177 kaddr += ext2_last_byte(inode, i) - EXT2_DIR_REC_LEN(1);
179 while ((char *)de <= kaddr) {
180 + de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de,
181 + inode->i_sb->s_blocksize);
182 if (de->rec_len == 0) {
183 ext2_error(inode->i_sb, __FUNCTION__,
184 "zero-length directory entry");
185 Index: linux-2.6.23-rc5/include/linux/ext2_fs.h
186 ===================================================================
187 --- linux-2.6.23-rc5.orig/include/linux/ext2_fs.h 2007-09-12 16:25:40.000000000 -0700
188 +++ linux-2.6.23-rc5/include/linux/ext2_fs.h 2007-09-12 16:34:07.000000000 -0700
189 @@ -557,5 +557,18 @@ enum {
190 #define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
191 #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
192 ~EXT2_DIR_ROUND)
193 +#define EXT2_DIR_MAX_REC_LEN 65532
196 + * Align a tail offset(address) to the end of a directory block
197 + */
198 +#define EXT2_DIR_ADJUST_TAIL_OFFS(offs, bsize) \
199 + ((((offs) & ((bsize) -1)) == EXT2_DIR_MAX_REC_LEN) ? \
200 + ((offs) + (bsize) - EXT2_DIR_MAX_REC_LEN):(offs))
202 +#define EXT2_DIR_ADJUST_TAIL_ADDR(page, de, bsize) \
203 + (((((char *)(de) - (page)) & ((bsize) - 1)) == EXT2_DIR_MAX_REC_LEN) ? \
204 + ((ext2_dirent *)((char *)(de) + (bsize) - EXT2_DIR_MAX_REC_LEN)):(de))
206 #endif /* _LINUX_EXT2_FS_H */