summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHongxu Jia <hongxu.jia@windriver.com>2025-02-19 15:04:36 +0800
committerSteve Sakoman <steve@sakoman.com>2025-02-28 06:45:14 -0800
commit8c190b0e8e2e20889b3ddae0a3e9e16e77b78701 (patch)
tree78688c1d38d28138a7c429d45396b0183d290044
parent35f98c1ff33a18315fed1d649ce3982fb18c9d2c (diff)
downloadpoky-8c190b0e8e2e20889b3ddae0a3e9e16e77b78701.tar.gz
u-boot: fix CVE-2024-57257
A stack consumption issue in sqfs_size in Das U-Boot before 2025.01-rc1 occurs via a crafted squashfs filesystem with deep symlink nesting. https://nvd.nist.gov/vuln/detail/CVE-2024-57257 (From OE-Core rev: 890597539246c0f2b427d60965d5665cf7f4731c) Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-bsp/u-boot/files/CVE-2024-57257.patch227
-rw-r--r--meta/recipes-bsp/u-boot/u-boot-common.inc1
2 files changed, 228 insertions, 0 deletions
diff --git a/meta/recipes-bsp/u-boot/files/CVE-2024-57257.patch b/meta/recipes-bsp/u-boot/files/CVE-2024-57257.patch
new file mode 100644
index 0000000000..bfffcafa43
--- /dev/null
+++ b/meta/recipes-bsp/u-boot/files/CVE-2024-57257.patch
@@ -0,0 +1,227 @@
1From 4eb527c473068953f90ea65b33046a25140e0a89 Mon Sep 17 00:00:00 2001
2From: Richard Weinberger <richard@nod.at>
3Date: Fri, 2 Aug 2024 18:36:47 +0200
4Subject: [PATCH 4/8] squashfs: Fix stack overflow while symlink resolving
5
6The squashfs driver blindly follows symlinks, and calls sqfs_size()
7recursively. So an attacker can create a crafted filesystem and with
8a deep enough nesting level a stack overflow can be achieved.
9
10Fix by limiting the nesting level to 8.
11
12Signed-off-by: Richard Weinberger <richard@nod.at>
13Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
14
15CVE: CVE-2024-57257
16Upstream-Status: Backport [https://source.denx.de/u-boot/u-boot/-/commit/4f5cc096bfd0a591f8a11e86999e3d90a9484c34]
17Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
18---
19 fs/squashfs/sqfs.c | 76 +++++++++++++++++++++++++++++++++++++---------
20 1 file changed, 61 insertions(+), 15 deletions(-)
21
22diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
23index 16a07c06..a5b7890e 100644
24--- a/fs/squashfs/sqfs.c
25+++ b/fs/squashfs/sqfs.c
26@@ -24,7 +24,12 @@
27 #include "sqfs_filesystem.h"
28 #include "sqfs_utils.h"
29
30+#define MAX_SYMLINK_NEST 8
31+
32 static struct squashfs_ctxt ctxt;
33+static int symlinknest;
34+
35+static int sqfs_readdir_nest(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp);
36
37 static int sqfs_disk_read(__u32 block, __u32 nr_blocks, void *buf)
38 {
39@@ -508,7 +513,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
40 goto out;
41 }
42
43- while (!sqfs_readdir(dirsp, &dent)) {
44+ while (!sqfs_readdir_nest(dirsp, &dent)) {
45 ret = strcmp(dent->name, token_list[j]);
46 if (!ret)
47 break;
48@@ -533,6 +538,11 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
49
50 /* Check for symbolic link and inode type sanity */
51 if (get_unaligned_le16(&dir->inode_type) == SQFS_SYMLINK_TYPE) {
52+ if (++symlinknest == MAX_SYMLINK_NEST) {
53+ ret = -ELOOP;
54+ goto out;
55+ }
56+
57 sym = (struct squashfs_symlink_inode *)table;
58 /* Get first j + 1 tokens */
59 path = sqfs_concat_tokens(token_list, j + 1);
60@@ -880,7 +890,7 @@ out:
61 return metablks_count;
62 }
63
64-int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
65+static int sqfs_opendir_nest(const char *filename, struct fs_dir_stream **dirsp)
66 {
67 unsigned char *inode_table = NULL, *dir_table = NULL;
68 int j, token_count = 0, ret = 0, metablks_count;
69@@ -975,7 +985,19 @@ out:
70 return ret;
71 }
72
73+int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
74+{
75+ symlinknest = 0;
76+ return sqfs_opendir_nest(filename, dirsp);
77+}
78+
79 int sqfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
80+{
81+ symlinknest = 0;
82+ return sqfs_readdir_nest(fs_dirs, dentp);
83+}
84+
85+static int sqfs_readdir_nest(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
86 {
87 struct squashfs_super_block *sblk = ctxt.sblk;
88 struct squashfs_dir_stream *dirs;
89@@ -1319,8 +1341,8 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
90 return datablk_count;
91 }
92
93-int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
94- loff_t *actread)
95+static int sqfs_read_nest(const char *filename, void *buf, loff_t offset,
96+ loff_t len, loff_t *actread)
97 {
98 char *dir = NULL, *fragment_block, *datablock = NULL;
99 char *fragment = NULL, *file = NULL, *resolved, *data;
100@@ -1350,11 +1372,11 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
101 }
102
103 /*
104- * sqfs_opendir will uncompress inode and directory tables, and will
105+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
106 * return a pointer to the directory that contains the requested file.
107 */
108 sqfs_split_path(&file, &dir, filename);
109- ret = sqfs_opendir(dir, &dirsp);
110+ ret = sqfs_opendir_nest(dir, &dirsp);
111 if (ret) {
112 goto out;
113 }
114@@ -1362,7 +1384,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
115 dirs = (struct squashfs_dir_stream *)dirsp;
116
117 /* For now, only regular files are able to be loaded */
118- while (!sqfs_readdir(dirsp, &dent)) {
119+ while (!sqfs_readdir_nest(dirsp, &dent)) {
120 ret = strcmp(dent->name, file);
121 if (!ret)
122 break;
123@@ -1411,9 +1433,14 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
124 break;
125 case SQFS_SYMLINK_TYPE:
126 case SQFS_LSYMLINK_TYPE:
127+ if (++symlinknest == MAX_SYMLINK_NEST) {
128+ ret = -ELOOP;
129+ goto out;
130+ }
131+
132 symlink = (struct squashfs_symlink_inode *)ipos;
133 resolved = sqfs_resolve_symlink(symlink, filename);
134- ret = sqfs_read(resolved, buf, offset, len, actread);
135+ ret = sqfs_read_nest(resolved, buf, offset, len, actread);
136 free(resolved);
137 goto out;
138 case SQFS_BLKDEV_TYPE:
139@@ -1584,7 +1611,14 @@ out:
140 return ret;
141 }
142
143-int sqfs_size(const char *filename, loff_t *size)
144+int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
145+ loff_t *actread)
146+{
147+ symlinknest = 0;
148+ return sqfs_read_nest(filename, buf, offset, len, actread);
149+}
150+
151+static int sqfs_size_nest(const char *filename, loff_t *size)
152 {
153 struct squashfs_super_block *sblk = ctxt.sblk;
154 struct squashfs_symlink_inode *symlink;
155@@ -1600,10 +1634,10 @@ int sqfs_size(const char *filename, loff_t *size)
156
157 sqfs_split_path(&file, &dir, filename);
158 /*
159- * sqfs_opendir will uncompress inode and directory tables, and will
160+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
161 * return a pointer to the directory that contains the requested file.
162 */
163- ret = sqfs_opendir(dir, &dirsp);
164+ ret = sqfs_opendir_nest(dir, &dirsp);
165 if (ret) {
166 ret = -EINVAL;
167 goto free_strings;
168@@ -1611,7 +1645,7 @@ int sqfs_size(const char *filename, loff_t *size)
169
170 dirs = (struct squashfs_dir_stream *)dirsp;
171
172- while (!sqfs_readdir(dirsp, &dent)) {
173+ while (!sqfs_readdir_nest(dirsp, &dent)) {
174 ret = strcmp(dent->name, file);
175 if (!ret)
176 break;
177@@ -1644,6 +1678,11 @@ int sqfs_size(const char *filename, loff_t *size)
178 break;
179 case SQFS_SYMLINK_TYPE:
180 case SQFS_LSYMLINK_TYPE:
181+ if (++symlinknest == MAX_SYMLINK_NEST) {
182+ *size = 0;
183+ return -ELOOP;
184+ }
185+
186 symlink = (struct squashfs_symlink_inode *)ipos;
187 resolved = sqfs_resolve_symlink(symlink, filename);
188 ret = sqfs_size(resolved, size);
189@@ -1683,10 +1722,11 @@ int sqfs_exists(const char *filename)
190
191 sqfs_split_path(&file, &dir, filename);
192 /*
193- * sqfs_opendir will uncompress inode and directory tables, and will
194+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
195 * return a pointer to the directory that contains the requested file.
196 */
197- ret = sqfs_opendir(dir, &dirsp);
198+ symlinknest = 0;
199+ ret = sqfs_opendir_nest(dir, &dirsp);
200 if (ret) {
201 ret = -EINVAL;
202 goto free_strings;
203@@ -1694,7 +1734,7 @@ int sqfs_exists(const char *filename)
204
205 dirs = (struct squashfs_dir_stream *)dirsp;
206
207- while (!sqfs_readdir(dirsp, &dent)) {
208+ while (!sqfs_readdir_nest(dirsp, &dent)) {
209 ret = strcmp(dent->name, file);
210 if (!ret)
211 break;
212@@ -1711,6 +1751,12 @@ free_strings:
213 return ret == 0;
214 }
215
216+int sqfs_size(const char *filename, loff_t *size)
217+{
218+ symlinknest = 0;
219+ return sqfs_size_nest(filename, size);
220+}
221+
222 void sqfs_close(void)
223 {
224 sqfs_decompressor_cleanup(&ctxt);
225--
2262.34.1
227
diff --git a/meta/recipes-bsp/u-boot/u-boot-common.inc b/meta/recipes-bsp/u-boot/u-boot-common.inc
index 097ef685e9..ec3b4d8fdf 100644
--- a/meta/recipes-bsp/u-boot/u-boot-common.inc
+++ b/meta/recipes-bsp/u-boot/u-boot-common.inc
@@ -18,6 +18,7 @@ SRC_URI = "git://source.denx.de/u-boot/u-boot.git;protocol=https;branch=master \
18 file://CVE-2024-57254.patch \ 18 file://CVE-2024-57254.patch \
19 file://CVE-2024-57255.patch \ 19 file://CVE-2024-57255.patch \
20 file://CVE-2024-57256.patch \ 20 file://CVE-2024-57256.patch \
21 file://CVE-2024-57257.patch \
21" 22"
22 23
23S = "${WORKDIR}/git" 24S = "${WORKDIR}/git"