Files
s390-tools/zdump/dfi_ngdump.c
Alexander Egorenkov 1f68c1aaf3 zdump/ngdump: Perform sanity checks on path to dump image
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 <egorenar@linux.ibm.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2026-07-20 15:25:59 +02:00

151 lines
2.8 KiB
C

/*
* zgetdump - Tool for copying and converting System z dumps
*
* NGDump dump input format
*
* Copyright IBM Corp. 2021
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <err.h>
#include <sys/mount.h>
#include "lib/util_libc.h"
#include "zgetdump.h"
#include "zg.h"
#include "dfi.h"
#include "ngdump.h"
/*
* File local static data
*/
static struct {
char *device;
char *mount_point;
struct ngdump_meta meta;
} l;
static int open_dump_file(void)
{
char *mount_point = NULL;
char *filename = NULL;
int rc;
mount_point = util_strdup("/tmp/zdump-ngdump-XXXXXX");
/* Create a mount point directory */
if (mkdtemp(mount_point) == NULL) {
warnx("Could not create directory \"%s\"", mount_point);
goto fail_free;
}
if (mount(l.device, mount_point, NGDUMP_FSTYPE, MS_RDONLY, NULL)) {
warnx("Could not mount \"%s\" (%s)", l.device, strerror(errno));
goto fail_rmdir;
}
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);
if (!g.fh)
goto fail_umount;
l.mount_point = mount_point;
return 0;
fail_umount:
umount(mount_point);
fail_rmdir:
rmdir(mount_point);
fail_free:
free(mount_point);
return -1;
}
static void cleanup(void)
{
if (l.mount_point) {
zg_close(g.fh);
g.fh = NULL;
umount(l.mount_point);
rmdir(l.mount_point);
free(l.mount_point);
l.mount_point = NULL;
}
if (l.device) {
g.fh = zg_open(l.device, O_RDONLY, ZG_CHECK);
free(l.device);
l.device = NULL;
}
}
static int dfi_ngdump_init(void)
{
/*
* Copy path to the dump partition and close its file descriptor
* because we don't read raw partitions with NGDump but use a
* file system instead.
*/
l.device = util_strdup(g.fh->path);
zg_close(g.fh);
g.fh = NULL;
/*
* First, we need to read information contained in the meta-data
* file because it will tell us where a dump file on the file system
* is located.
*/
if (ngdump_read_meta_from_device(l.device, &l.meta)) {
cleanup();
return -1;
}
/* No dump made yet but partition is a valid NGDump partition. */
if (!l.meta.file) {
cleanup();
return -1;
}
/*
* Now we open the dump file and initialize the ELF DFI.
* After that, the control is passed to the ELF DFI.
*/
if (open_dump_file()) {
cleanup();
return -1;
}
if (dfi_elf.init()) {
cleanup();
return -1;
}
return 0;
}
static void dfi_ngdump_exit(void)
{
if (dfi_elf.exit)
dfi_elf.exit();
cleanup();
}
/*
* NGDump DFI operations
*/
struct dfi dfi_ngdump = {
.name = "elf",
.init = dfi_ngdump_init,
.exit = dfi_ngdump_exit,
.feat_bits = DFI_FEAT_COPY | DFI_FEAT_SEEK,
};