summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHongxu Jia <hongxu.jia@windriver.com>2025-02-19 16:18:17 +0800
committerSteve Sakoman <steve@sakoman.com>2025-02-28 06:51:35 -0800
commit86f0ab4d07f2948abda527d7361b3819676ea41f (patch)
treec80ec3e2825a294f9812b129442deacacf985fe3
parentc54a2f894e1195bba6cd75358a729a2f4ec93398 (diff)
downloadpoky-86f0ab4d07f2948abda527d7361b3819676ea41f.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: 5ed8ad78bcce836aa8894de7a1d7fdf719e5bbca) 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.patch228
-rw-r--r--meta/recipes-bsp/u-boot/u-boot_2022.01.bb1
2 files changed, 229 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..5b6cbb8cad
--- /dev/null
+++ b/meta/recipes-bsp/u-boot/files/CVE-2024-57257.patch
@@ -0,0 +1,228 @@
1From 790a2005e7a44dba059f5dbf1b9eff3a13e9b5e7 Mon Sep 17 00:00:00 2001
2From: Hongxu Jia <hongxu.jia@windriver.com>
3Date: Wed, 19 Feb 2025 15:51:53 +0800
4Subject: [PATCH] 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]
17
18Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
19---
20 fs/squashfs/sqfs.c | 76 +++++++++++++++++++++++++++++++++++++---------
21 1 file changed, 61 insertions(+), 15 deletions(-)
22
23diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
24index 7f2af8e1f9..09c0911689 100644
25--- a/fs/squashfs/sqfs.c
26+++ b/fs/squashfs/sqfs.c
27@@ -24,7 +24,12 @@
28 #include "sqfs_filesystem.h"
29 #include "sqfs_utils.h"
30
31+#define MAX_SYMLINK_NEST 8
32+
33 static struct squashfs_ctxt ctxt;
34+static int symlinknest;
35+
36+static int sqfs_readdir_nest(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp);
37
38 static int sqfs_disk_read(__u32 block, __u32 nr_blocks, void *buf)
39 {
40@@ -502,7 +507,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
41 goto out;
42 }
43
44- while (!sqfs_readdir(dirsp, &dent)) {
45+ while (!sqfs_readdir_nest(dirsp, &dent)) {
46 ret = strcmp(dent->name, token_list[j]);
47 if (!ret)
48 break;
49@@ -527,6 +532,11 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
50
51 /* Check for symbolic link and inode type sanity */
52 if (get_unaligned_le16(&dir->inode_type) == SQFS_SYMLINK_TYPE) {
53+ if (++symlinknest == MAX_SYMLINK_NEST) {
54+ ret = -ELOOP;
55+ goto out;
56+ }
57+
58 sym = (struct squashfs_symlink_inode *)table;
59 /* Get first j + 1 tokens */
60 path = sqfs_concat_tokens(token_list, j + 1);
61@@ -872,7 +882,7 @@ out:
62 return metablks_count;
63 }
64
65-int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
66+static int sqfs_opendir_nest(const char *filename, struct fs_dir_stream **dirsp)
67 {
68 unsigned char *inode_table = NULL, *dir_table = NULL;
69 int j, token_count = 0, ret = 0, metablks_count;
70@@ -967,7 +977,19 @@ out:
71 return ret;
72 }
73
74+int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp)
75+{
76+ symlinknest = 0;
77+ return sqfs_opendir_nest(filename, dirsp);
78+}
79+
80 int sqfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
81+{
82+ symlinknest = 0;
83+ return sqfs_readdir_nest(fs_dirs, dentp);
84+}
85+
86+static int sqfs_readdir_nest(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
87 {
88 struct squashfs_super_block *sblk = ctxt.sblk;
89 struct squashfs_dir_stream *dirs;
90@@ -1311,8 +1333,8 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
91 return datablk_count;
92 }
93
94-int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
95- loff_t *actread)
96+static int sqfs_read_nest(const char *filename, void *buf, loff_t offset,
97+ loff_t len, loff_t *actread)
98 {
99 char *dir = NULL, *fragment_block, *datablock = NULL, *data_buffer = NULL;
100 char *fragment = NULL, *file = NULL, *resolved, *data;
101@@ -1342,11 +1364,11 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
102 }
103
104 /*
105- * sqfs_opendir will uncompress inode and directory tables, and will
106+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
107 * return a pointer to the directory that contains the requested file.
108 */
109 sqfs_split_path(&file, &dir, filename);
110- ret = sqfs_opendir(dir, &dirsp);
111+ ret = sqfs_opendir_nest(dir, &dirsp);
112 if (ret) {
113 goto out;
114 }
115@@ -1354,7 +1376,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
116 dirs = (struct squashfs_dir_stream *)dirsp;
117
118 /* For now, only regular files are able to be loaded */
119- while (!sqfs_readdir(dirsp, &dent)) {
120+ while (!sqfs_readdir_nest(dirsp, &dent)) {
121 ret = strcmp(dent->name, file);
122 if (!ret)
123 break;
124@@ -1403,9 +1425,14 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
125 break;
126 case SQFS_SYMLINK_TYPE:
127 case SQFS_LSYMLINK_TYPE:
128+ if (++symlinknest == MAX_SYMLINK_NEST) {
129+ ret = -ELOOP;
130+ goto out;
131+ }
132+
133 symlink = (struct squashfs_symlink_inode *)ipos;
134 resolved = sqfs_resolve_symlink(symlink, filename);
135- ret = sqfs_read(resolved, buf, offset, len, actread);
136+ ret = sqfs_read_nest(resolved, buf, offset, len, actread);
137 free(resolved);
138 goto out;
139 case SQFS_BLKDEV_TYPE:
140@@ -1579,7 +1606,14 @@ out:
141 return ret;
142 }
143
144-int sqfs_size(const char *filename, loff_t *size)
145+int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
146+ loff_t *actread)
147+{
148+ symlinknest = 0;
149+ return sqfs_read_nest(filename, buf, offset, len, actread);
150+}
151+
152+static int sqfs_size_nest(const char *filename, loff_t *size)
153 {
154 struct squashfs_super_block *sblk = ctxt.sblk;
155 struct squashfs_symlink_inode *symlink;
156@@ -1595,10 +1629,10 @@ int sqfs_size(const char *filename, loff_t *size)
157
158 sqfs_split_path(&file, &dir, filename);
159 /*
160- * sqfs_opendir will uncompress inode and directory tables, and will
161+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
162 * return a pointer to the directory that contains the requested file.
163 */
164- ret = sqfs_opendir(dir, &dirsp);
165+ ret = sqfs_opendir_nest(dir, &dirsp);
166 if (ret) {
167 ret = -EINVAL;
168 goto free_strings;
169@@ -1606,7 +1640,7 @@ int sqfs_size(const char *filename, loff_t *size)
170
171 dirs = (struct squashfs_dir_stream *)dirsp;
172
173- while (!sqfs_readdir(dirsp, &dent)) {
174+ while (!sqfs_readdir_nest(dirsp, &dent)) {
175 ret = strcmp(dent->name, file);
176 if (!ret)
177 break;
178@@ -1639,6 +1673,11 @@ int sqfs_size(const char *filename, loff_t *size)
179 break;
180 case SQFS_SYMLINK_TYPE:
181 case SQFS_LSYMLINK_TYPE:
182+ if (++symlinknest == MAX_SYMLINK_NEST) {
183+ *size = 0;
184+ return -ELOOP;
185+ }
186+
187 symlink = (struct squashfs_symlink_inode *)ipos;
188 resolved = sqfs_resolve_symlink(symlink, filename);
189 ret = sqfs_size(resolved, size);
190@@ -1678,10 +1717,11 @@ int sqfs_exists(const char *filename)
191
192 sqfs_split_path(&file, &dir, filename);
193 /*
194- * sqfs_opendir will uncompress inode and directory tables, and will
195+ * sqfs_opendir_nest will uncompress inode and directory tables, and will
196 * return a pointer to the directory that contains the requested file.
197 */
198- ret = sqfs_opendir(dir, &dirsp);
199+ symlinknest = 0;
200+ ret = sqfs_opendir_nest(dir, &dirsp);
201 if (ret) {
202 ret = -EINVAL;
203 goto free_strings;
204@@ -1689,7 +1729,7 @@ int sqfs_exists(const char *filename)
205
206 dirs = (struct squashfs_dir_stream *)dirsp;
207
208- while (!sqfs_readdir(dirsp, &dent)) {
209+ while (!sqfs_readdir_nest(dirsp, &dent)) {
210 ret = strcmp(dent->name, file);
211 if (!ret)
212 break;
213@@ -1706,6 +1746,12 @@ free_strings:
214 return ret == 0;
215 }
216
217+int sqfs_size(const char *filename, loff_t *size)
218+{
219+ symlinknest = 0;
220+ return sqfs_size_nest(filename, size);
221+}
222+
223 void sqfs_close(void)
224 {
225 sqfs_decompressor_cleanup(&ctxt);
226--
2272.34.1
228
diff --git a/meta/recipes-bsp/u-boot/u-boot_2022.01.bb b/meta/recipes-bsp/u-boot/u-boot_2022.01.bb
index c643fb35f3..c68e3e442f 100644
--- a/meta/recipes-bsp/u-boot/u-boot_2022.01.bb
+++ b/meta/recipes-bsp/u-boot/u-boot_2022.01.bb
@@ -14,6 +14,7 @@ SRC_URI += " file://0001-riscv32-Use-double-float-ABI-for-rv32.patch \
14 file://CVE-2024-57254.patch \ 14 file://CVE-2024-57254.patch \
15 file://CVE-2024-57255.patch \ 15 file://CVE-2024-57255.patch \
16 file://CVE-2024-57256.patch \ 16 file://CVE-2024-57256.patch \
17 file://CVE-2024-57257.patch \
17 " 18 "
18 19
19DEPENDS += "bc-native dtc-native python3-setuptools-native" 20DEPENDS += "bc-native dtc-native python3-setuptools-native"