blob: 5d5df6f15be2e56bb682213df24e26b2375dc05e [file] [log] [blame]
Andrew Geissler595f6302022-01-24 19:11:47 +00001The 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