From 1f68c1aaf357ccc4302a581b8fee09361eb3278b Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Wed, 1 Jul 2026 10:23:47 +0200 Subject: [PATCH] zdump/ngdump: Perform sanity checks on path to dump image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure that the path to a dump image specified in the NGDump meta file of a dump device points to a valid location within the dump device. Especially, disallow escaping from a dump device with a dump image path using references to '..' or symbolic links pointing outside of the dump device. Signed-off-by: Alexander Egorenkov Reviewed-by: Ilya Leoshkevich Signed-off-by: Jan Höppner --- zdump/dfi_ngdump.c | 7 ++++++- zdump/ngdump.c | 48 +++++++++++++++++++++++++++++++++++++++++----- zdump/ngdump.h | 3 +++ 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/zdump/dfi_ngdump.c b/zdump/dfi_ngdump.c index 510ce0e6..b576d4d3 100644 --- a/zdump/dfi_ngdump.c +++ b/zdump/dfi_ngdump.c @@ -32,6 +32,7 @@ static int open_dump_file(void) { char *mount_point = NULL; char *filename = NULL; + int rc; mount_point = util_strdup("/tmp/zdump-ngdump-XXXXXX"); @@ -46,7 +47,11 @@ static int open_dump_file(void) goto fail_rmdir; } - util_asprintf(&filename, "%s/%s", mount_point, l.meta.file); + rc = ngdump_get_dump_path(mount_point, &l.meta, &filename); + if (rc) { + warnx("Could not resolve path to dump file \"%s\"", l.meta.file); + goto fail_rmdir; + } g.fh = zg_open(filename, O_RDONLY, ZG_CHECK); free(filename); diff --git a/zdump/ngdump.c b/zdump/ngdump.c index 905dfb2c..d97ba947 100644 --- a/zdump/ngdump.c +++ b/zdump/ngdump.c @@ -223,12 +223,10 @@ static int validate_meta(const char *mount_point, struct ngdump_meta *meta) return -1; } - util_asprintf(&filename, "%s/%s", mount_point, meta->file); - - rc = access(filename, R_OK); + rc = ngdump_get_dump_path(mount_point, meta, &filename); if (rc) { - warnx("Could not access dump file \"%s\"", meta->file); - goto out; + warnx("Could not resolve path to dump file \"%s\"", meta->file); + return -1; } rc = check_sha256sum(filename, meta->sha256sum); @@ -608,3 +606,43 @@ int ngdump_get_dump_part(struct zg_fh *zg_fh, char **part_path) return part_num; } + +int ngdump_get_dump_path(const char *mount_point, + const struct ngdump_meta *meta, + char **path) + +{ + char *filename = NULL; + char *real_path; + int rc; + + util_asprintf(&filename, "%s/%s", mount_point, meta->file); + + util_log_print(UTIL_LOG_DEBUG, "%s: Dump path %s\n", + __func__, filename); + + real_path = realpath(filename, NULL); + free(filename); + if (!real_path) + return -1; + + util_log_print(UTIL_LOG_DEBUG, "%s: Real dump path %s\n", + __func__, real_path); + + /* Disallow escaping from a dump device with a relative path or + symbolic link. */ + if (strncmp(mount_point, real_path, strlen(mount_point)) != 0) + goto fail_free_real_path; + + rc = access(real_path, R_OK); + if (rc) + goto fail_free_real_path; + + *path = real_path; + + return 0; + +fail_free_real_path: + free(real_path); + return -1; +} diff --git a/zdump/ngdump.h b/zdump/ngdump.h index 1e6846e7..58dddc3a 100644 --- a/zdump/ngdump.h +++ b/zdump/ngdump.h @@ -31,5 +31,8 @@ int ngdump_read_meta_from_device(const char *device, struct ngdump_meta *meta); int ngdump_get_dump_part(struct zg_fh *zg_fh, char **part_path); int ngdump_get_part_path(const char *disk_path, int part_num, enum ngdump_disk_type ng_type, char **part_path); +int ngdump_get_dump_path(const char *mount_point, + const struct ngdump_meta *meta, + char **path); #endif /* ZGETDUMP_NGDUMP_H */