summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch')
-rw-r--r--meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch190
1 files changed, 190 insertions, 0 deletions
diff --git a/meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch b/meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch
new file mode 100644
index 0000000000..0dabfba663
--- /dev/null
+++ b/meta/recipes-devtools/squashfs-tools/patches/squashfs-4.2-fix-CVE-2012-4025.patch
@@ -0,0 +1,190 @@
1Upstream-Status: Backport
2
3Reference: http://squashfs.git.sourceforge.net/git/gitweb.cgi?
4p=squashfs/squashfs;a=patch;h=8515b3d420f502c5c0236b86e2d6d7e3b23c190e
5
6Integer overflow in the queue_init function in unsquashfs.c in
7unsquashfs in Squashfs 4.2 and earlier allows remote attackers
8to execute arbitrary code via a crafted block_log field in the
9superblock of a .sqsh file, leading to a heap-based buffer overflow.
10
11http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-4025
12
13Signed-off-by: yanjun.zhu <yanjun.zhu@windriver.com>
14
15--- a/unsquashfs.c 2012-11-30 17:57:57.000000000 +0800
16+++ b/unsquashfs.c 2012-11-30 17:58:09.000000000 +0800
17@@ -33,6 +33,7 @@
18 #include <sys/types.h>
19 #include <sys/time.h>
20 #include <sys/resource.h>
21+#include <limits.h>
22
23 struct cache *fragment_cache, *data_cache;
24 struct queue *to_reader, *to_deflate, *to_writer, *from_writer;
25@@ -138,6 +139,24 @@ void sigalrm_handler()
26 }
27
28
29+int add_overflow(int a, int b)
30+{
31+ return (INT_MAX - a) < b;
32+}
33+
34+
35+int shift_overflow(int a, int shift)
36+{
37+ return (INT_MAX >> shift) < a;
38+}
39+
40+
41+int multiply_overflow(int a, int multiplier)
42+{
43+ return (INT_MAX / multiplier) < a;
44+}
45+
46+
47 struct queue *queue_init(int size)
48 {
49 struct queue *queue = malloc(sizeof(struct queue));
50@@ -145,6 +164,10 @@ struct queue *queue_init(int size)
51 if(queue == NULL)
52 EXIT_UNSQUASH("Out of memory in queue_init\n");
53
54+ if(add_overflow(size, 1) ||
55+ multiply_overflow(size + 1, sizeof(void *)))
56+ EXIT_UNSQUASH("Size too large in queue_init\n");
57+
58 queue->data = malloc(sizeof(void *) * (size + 1));
59 if(queue->data == NULL)
60 EXIT_UNSQUASH("Out of memory in queue_init\n");
61@@ -1948,13 +1971,30 @@ void initialise_threads(int fragment_buf
62 * allocate to_reader, to_deflate and to_writer queues. Set based on
63 * open file limit and cache size, unless open file limit is unlimited,
64 * in which case set purely based on cache limits
65+ *
66+ * In doing so, check that the user supplied values do not overflow
67+ * a signed int
68 */
69 if (max_files != -1) {
70+ if(add_overflow(data_buffer_size, max_files) ||
71+ add_overflow(data_buffer_size, max_files * 2))
72+ EXIT_UNSQUASH("Data queue size is too large\n");
73+
74 to_reader = queue_init(max_files + data_buffer_size);
75 to_deflate = queue_init(max_files + data_buffer_size);
76 to_writer = queue_init(max_files * 2 + data_buffer_size);
77 } else {
78- int all_buffers_size = fragment_buffer_size + data_buffer_size;
79+ int all_buffers_size;
80+
81+ if(add_overflow(fragment_buffer_size, data_buffer_size))
82+ EXIT_UNSQUASH("Data and fragment queues combined are"
83+ " too large\n");
84+
85+ all_buffers_size = fragment_buffer_size + data_buffer_size;
86+
87+ if(add_overflow(all_buffers_size, all_buffers_size))
88+ EXIT_UNSQUASH("Data and fragment queues combined are"
89+ " too large\n");
90
91 to_reader = queue_init(all_buffers_size);
92 to_deflate = queue_init(all_buffers_size);
93@@ -2059,6 +2099,32 @@ void progress_bar(long long current, lon
94 }
95
96
97+int parse_number(char *arg, int *res)
98+{
99+ char *b;
100+ long number = strtol(arg, &b, 10);
101+
102+ /* check for trailing junk after number */
103+ if(*b != '\0')
104+ return 0;
105+
106+ /* check for strtol underflow or overflow in conversion */
107+ if(number == LONG_MIN || number == LONG_MAX)
108+ return 0;
109+
110+ /* reject negative numbers as invalid */
111+ if(number < 0)
112+ return 0;
113+
114+ /* check if long result will overflow signed int */
115+ if(number > INT_MAX)
116+ return 0;
117+
118+ *res = number;
119+ return 1;
120+}
121+
122+
123 #define VERSION() \
124 printf("unsquashfs version 4.2 (2011/02/28)\n");\
125 printf("copyright (C) 2011 Phillip Lougher "\
126@@ -2140,8 +2206,8 @@ int main(int argc, char *argv[])
127 } else if(strcmp(argv[i], "-data-queue") == 0 ||
128 strcmp(argv[i], "-da") == 0) {
129 if((++i == argc) ||
130- (data_buffer_size = strtol(argv[i], &b,
131- 10), *b != '\0')) {
132+ !parse_number(argv[i],
133+ &data_buffer_size)) {
134 ERROR("%s: -data-queue missing or invalid "
135 "queue size\n", argv[0]);
136 exit(1);
137@@ -2154,8 +2220,8 @@ int main(int argc, char *argv[])
138 } else if(strcmp(argv[i], "-frag-queue") == 0 ||
139 strcmp(argv[i], "-fr") == 0) {
140 if((++i == argc) ||
141- (fragment_buffer_size = strtol(argv[i],
142- &b, 10), *b != '\0')) {
143+ !parse_number(argv[i],
144+ &fragment_buffer_size)) {
145 ERROR("%s: -frag-queue missing or invalid "
146 "queue size\n", argv[0]);
147 exit(1);
148@@ -2280,11 +2346,39 @@ options:
149 block_log = sBlk.s.block_log;
150
151 /*
152+ * Sanity check block size and block log.
153+ *
154+ * Check they're within correct limits
155+ */
156+ if(block_size > SQUASHFS_FILE_MAX_SIZE ||
157+ block_log > SQUASHFS_FILE_MAX_LOG)
158+ EXIT_UNSQUASH("Block size or block_log too large."
159+ " File system is corrupt.\n");
160+
161+ /*
162+ * Check block_size and block_log match
163+ */
164+ if(block_size != (1 << block_log))
165+ EXIT_UNSQUASH("Block size and block_log do not match."
166+ " File system is corrupt.\n");
167+
168+ /*
169 * convert from queue size in Mbytes to queue size in
170- * blocks
171+ * blocks.
172+ *
173+ * In doing so, check that the user supplied values do not
174+ * overflow a signed int
175 */
176- fragment_buffer_size <<= 20 - block_log;
177- data_buffer_size <<= 20 - block_log;
178+ if(shift_overflow(fragment_buffer_size, 20 - block_log))
179+ EXIT_UNSQUASH("Fragment queue size is too large\n");
180+ else
181+ fragment_buffer_size <<= 20 - block_log;
182+
183+ if(shift_overflow(data_buffer_size, 20 - block_log))
184+ EXIT_UNSQUASH("Data queue size is too large\n");
185+ else
186+ data_buffer_size <<= 20 - block_log;
187+
188 initialise_threads(fragment_buffer_size, data_buffer_size);
189
190 fragment_data = malloc(block_size);