/[linux-patches]/genpatches-2.6/tags/2.6.18-9/4301_squashfs-fsfuzzer.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.18-9/4301_squashfs-fsfuzzer.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 802 - (show annotations) (download)
Wed Jan 10 14:47:23 2007 UTC (11 years, 6 months ago) by dsd
File size: 12240 byte(s)
2.6.18-9 release
1 Index: linux-2.6.18-gentoo-r5/fs/squashfs/inode.c
2 ===================================================================
3 --- linux-2.6.18-gentoo-r5.orig/fs/squashfs/inode.c
4 +++ linux-2.6.18-gentoo-r5/fs/squashfs/inode.c
5 @@ -173,14 +173,15 @@ out:
6
7 SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
8 long long index, unsigned int length,
9 - long long *next_index)
10 + long long *next_index, int srclength)
11 {
12 struct squashfs_sb_info *msblk = s->s_fs_info;
13 + struct squashfs_super_block *sblk = &msblk->sblk;
14 struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
15 msblk->devblksize_log2) + 2];
16 unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
17 unsigned int cur_index = index >> msblk->devblksize_log2;
18 - int bytes, avail_bytes, b = 0, k;
19 + int bytes, avail_bytes, b = 0, k = 0;
20 char *c_buffer;
21 unsigned int compressed;
22 unsigned int c_byte = length;
23 @@ -191,8 +192,11 @@ SQSH_EXTERN unsigned int squashfs_read_d
24 c_buffer = compressed ? msblk->read_data : buffer;
25 c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
26
27 - TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
28 - ? "" : "un", (unsigned int) c_byte);
29 + TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
30 + ? "" : "un", (unsigned int) c_byte, srclength);
31 +
32 + if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
33 + goto read_failure;
34
35 if (!(bh[0] = sb_getblk(s, cur_index)))
36 goto block_release;
37 @@ -204,6 +208,9 @@ SQSH_EXTERN unsigned int squashfs_read_d
38 }
39 ll_rw_block(READ, b, bh);
40 } else {
41 + if (index < 0 || (index + 2) > sblk->bytes_used)
42 + goto read_failure;
43 +
44 if (!(bh[0] = get_block_length(s, &cur_index, &offset,
45 &c_byte)))
46 goto read_failure;
47 @@ -216,6 +223,9 @@ SQSH_EXTERN unsigned int squashfs_read_d
48 TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
49 ? "" : "un", (unsigned int) c_byte);
50
51 + if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
52 + goto read_failure;
53 +
54 for (b = 1; bytes < c_byte; b++) {
55 if (!(bh[b] = sb_getblk(s, ++cur_index)))
56 goto block_release;
57 @@ -227,7 +237,7 @@ SQSH_EXTERN unsigned int squashfs_read_d
58 if (compressed)
59 down(&msblk->read_data_mutex);
60
61 - for (bytes = 0, k = 0; k < b; k++) {
62 + for (bytes = 0; k < b; k++) {
63 avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
64 msblk->devblksize - offset :
65 c_byte - bytes;
66 @@ -249,7 +259,7 @@ SQSH_EXTERN unsigned int squashfs_read_d
67 msblk->stream.next_in = c_buffer;
68 msblk->stream.avail_in = c_byte;
69 msblk->stream.next_out = buffer;
70 - msblk->stream.avail_out = msblk->read_size;
71 + msblk->stream.avail_out = srclength;
72
73 if (((zlib_err = zlib_inflateInit(&msblk->stream)) != Z_OK) ||
74 ((zlib_err = zlib_inflate(&msblk->stream, Z_FINISH))
75 @@ -271,8 +281,8 @@ SQSH_EXTERN unsigned int squashfs_read_d
76 return bytes;
77
78 block_release:
79 - while (--b >= 0)
80 - brelse(bh[b]);
81 + for (; k < b; k++)
82 + brelse(bh[k]);
83
84 read_failure:
85 ERROR("sb_bread failed reading block 0x%x\n", cur_index);
86 @@ -336,14 +346,20 @@ SQSH_EXTERN int squashfs_get_cached_bloc
87 msblk->block_cache[i].block = SQUASHFS_USED_BLK;
88 up(&msblk->block_cache_mutex);
89
90 - if (!(msblk->block_cache[i].length =
91 - squashfs_read_data(s,
92 - msblk->block_cache[i].data,
93 - block, 0, &next_index))) {
94 - ERROR("Unable to read cache block [%llx:%x]\n",
95 - block, offset);
96 - goto out;
97 - }
98 + msblk->block_cache[i].length = squashfs_read_data(s,
99 + msblk->block_cache[i].data, block, 0, &next_index,
100 + SQUASHFS_METADATA_SIZE);
101 +
102 + if (msblk->block_cache[i].length == 0) {
103 + ERROR("Unable to read cache block [%llx:%x]\n",
104 + block, offset);
105 + down(&msblk->block_cache_mutex);
106 + msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
107 + kfree(msblk->block_cache[i].data);
108 + wake_up(&msblk->waitq);
109 + up(&msblk->block_cache_mutex);
110 + goto out;
111 + }
112
113 down(&msblk->block_cache_mutex);
114 wake_up(&msblk->waitq);
115 @@ -357,7 +373,11 @@ SQSH_EXTERN int squashfs_get_cached_bloc
116 continue;
117 }
118
119 - if ((bytes = msblk->block_cache[i].length - offset) >= length) {
120 + bytes = msblk->block_cache[i].length - offset;
121 +
122 + if (bytes < 1)
123 + goto out;
124 + else if (bytes >= length) {
125 if (buffer)
126 memcpy(buffer, msblk->block_cache[i].data +
127 offset, length);
128 @@ -442,6 +462,7 @@ SQSH_EXTERN struct squashfs_fragment_cac
129 {
130 int i, n;
131 struct squashfs_sb_info *msblk = s->s_fs_info;
132 + struct squashfs_super_block *sblk = &msblk->sblk;
133
134 while ( 1 ) {
135 down(&msblk->fragment_mutex);
136 @@ -487,7 +508,8 @@ SQSH_EXTERN struct squashfs_fragment_cac
137
138 if (!(msblk->fragment[i].length = squashfs_read_data(s,
139 msblk->fragment[i].data,
140 - start_block, length, NULL))) {
141 + start_block, length, NULL,
142 + sblk->block_size))) {
143 ERROR("Unable to read fragment cache block "
144 "[%llx]\n", start_block);
145 msblk->fragment[i].locked = 0;
146 @@ -876,6 +898,10 @@ static int read_fragment_index_table(str
147 {
148 struct squashfs_sb_info *msblk = s->s_fs_info;
149 struct squashfs_super_block *sblk = &msblk->sblk;
150 + unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
151 +
152 + if (length == 0)
153 + return 1;
154
155 /* Allocate fragment index table */
156 if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES
157 @@ -884,13 +910,9 @@ static int read_fragment_index_table(str
158 return 0;
159 }
160
161 - if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) &&
162 - !squashfs_read_data(s, (char *)
163 - msblk->fragment_index,
164 - sblk->fragment_table_start,
165 - SQUASHFS_FRAGMENT_INDEX_BYTES
166 - (sblk->fragments) |
167 - SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
168 + if (!squashfs_read_data(s, (char *) msblk->fragment_index,
169 + sblk->fragment_table_start, length |
170 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
171 ERROR("unable to read fragment index table\n");
172 return 0;
173 }
174 @@ -982,9 +1004,11 @@ static int squashfs_fill_super(struct su
175 init_waitqueue_head(&msblk->waitq);
176 init_waitqueue_head(&msblk->fragment_wait_queue);
177
178 + sblk->bytes_used = sizeof(struct squashfs_super_block);
179 if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
180 sizeof(struct squashfs_super_block) |
181 - SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
182 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
183 + sizeof(struct squashfs_super_block))) {
184 SERROR("unable to read superblock\n");
185 goto failed_mount;
186 }
187 @@ -1012,6 +1036,15 @@ static int squashfs_fill_super(struct su
188 if(!supported_squashfs_filesystem(msblk, silent))
189 goto failed_mount;
190
191 + /* Check the filesystem does not extend beyond the end of the
192 + block device */
193 + if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
194 + goto failed_mount;
195 +
196 + /* Check the root inode for sanity */
197 + if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
198 + goto failed_mount;
199 +
200 TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
201 TRACE("Inodes are %scompressed\n",
202 SQUASHFS_UNCOMPRESSED_INODES
203 @@ -1081,7 +1114,9 @@ static int squashfs_fill_super(struct su
204 if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
205 ((sblk->no_uids + sblk->no_guids) *
206 sizeof(unsigned int)) |
207 - SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
208 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
209 + (sblk->no_uids + sblk->no_guids) *
210 + sizeof(unsigned int))) {
211 ERROR("unable to read uid/gid table\n");
212 goto failed_mount;
213 }
214 @@ -1092,7 +1127,9 @@ static int squashfs_fill_super(struct su
215 if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
216 ((sblk->no_uids + sblk->no_guids) *
217 sizeof(unsigned int)) |
218 - SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
219 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
220 + (sblk->no_uids + sblk->no_guids) *
221 + sizeof(unsigned int))) {
222 ERROR("unable to read uid/gid table\n");
223 goto failed_mount;
224 }
225 @@ -1518,7 +1555,8 @@ static int squashfs_readpage(struct file
226 down(&msblk->read_page_mutex);
227
228 if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
229 - block, bsize, NULL))) {
230 + block, bsize, NULL,
231 + msblk->read_size))) {
232 ERROR("Unable to read page, block %llx, size %x\n", block,
233 bsize);
234 up(&msblk->read_page_mutex);
235 @@ -1618,15 +1656,12 @@ static int squashfs_readpage4K(struct fi
236
237 if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
238 PAGE_CACHE_SHIFT)) {
239 - pageaddr = kmap_atomic(page, KM_USER0);
240 block_list = NULL;
241 goto skip_read;
242 }
243
244 if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
245 ERROR("Failed to allocate block_list\n");
246 - pageaddr = kmap_atomic(page, KM_USER0);
247 - block_list = NULL;
248 goto skip_read;
249 }
250
251 @@ -1638,11 +1673,12 @@ static int squashfs_readpage4K(struct fi
252
253 down(&msblk->read_page_mutex);
254 bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
255 - bsize, NULL);
256 - pageaddr = kmap_atomic(page, KM_USER0);
257 - if (bytes)
258 + bsize, NULL, msblk->read_size);
259 + if (bytes) {
260 + pageaddr = kmap_atomic(page, KM_USER0);
261 memcpy(pageaddr, msblk->read_page, bytes);
262 - else
263 + kunmap_atomic(pageaddr, KM_USER0);
264 + } else
265 ERROR("Unable to read page, block %llx, size %x\n",
266 block, bsize);
267 up(&msblk->read_page_mutex);
268 @@ -1652,11 +1688,12 @@ static int squashfs_readpage4K(struct fi
269 SQUASHFS_I(inode)->
270 u.s1.fragment_start_block,
271 SQUASHFS_I(inode)-> u.s1.fragment_size);
272 - pageaddr = kmap_atomic(page, KM_USER0);
273 if (fragment) {
274 bytes = i_size_read(inode) & (sblk->block_size - 1);
275 + pageaddr = kmap_atomic(page, KM_USER0);
276 memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
277 u.s1.fragment_offset, bytes);
278 + kunmap_atomic(pageaddr, KM_USER0);
279 release_cached_fragment(msblk, fragment);
280 } else
281 ERROR("Unable to read page, block %llx, size %x\n",
282 @@ -1666,6 +1703,7 @@ static int squashfs_readpage4K(struct fi
283 }
284
285 skip_read:
286 + pageaddr = kmap_atomic(page, KM_USER0);
287 memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
288 kunmap_atomic(pageaddr, KM_USER0);
289 flush_dcache_page(page);
290 Index: linux-2.6.18-gentoo-r5/fs/squashfs/squashfs2_0.c
291 ===================================================================
292 --- linux-2.6.18-gentoo-r5.orig/fs/squashfs/squashfs2_0.c
293 +++ linux-2.6.18-gentoo-r5/fs/squashfs/squashfs2_0.c
294 @@ -73,12 +73,13 @@ static int read_fragment_index_table_2(s
295 }
296
297 if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
298 - !squashfs_read_data(s, (char *)
299 - msblk->fragment_index_2,
300 - sblk->fragment_table_start,
301 - SQUASHFS_FRAGMENT_INDEX_BYTES_2
302 - (sblk->fragments) |
303 - SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) {
304 + !squashfs_read_data(s, (char *)
305 + msblk->fragment_index_2,
306 + sblk->fragment_table_start,
307 + SQUASHFS_FRAGMENT_INDEX_BYTES_2
308 + (sblk->fragments) |
309 + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL,
310 + SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
311 ERROR("unable to read fragment index table\n");
312 return 0;
313 }
314 Index: linux-2.6.18-gentoo-r5/fs/squashfs/squashfs.h
315 ===================================================================
316 --- linux-2.6.18-gentoo-r5.orig/fs/squashfs/squashfs.h
317 +++ linux-2.6.18-gentoo-r5/fs/squashfs/squashfs.h
318 @@ -49,7 +49,7 @@ static inline struct squashfs_inode_info
319 #define SQSH_EXTERN
320 extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
321 long long index, unsigned int length,
322 - long long *next_index);
323 + long long *next_index, int srclength);
324 extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
325 long long block, unsigned int offset,
326 int length, long long *next_block,

  ViewVC Help
Powered by ViewVC 1.1.20