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