From 7a216a1fd02d73473455d72dd8e41abae848c829 Mon Sep 17 00:00:00 2001
From: Roman Fietze <
roman.fi...@vaillant-group.com>
Date: Tue, 17 Mar 2026 13:45:02 +0100
Subject: [PATCH] core: check for valid filenames
Fixes CVE-2023-7216.
Signed-off-by: Roman Fietze <
roman....@magna.com>
---
core/stream_interface.c | 10 ++++++++++
core/util.c | 7 +++++++
include/util.h | 1 +
test/test_util.c | 13 ++++++++++++-
4 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/core/stream_interface.c b/core/stream_interface.c
index a0c73470..06f5cc40 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -121,6 +121,11 @@ static int extract_file_to_tmp(int fd, const char *fname, unsigned long *poffs,
fdh.filename, fdh.size, max_size);
goto err;
}
+
if (!is_filename_valid(fdh.filename)) {
+
ERROR("%s is an invalid filename, aborting", fdh.filename);
+
return -1;
+
}
+
TRACE("Found file");
TRACE("\tfilename %s", fdh.filename);
TRACE("\tsize %u", (unsigned int)fdh.size);
@@ -261,6 +266,11 @@ static int extract_files(int fd, struct swupdate_cfg *software)
break;
}
+
if (!is_filename_valid(fdh.filename)) {
+
ERROR("%s is an invalid filename, aborting", fdh.filename);
+
return -1;
+
}
+
TRACE("Found file");
TRACE("\tfilename %s", fdh.filename);
TRACE("\tsize %u %s", (unsigned int)fdh.size,
diff --git a/core/util.c b/core/util.c
index 3f62e070..5b397c4f 100644
--- a/core/util.c
+++ b/core/util.c
@@ -1282,3 +1282,10 @@ bool check_same_file(int fd1, int fd2) {
if(fstat(fd2, &stat2) < 0) return false;
return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
}
+
+
+bool
+is_filename_valid (const char *file_name)
+{
+ return file_name != NULL && file_name[0] != '/' && strstr(file_name, "../") == NULL;
+}
diff --git a/include/util.h b/include/util.h
index d4874f64..a29495c4 100644
--- a/include/util.h
+++ b/include/util.h
@@ -285,6 +285,7 @@ int read_lines_notify(int fd, char *buf, int buf_size, int *buf_offset,
long long get_output_size(struct img_type *img, bool strict);
bool img_check_free_space(struct img_type *img, int fd);
bool check_same_file(int fd1, int fd2);
+bool is_filename_valid (const char *file_name);
/* location for libubootenv configuration file */
const char *get_fwenv_config(void);
diff --git a/test/test_util.c b/test/test_util.c
index d6f2c0a0..ef7708c8 100644
--- a/test/test_util.c
+++ b/test/test_util.c
@@ -39,12 +39,23 @@ static void test_util_ustrtoull(void **state)
assert_string_equal(suffix, ", some fancy things");
}
+static void test_util_is_filename_valid(void **state)
+{
+ (void)state;
+ assert_true(is_filename_valid("a.swu"));
+ assert_true(is_filename_valid( "sub/d.swu"));
+ assert_false(is_filename_valid("/c.swu"));
+ assert_false(is_filename_valid("../b.swu"));
+ assert_false(is_filename_valid("sub/../e.swu"));
+}
+
int main(void)
{
int error_count = 0;
const struct CMUnitTest util_tests[] = {
cmocka_unit_test(test_util_ustrtoull),
-
cmocka_unit_test(test_util_size_delimiter_match)
+
cmocka_unit_test(test_util_size_delimiter_match),
+
cmocka_unit_test(test_util_is_filename_valid)
};
error_count += cmocka_run_group_tests_name("util", util_tests,
util_setup, util_teardown);
--
2.51.0