summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/squashfs-tools
diff options
context:
space:
mode:
authorKai Kang <kai.kang@windriver.com>2021-11-02 16:17:01 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-11-03 11:12:26 +0000
commit8b07a6769c2fc0cb6463753dee7f91139cac2d9f (patch)
tree69ad713f14c838fcbec2717546a603a23d93f26d /meta/recipes-devtools/squashfs-tools
parent7ee9a45fe06b1b3082f5045e01113119851b74a4 (diff)
downloadpoky-8b07a6769c2fc0cb6463753dee7f91139cac2d9f.tar.gz
squashfs-tools: fix CVE-2021-41072
Backport patch to fix CVE-2021-41072. And 3 more ancestor commits are backported too, otherwise it fails to compile. CVE: CVE-2021-41072 Ref: * https://nvd.nist.gov/vuln/detail/CVE-2021-41072 (From OE-Core rev: 5a6ef2c040154a5a4e5516013a8ff58c8ca7a518) Signed-off-by: Kai Kang <kai.kang@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/squashfs-tools')
-rw-r--r--meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-1.patch135
-rw-r--r--meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-2.patch108
-rw-r--r--meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-3.patch326
-rw-r--r--meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072.patch325
-rw-r--r--meta/recipes-devtools/squashfs-tools/squashfs-tools_git.bb4
5 files changed, 898 insertions, 0 deletions
diff --git a/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-1.patch b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-1.patch
new file mode 100644
index 0000000000..d01b5c6871
--- /dev/null
+++ b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-1.patch
@@ -0,0 +1,135 @@
1The commit is required by the fix for CVE-2021-41072.
2
3Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/80b8441]
4
5Signed-off-by: Kai Kang <kai.kang@windriver.com>
6
7From 80b8441a37fcf8bf07dacf24d9d6c6459a0f6e36 Mon Sep 17 00:00:00 2001
8From: Phillip Lougher <phillip@squashfs.org.uk>
9Date: Sun, 12 Sep 2021 19:58:19 +0100
10Subject: [PATCH] unsquashfs: use squashfs_closedir() to delete directory
11
12Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
13---
14 squashfs-tools/unsquash-1.c | 3 +--
15 squashfs-tools/unsquash-1234.c | 11 +++++++++--
16 squashfs-tools/unsquash-2.c | 3 +--
17 squashfs-tools/unsquash-3.c | 3 +--
18 squashfs-tools/unsquash-4.c | 3 +--
19 squashfs-tools/unsquashfs.c | 7 -------
20 squashfs-tools/unsquashfs.h | 1 +
21 7 files changed, 14 insertions(+), 17 deletions(-)
22
23diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
24index acba821..7598499 100644
25--- a/squashfs-tools/unsquash-1.c
26+++ b/squashfs-tools/unsquash-1.c
27@@ -373,8 +373,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
28 return dir;
29
30 corrupted:
31- free(dir->dirs);
32- free(dir);
33+ squashfs_closedir(dir);
34 return NULL;
35 }
36
37diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
38index c2d4f42..0c8dfbb 100644
39--- a/squashfs-tools/unsquash-1234.c
40+++ b/squashfs-tools/unsquash-1234.c
41@@ -25,8 +25,8 @@
42 * unsquash-4.
43 */
44
45-#define TRUE 1
46-#define FALSE 0
47+#include "unsquashfs.h"
48+
49 /*
50 * Check name for validity, name should not
51 * - be ".", "./", or
52@@ -56,3 +56,10 @@ int check_name(char *name, int size)
53
54 return TRUE;
55 }
56+
57+
58+void squashfs_closedir(struct dir *dir)
59+{
60+ free(dir->dirs);
61+ free(dir);
62+}
63diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
64index 0746b3d..86f62ba 100644
65--- a/squashfs-tools/unsquash-2.c
66+++ b/squashfs-tools/unsquash-2.c
67@@ -465,8 +465,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
68 return dir;
69
70 corrupted:
71- free(dir->dirs);
72- free(dir);
73+ squashfs_closedir(dir);
74 return NULL;
75 }
76
77diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
78index 094caaa..c04aa9e 100644
79--- a/squashfs-tools/unsquash-3.c
80+++ b/squashfs-tools/unsquash-3.c
81@@ -499,8 +499,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
82 return dir;
83
84 corrupted:
85- free(dir->dirs);
86- free(dir);
87+ squashfs_closedir(dir);
88 return NULL;
89 }
90
91diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
92index 3a1b9e1..ff62dcc 100644
93--- a/squashfs-tools/unsquash-4.c
94+++ b/squashfs-tools/unsquash-4.c
95@@ -436,8 +436,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
96 return dir;
97
98 corrupted:
99- free(dir->dirs);
100- free(dir);
101+ squashfs_closedir(dir);
102 return NULL;
103 }
104
105diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c
106index 7b590bd..04be53c 100644
107--- a/squashfs-tools/unsquashfs.c
108+++ b/squashfs-tools/unsquashfs.c
109@@ -1350,13 +1350,6 @@ unsigned int *offset, unsigned int *type)
110 }
111
112
113-void squashfs_closedir(struct dir *dir)
114-{
115- free(dir->dirs);
116- free(dir);
117-}
118-
119-
120 char *get_component(char *target, char **targname)
121 {
122 char *start;
123diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
124index 2e9201c..5ecb2ab 100644
125--- a/squashfs-tools/unsquashfs.h
126+++ b/squashfs-tools/unsquashfs.h
127@@ -291,4 +291,5 @@ extern long long *alloc_index_table(int);
128
129 /* unsquash-1234.c */
130 extern int check_name(char *, int);
131+extern void squashfs_closedir(struct dir *);
132 #endif
133--
1342.17.1
135
diff --git a/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-2.patch b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-2.patch
new file mode 100644
index 0000000000..6b230b35c6
--- /dev/null
+++ b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-2.patch
@@ -0,0 +1,108 @@
1The commit is required by the fix for CVE-2021-41072.
2
3Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/1993a4e]
4
5Signed-off-by: Kai Kang <kai.kang@windriver.com>
6
7From 1993a4e7aeda04962bf26e84c15fba8b58837e10 Mon Sep 17 00:00:00 2001
8From: Phillip Lougher <phillip@squashfs.org.uk>
9Date: Sun, 12 Sep 2021 20:09:13 +0100
10Subject: [PATCH] unsquashfs: dynamically allocate name
11
12Dynamically allocate name rather than store it
13directly in structure.
14
15Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
16---
17 squashfs-tools/unsquash-1.c | 2 +-
18 squashfs-tools/unsquash-1234.c | 5 +++++
19 squashfs-tools/unsquash-2.c | 2 +-
20 squashfs-tools/unsquash-3.c | 2 +-
21 squashfs-tools/unsquash-4.c | 2 +-
22 squashfs-tools/unsquashfs.h | 2 +-
23 6 files changed, 10 insertions(+), 5 deletions(-)
24
25diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
26index 7598499..d0121c6 100644
27--- a/squashfs-tools/unsquash-1.c
28+++ b/squashfs-tools/unsquash-1.c
29@@ -360,7 +360,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
30 dir->dirs = new_dir;
31 }
32
33- strcpy(dir->dirs[dir->dir_count].name, dire->name);
34+ dir->dirs[dir->dir_count].name = strdup(dire->name);
35 dir->dirs[dir->dir_count].start_block =
36 dirh.start_block;
37 dir->dirs[dir->dir_count].offset = dire->offset;
38diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
39index 0c8dfbb..ac46d9d 100644
40--- a/squashfs-tools/unsquash-1234.c
41+++ b/squashfs-tools/unsquash-1234.c
42@@ -60,6 +60,11 @@ int check_name(char *name, int size)
43
44 void squashfs_closedir(struct dir *dir)
45 {
46+ int i;
47+
48+ for(i = 0; i < dir->dir_count; i++)
49+ free(dir->dirs[i].name);
50+
51 free(dir->dirs);
52 free(dir);
53 }
54diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
55index 86f62ba..e847980 100644
56--- a/squashfs-tools/unsquash-2.c
57+++ b/squashfs-tools/unsquash-2.c
58@@ -452,7 +452,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
59 dir->dirs = new_dir;
60 }
61
62- strcpy(dir->dirs[dir->dir_count].name, dire->name);
63+ dir->dirs[dir->dir_count].name = strdup(dire->name);
64 dir->dirs[dir->dir_count].start_block =
65 dirh.start_block;
66 dir->dirs[dir->dir_count].offset = dire->offset;
67diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
68index c04aa9e..8223f27 100644
69--- a/squashfs-tools/unsquash-3.c
70+++ b/squashfs-tools/unsquash-3.c
71@@ -486,7 +486,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
72 dir->dirs = new_dir;
73 }
74
75- strcpy(dir->dirs[dir->dir_count].name, dire->name);
76+ dir->dirs[dir->dir_count].name = strdup(dire->name);
77 dir->dirs[dir->dir_count].start_block =
78 dirh.start_block;
79 dir->dirs[dir->dir_count].offset = dire->offset;
80diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
81index ff62dcc..1e199a7 100644
82--- a/squashfs-tools/unsquash-4.c
83+++ b/squashfs-tools/unsquash-4.c
84@@ -423,7 +423,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
85 dir->dirs = new_dir;
86 }
87
88- strcpy(dir->dirs[dir->dir_count].name, dire->name);
89+ dir->dirs[dir->dir_count].name = strdup(dire->name);
90 dir->dirs[dir->dir_count].start_block =
91 dirh.start_block;
92 dir->dirs[dir->dir_count].offset = dire->offset;
93diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
94index 5ecb2ab..583fbe4 100644
95--- a/squashfs-tools/unsquashfs.h
96+++ b/squashfs-tools/unsquashfs.h
97@@ -164,7 +164,7 @@ struct queue {
98 #define DIR_ENT_SIZE 16
99
100 struct dir_ent {
101- char name[SQUASHFS_NAME_LEN + 1];
102+ char *name;
103 unsigned int start_block;
104 unsigned int offset;
105 unsigned int type;
106--
1072.17.1
108
diff --git a/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-3.patch b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-3.patch
new file mode 100644
index 0000000000..5d5df6f15b
--- /dev/null
+++ b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072-requisite-3.patch
@@ -0,0 +1,326 @@
1The commit is required by the fix for CVE-2021-41072.
2
3Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/9938154]
4
5Signed-off-by: Kai Kang <kai.kang@windriver.com>
6
7From 9938154174756ee48a94ea0b076397a2944b028d Mon Sep 17 00:00:00 2001
8From: Phillip Lougher <phillip@squashfs.org.uk>
9Date: Sun, 12 Sep 2021 22:58:11 +0100
10Subject: [PATCH] unsquashfs: use linked list to store directory names
11
12This should bring higher performance, and it allows sorting
13if necessary (1.x and 2.0 filesystems).
14
15Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
16---
17 squashfs-tools/unsquash-1.c | 30 +++++++++++++++---------------
18 squashfs-tools/unsquash-1234.c | 12 ++++++++----
19 squashfs-tools/unsquash-2.c | 29 +++++++++++++++--------------
20 squashfs-tools/unsquash-3.c | 29 +++++++++++++++--------------
21 squashfs-tools/unsquash-4.c | 29 +++++++++++++++--------------
22 squashfs-tools/unsquashfs.c | 16 ++++++++++------
23 squashfs-tools/unsquashfs.h | 3 ++-
24 7 files changed, 80 insertions(+), 68 deletions(-)
25
26diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
27index d0121c6..b604434 100644
28--- a/squashfs-tools/unsquash-1.c
29+++ b/squashfs-tools/unsquash-1.c
30@@ -254,7 +254,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
31 long long start;
32 int bytes = 0;
33 int dir_count, size, res;
34- struct dir_ent *new_dir;
35+ struct dir_ent *ent, *cur_ent = NULL;
36 struct dir *dir;
37
38 TRACE("squashfs_opendir: inode start block %d, offset %d\n",
39@@ -267,7 +267,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
40 MEM_ERROR();
41
42 dir->dir_count = 0;
43- dir->cur_entry = 0;
44+ dir->cur_entry = NULL;
45 dir->mode = (*i)->mode;
46 dir->uid = (*i)->uid;
47 dir->guid = (*i)->gid;
48@@ -351,20 +351,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
49 "%d:%d, type %d\n", dire->name,
50 dirh.start_block, dire->offset, dire->type);
51
52- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
53- new_dir = realloc(dir->dirs, (dir->dir_count +
54- DIR_ENT_SIZE) * sizeof(struct dir_ent));
55- if(new_dir == NULL)
56- MEM_ERROR();
57-
58- dir->dirs = new_dir;
59- }
60+ ent = malloc(sizeof(struct dir_ent));
61+ if(ent == NULL)
62+ MEM_ERROR();
63
64- dir->dirs[dir->dir_count].name = strdup(dire->name);
65- dir->dirs[dir->dir_count].start_block =
66- dirh.start_block;
67- dir->dirs[dir->dir_count].offset = dire->offset;
68- dir->dirs[dir->dir_count].type = dire->type;
69+ ent->name = strdup(dire->name);
70+ ent->start_block = dirh.start_block;
71+ ent->offset = dire->offset;
72+ ent->type = dire->type;
73+ ent->next = NULL;
74+ if(cur_ent == NULL)
75+ dir->dirs = ent;
76+ else
77+ cur_ent->next = ent;
78+ cur_ent = ent;
79 dir->dir_count ++;
80 bytes += dire->size + 1;
81 }
82diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
83index ac46d9d..e389f8d 100644
84--- a/squashfs-tools/unsquash-1234.c
85+++ b/squashfs-tools/unsquash-1234.c
86@@ -60,11 +60,15 @@ int check_name(char *name, int size)
87
88 void squashfs_closedir(struct dir *dir)
89 {
90- int i;
91+ struct dir_ent *ent = dir->dirs;
92
93- for(i = 0; i < dir->dir_count; i++)
94- free(dir->dirs[i].name);
95+ while(ent) {
96+ struct dir_ent *tmp = ent;
97+
98+ ent = ent->next;
99+ free(tmp->name);
100+ free(tmp);
101+ }
102
103- free(dir->dirs);
104 free(dir);
105 }
106diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
107index e847980..956f96f 100644
108--- a/squashfs-tools/unsquash-2.c
109+++ b/squashfs-tools/unsquash-2.c
110@@ -347,7 +347,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
111 long long start;
112 int bytes = 0;
113 int dir_count, size, res;
114- struct dir_ent *new_dir;
115+ struct dir_ent *ent, *cur_ent = NULL;
116 struct dir *dir;
117
118 TRACE("squashfs_opendir: inode start block %d, offset %d\n",
119@@ -360,7 +360,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
120 MEM_ERROR();
121
122 dir->dir_count = 0;
123- dir->cur_entry = 0;
124+ dir->cur_entry = NULL;
125 dir->mode = (*i)->mode;
126 dir->uid = (*i)->uid;
127 dir->guid = (*i)->gid;
128@@ -444,19 +444,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
129 "%d:%d, type %d\n", dire->name,
130 dirh.start_block, dire->offset, dire->type);
131
132- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
133- new_dir = realloc(dir->dirs, (dir->dir_count +
134- DIR_ENT_SIZE) * sizeof(struct dir_ent));
135- if(new_dir == NULL)
136- MEM_ERROR();
137- dir->dirs = new_dir;
138- }
139+ ent = malloc(sizeof(struct dir_ent));
140+ if(ent == NULL)
141+ MEM_ERROR();
142
143- dir->dirs[dir->dir_count].name = strdup(dire->name);
144- dir->dirs[dir->dir_count].start_block =
145- dirh.start_block;
146- dir->dirs[dir->dir_count].offset = dire->offset;
147- dir->dirs[dir->dir_count].type = dire->type;
148+ ent->name = strdup(dire->name);
149+ ent->start_block = dirh.start_block;
150+ ent->offset = dire->offset;
151+ ent->type = dire->type;
152+ ent->next = NULL;
153+ if(cur_ent == NULL)
154+ dir->dirs = ent;
155+ else
156+ cur_ent->next = ent;
157+ cur_ent = ent;
158 dir->dir_count ++;
159 bytes += dire->size + 1;
160 }
161diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
162index 8223f27..835a574 100644
163--- a/squashfs-tools/unsquash-3.c
164+++ b/squashfs-tools/unsquash-3.c
165@@ -381,7 +381,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
166 long long start;
167 int bytes = 0;
168 int dir_count, size, res;
169- struct dir_ent *new_dir;
170+ struct dir_ent *ent, *cur_ent = NULL;
171 struct dir *dir;
172
173 TRACE("squashfs_opendir: inode start block %d, offset %d\n",
174@@ -394,7 +394,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
175 MEM_ERROR();
176
177 dir->dir_count = 0;
178- dir->cur_entry = 0;
179+ dir->cur_entry = NULL;
180 dir->mode = (*i)->mode;
181 dir->uid = (*i)->uid;
182 dir->guid = (*i)->gid;
183@@ -478,19 +478,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
184 "%d:%d, type %d\n", dire->name,
185 dirh.start_block, dire->offset, dire->type);
186
187- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
188- new_dir = realloc(dir->dirs, (dir->dir_count +
189- DIR_ENT_SIZE) * sizeof(struct dir_ent));
190- if(new_dir == NULL)
191- MEM_ERROR();
192- dir->dirs = new_dir;
193- }
194+ ent = malloc(sizeof(struct dir_ent));
195+ if(ent == NULL)
196+ MEM_ERROR();
197
198- dir->dirs[dir->dir_count].name = strdup(dire->name);
199- dir->dirs[dir->dir_count].start_block =
200- dirh.start_block;
201- dir->dirs[dir->dir_count].offset = dire->offset;
202- dir->dirs[dir->dir_count].type = dire->type;
203+ ent->name = strdup(dire->name);
204+ ent->start_block = dirh.start_block;
205+ ent->offset = dire->offset;
206+ ent->type = dire->type;
207+ ent->next = NULL;
208+ if(cur_ent == NULL)
209+ dir->dirs = ent;
210+ else
211+ cur_ent->next = ent;
212+ cur_ent = ent;
213 dir->dir_count ++;
214 bytes += dire->size + 1;
215 }
216diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
217index 1e199a7..694783d 100644
218--- a/squashfs-tools/unsquash-4.c
219+++ b/squashfs-tools/unsquash-4.c
220@@ -331,7 +331,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
221 struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
222 long long start;
223 int bytes = 0, dir_count, size, res;
224- struct dir_ent *new_dir;
225+ struct dir_ent *ent, *cur_ent = NULL;
226 struct dir *dir;
227
228 TRACE("squashfs_opendir: inode start block %d, offset %d\n",
229@@ -344,7 +344,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
230 MEM_ERROR();
231
232 dir->dir_count = 0;
233- dir->cur_entry = 0;
234+ dir->cur_entry = NULL;
235 dir->mode = (*i)->mode;
236 dir->uid = (*i)->uid;
237 dir->guid = (*i)->gid;
238@@ -415,19 +415,20 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
239 "%d:%d, type %d\n", dire->name,
240 dirh.start_block, dire->offset, dire->type);
241
242- if((dir->dir_count % DIR_ENT_SIZE) == 0) {
243- new_dir = realloc(dir->dirs, (dir->dir_count +
244- DIR_ENT_SIZE) * sizeof(struct dir_ent));
245- if(new_dir == NULL)
246- MEM_ERROR();
247- dir->dirs = new_dir;
248- }
249+ ent = malloc(sizeof(struct dir_ent));
250+ if(ent == NULL)
251+ MEM_ERROR();
252
253- dir->dirs[dir->dir_count].name = strdup(dire->name);
254- dir->dirs[dir->dir_count].start_block =
255- dirh.start_block;
256- dir->dirs[dir->dir_count].offset = dire->offset;
257- dir->dirs[dir->dir_count].type = dire->type;
258+ ent->name = strdup(dire->name);
259+ ent->start_block = dirh.start_block;
260+ ent->offset = dire->offset;
261+ ent->type = dire->type;
262+ ent->next = NULL;
263+ if(cur_ent == NULL)
264+ dir->dirs = ent;
265+ else
266+ cur_ent->next = ent;
267+ cur_ent = ent;
268 dir->dir_count ++;
269 bytes += dire->size + 1;
270 }
271diff --git a/squashfs-tools/unsquashfs.c b/squashfs-tools/unsquashfs.c
272index 04be53c..fee28ec 100644
273--- a/squashfs-tools/unsquashfs.c
274+++ b/squashfs-tools/unsquashfs.c
275@@ -1337,14 +1337,18 @@ failed:
276 int squashfs_readdir(struct dir *dir, char **name, unsigned int *start_block,
277 unsigned int *offset, unsigned int *type)
278 {
279- if(dir->cur_entry == dir->dir_count)
280+ if(dir->cur_entry == NULL)
281+ dir->cur_entry = dir->dirs;
282+ else
283+ dir->cur_entry = dir->cur_entry->next;
284+
285+ if(dir->cur_entry == NULL)
286 return FALSE;
287
288- *name = dir->dirs[dir->cur_entry].name;
289- *start_block = dir->dirs[dir->cur_entry].start_block;
290- *offset = dir->dirs[dir->cur_entry].offset;
291- *type = dir->dirs[dir->cur_entry].type;
292- dir->cur_entry ++;
293+ *name = dir->cur_entry->name;
294+ *start_block = dir->cur_entry->start_block;
295+ *offset = dir->cur_entry->offset;
296+ *type = dir->cur_entry->type;
297
298 return TRUE;
299 }
300diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
301index 583fbe4..f8cf78c 100644
302--- a/squashfs-tools/unsquashfs.h
303+++ b/squashfs-tools/unsquashfs.h
304@@ -168,17 +168,18 @@ struct dir_ent {
305 unsigned int start_block;
306 unsigned int offset;
307 unsigned int type;
308+ struct dir_ent *next;
309 };
310
311 struct dir {
312 int dir_count;
313- int cur_entry;
314 unsigned int mode;
315 uid_t uid;
316 gid_t guid;
317 unsigned int mtime;
318 unsigned int xattr;
319 struct dir_ent *dirs;
320+ struct dir_ent *cur_entry;
321 };
322
323 struct file_entry {
324--
3252.17.1
326
diff --git a/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072.patch b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072.patch
new file mode 100644
index 0000000000..94d6da4b14
--- /dev/null
+++ b/meta/recipes-devtools/squashfs-tools/squashfs-tools/CVE-2021-41072.patch
@@ -0,0 +1,325 @@
1CVE: CVE-2021-41072
2Upstream-Status: Backport [https://github.com/plougher/squashfs-tools/commit/e048580]
3
4Signed-off-by: Kai Kang <kai.kang@windriver.com>
5
6From e0485802ec72996c20026da320650d8362f555bd Mon Sep 17 00:00:00 2001
7From: Phillip Lougher <phillip@squashfs.org.uk>
8Date: Sun, 12 Sep 2021 23:50:06 +0100
9Subject: [PATCH] Unsquashfs: additional write outside destination directory
10 exploit fix
11
12An issue on github (https://github.com/plougher/squashfs-tools/issues/72)
13showed how some specially crafted Squashfs filesystems containing
14invalid file names (with '/' and '..') can cause Unsquashfs to write
15files outside of the destination directory.
16
17Since then it has been shown that specially crafted Squashfs filesystems
18that contain a symbolic link pointing outside of the destination directory,
19coupled with an identically named file within the same directory, can
20cause Unsquashfs to write files outside of the destination directory.
21
22Specifically the symbolic link produces a pathname pointing outside
23of the destination directory, which is then followed when writing the
24duplicate identically named file within the directory.
25
26This commit fixes this exploit by explictly checking for duplicate
27filenames within a directory. As directories in v2.1, v3.x, and v4.0
28filesystems are sorted, this is achieved by checking for consecutively
29identical filenames. Additionally directories are checked to
30ensure they are sorted, to avoid attempts to evade the duplicate
31check.
32
33Version 1.x and 2.0 filesystems (where the directories were unsorted)
34are sorted and then the above duplicate filename check is applied.
35
36Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
37---
38 squashfs-tools/Makefile | 6 +-
39 squashfs-tools/unsquash-1.c | 6 ++
40 squashfs-tools/unsquash-12.c | 110 +++++++++++++++++++++++++++++++++
41 squashfs-tools/unsquash-1234.c | 21 +++++++
42 squashfs-tools/unsquash-2.c | 16 +++++
43 squashfs-tools/unsquash-3.c | 6 ++
44 squashfs-tools/unsquash-4.c | 6 ++
45 squashfs-tools/unsquashfs.h | 4 ++
46 8 files changed, 173 insertions(+), 2 deletions(-)
47 create mode 100644 squashfs-tools/unsquash-12.c
48
49diff --git a/squashfs-tools/Makefile b/squashfs-tools/Makefile
50index 7262a2e..1b544ed 100755
51--- a/squashfs-tools/Makefile
52+++ b/squashfs-tools/Makefile
53@@ -160,8 +160,8 @@ MKSQUASHFS_OBJS = mksquashfs.o read_fs.o action.o swap.o pseudo.o compressor.o \
54 caches-queues-lists.o reader.o tar.o
55
56 UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \
57- unsquash-4.o unsquash-123.o unsquash-34.o unsquash-1234.o swap.o \
58- compressor.o unsquashfs_info.o
59+ unsquash-4.o unsquash-123.o unsquash-34.o unsquash-1234.o unsquash-12.o \
60+ swap.o compressor.o unsquashfs_info.o
61
62 CFLAGS ?= -O2
63 CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \
64@@ -393,6 +393,8 @@ unsquash-34.o: unsquashfs.h unsquash-34.c unsquashfs_error.h
65
66 unsquash-1234.o: unsquash-1234.c unsquashfs_error.h
67
68+unsquash-1234.o: unsquash-12.c
69+
70 unsquashfs_xattr.o: unsquashfs_xattr.c unsquashfs.h squashfs_fs.h xattr.h unsquashfs_error.h
71
72 unsquashfs_info.o: unsquashfs.h squashfs_fs.h unsquashfs_error.h
73diff --git a/squashfs-tools/unsquash-1.c b/squashfs-tools/unsquash-1.c
74index b604434..88866fc 100644
75--- a/squashfs-tools/unsquash-1.c
76+++ b/squashfs-tools/unsquash-1.c
77@@ -370,6 +370,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
78 }
79 }
80
81+ /* check directory for duplicate names. Need to sort directory first */
82+ sort_directory(dir);
83+ if(check_directory(dir) == FALSE) {
84+ ERROR("File system corrupted: directory has duplicate names\n");
85+ goto corrupted;
86+ }
87 return dir;
88
89 corrupted:
90diff --git a/squashfs-tools/unsquash-12.c b/squashfs-tools/unsquash-12.c
91new file mode 100644
92index 0000000..61bf128
93--- /dev/null
94+++ b/squashfs-tools/unsquash-12.c
95@@ -0,0 +1,110 @@
96+/*
97+ * Unsquash a squashfs filesystem. This is a highly compressed read only
98+ * filesystem.
99+ *
100+ * Copyright (c) 2021
101+ * Phillip Lougher <phillip@squashfs.org.uk>
102+ *
103+ * This program is free software; you can redistribute it and/or
104+ * modify it under the terms of the GNU General Public License
105+ * as published by the Free Software Foundation; either version 2,
106+ * or (at your option) any later version.
107+ *
108+ * This program is distributed in the hope that it will be useful,
109+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
110+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
111+ * GNU General Public License for more details.
112+ *
113+ * You should have received a copy of the GNU General Public License
114+ * along with this program; if not, write to the Free Software
115+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
116+ *
117+ * unsquash-12.c
118+ *
119+ * Helper functions used by unsquash-1 and unsquash-2.
120+ */
121+
122+#include "unsquashfs.h"
123+
124+/*
125+ * Bottom up linked list merge sort.
126+ *
127+ */
128+void sort_directory(struct dir *dir)
129+{
130+ struct dir_ent *cur, *l1, *l2, *next;
131+ int len1, len2, stride = 1;
132+
133+ if(dir->dir_count < 2)
134+ return;
135+
136+ /*
137+ * We can consider our linked-list to be made up of stride length
138+ * sublists. Eacn iteration around this loop merges adjacent
139+ * stride length sublists into larger 2*stride sublists. We stop
140+ * when stride becomes equal to the entire list.
141+ *
142+ * Initially stride = 1 (by definition a sublist of 1 is sorted), and
143+ * these 1 element sublists are merged into 2 element sublists, which
144+ * are then merged into 4 element sublists and so on.
145+ */
146+ do {
147+ l2 = dir->dirs; /* head of current linked list */
148+ cur = NULL; /* empty output list */
149+
150+ /*
151+ * Iterate through the linked list, merging adjacent sublists.
152+ * On each interation l2 points to the next sublist pair to be
153+ * merged (if there's only one sublist left this is simply added
154+ * to the output list)
155+ */
156+ while(l2) {
157+ l1 = l2;
158+ for(len1 = 0; l2 && len1 < stride; len1 ++, l2 = l2->next);
159+ len2 = stride;
160+
161+ /*
162+ * l1 points to first sublist.
163+ * l2 points to second sublist.
164+ * Merge them onto the output list
165+ */
166+ while(len1 && l2 && len2) {
167+ if(strcmp(l1->name, l2->name) <= 0) {
168+ next = l1;
169+ l1 = l1->next;
170+ len1 --;
171+ } else {
172+ next = l2;
173+ l2 = l2->next;
174+ len2 --;
175+ }
176+
177+ if(cur) {
178+ cur->next = next;
179+ cur = next;
180+ } else
181+ dir->dirs = cur = next;
182+ }
183+ /*
184+ * One sublist is now empty, copy the other one onto the
185+ * output list
186+ */
187+ for(; len1; len1 --, l1 = l1->next) {
188+ if(cur) {
189+ cur->next = l1;
190+ cur = l1;
191+ } else
192+ dir->dirs = cur = l1;
193+ }
194+ for(; l2 && len2; len2 --, l2 = l2->next) {
195+ if(cur) {
196+ cur->next = l2;
197+ cur = l2;
198+ } else
199+ dir->dirs = cur = l2;
200+ }
201+ }
202+ cur->next = NULL;
203+ stride = stride << 1;
204+ } while(stride < dir->dir_count);
205+}
206diff --git a/squashfs-tools/unsquash-1234.c b/squashfs-tools/unsquash-1234.c
207index e389f8d..98a81ed 100644
208--- a/squashfs-tools/unsquash-1234.c
209+++ b/squashfs-tools/unsquash-1234.c
210@@ -72,3 +72,24 @@ void squashfs_closedir(struct dir *dir)
211
212 free(dir);
213 }
214+
215+
216+/*
217+ * Check directory for duplicate names. As the directory should be sorted,
218+ * duplicates will be consecutive. Obviously we also need to check if the
219+ * directory has been deliberately unsorted, to evade this check.
220+ */
221+int check_directory(struct dir *dir)
222+{
223+ int i;
224+ struct dir_ent *ent;
225+
226+ if(dir->dir_count < 2)
227+ return TRUE;
228+
229+ for(ent = dir->dirs, i = 0; i < dir->dir_count - 1; ent = ent->next, i++)
230+ if(strcmp(ent->name, ent->next->name) >= 0)
231+ return FALSE;
232+
233+ return TRUE;
234+}
235diff --git a/squashfs-tools/unsquash-2.c b/squashfs-tools/unsquash-2.c
236index 956f96f..0e36f7d 100644
237--- a/squashfs-tools/unsquash-2.c
238+++ b/squashfs-tools/unsquash-2.c
239@@ -29,6 +29,7 @@
240 static squashfs_fragment_entry_2 *fragment_table;
241 static unsigned int *uid_table, *guid_table;
242 static squashfs_operations ops;
243+static int needs_sorting = FALSE;
244
245
246 static void read_block_list(unsigned int *block_list, long long start,
247@@ -463,6 +464,17 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
248 }
249 }
250
251+ if(needs_sorting)
252+ sort_directory(dir);
253+
254+ /* check directory for duplicate names and sorting */
255+ if(check_directory(dir) == FALSE) {
256+ if(needs_sorting)
257+ ERROR("File system corrupted: directory has duplicate names\n");
258+ else
259+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
260+ goto corrupted;
261+ }
262 return dir;
263
264 corrupted:
265@@ -596,6 +608,10 @@ int read_super_2(squashfs_operations **s_ops, void *s)
266 * 2.x filesystems use gzip compression.
267 */
268 comp = lookup_compressor("gzip");
269+
270+ if(sBlk_3->s_minor == 0)
271+ needs_sorting = TRUE;
272+
273 return TRUE;
274 }
275
276diff --git a/squashfs-tools/unsquash-3.c b/squashfs-tools/unsquash-3.c
277index 835a574..0123562 100644
278--- a/squashfs-tools/unsquash-3.c
279+++ b/squashfs-tools/unsquash-3.c
280@@ -497,6 +497,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
281 }
282 }
283
284+ /* check directory for duplicate names and sorting */
285+ if(check_directory(dir) == FALSE) {
286+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
287+ goto corrupted;
288+ }
289+
290 return dir;
291
292 corrupted:
293diff --git a/squashfs-tools/unsquash-4.c b/squashfs-tools/unsquash-4.c
294index 694783d..c615bb8 100644
295--- a/squashfs-tools/unsquash-4.c
296+++ b/squashfs-tools/unsquash-4.c
297@@ -434,6 +434,12 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
298 }
299 }
300
301+ /* check directory for duplicate names and sorting */
302+ if(check_directory(dir) == FALSE) {
303+ ERROR("File system corrupted: directory has duplicate names or is unsorted\n");
304+ goto corrupted;
305+ }
306+
307 return dir;
308
309 corrupted:
310diff --git a/squashfs-tools/unsquashfs.h b/squashfs-tools/unsquashfs.h
311index f8cf78c..bf2a80d 100644
312--- a/squashfs-tools/unsquashfs.h
313+++ b/squashfs-tools/unsquashfs.h
314@@ -293,4 +293,8 @@ extern long long *alloc_index_table(int);
315 /* unsquash-1234.c */
316 extern int check_name(char *, int);
317 extern void squashfs_closedir(struct dir *);
318+extern int check_directory(struct dir *);
319+
320+/* unsquash-12.c */
321+extern void sort_directory(struct dir *);
322 #endif
323--
3242.17.1
325
diff --git a/meta/recipes-devtools/squashfs-tools/squashfs-tools_git.bb b/meta/recipes-devtools/squashfs-tools/squashfs-tools_git.bb
index 24ac893d1e..6a19cba8f7 100644
--- a/meta/recipes-devtools/squashfs-tools/squashfs-tools_git.bb
+++ b/meta/recipes-devtools/squashfs-tools/squashfs-tools_git.bb
@@ -11,6 +11,10 @@ PV = "4.5"
11SRCREV = "0496d7c3de3e09da37ba492081c86159806ebb07" 11SRCREV = "0496d7c3de3e09da37ba492081c86159806ebb07"
12SRC_URI = "git://github.com/plougher/squashfs-tools.git;protocol=https;branch=master \ 12SRC_URI = "git://github.com/plougher/squashfs-tools.git;protocol=https;branch=master \
13 file://0001-Avoid-use-of-INSTALL_DIR-for-symlink-targets.patch \ 13 file://0001-Avoid-use-of-INSTALL_DIR-for-symlink-targets.patch \
14 file://CVE-2021-41072-requisite-1.patch;striplevel=2 \
15 file://CVE-2021-41072-requisite-2.patch;striplevel=2 \
16 file://CVE-2021-41072-requisite-3.patch;striplevel=2 \
17 file://CVE-2021-41072.patch;striplevel=2 \
14 " 18 "
15 19
16S = "${WORKDIR}/git/squashfs-tools" 20S = "${WORKDIR}/git/squashfs-tools"