zipl/src: prevent NULL pointer deref when preparing qcow2 images for IPL

This fixes c0f02d2f6 which results in problems when preparing qcow2
images for IPL:

zipl -V --blsdir /tmp/tmp.kdPooQjoBh/boot//loader/entries/ --config /
Program terminated with signal SIGFPE, Arithmetic exception.

Don't use pointer to not initialized struct disk_info after failed
auto-detection of disk parameters. Make the check that the file
locates on the disk in the form of a separate procedure.

Reported-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Tested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Eduard Shishkin
2024-08-26 18:48:05 +02:00
committed by Jan Höppner
parent 41da0f0809
commit 0e4992da3a

View File

@@ -298,6 +298,47 @@ create_component_header(void* buffer, component_header_type type)
header->type = (uint8_t) type;
}
/*
* Not precise check that the file FILENAME locates on specified physical DISK.
*
* Try to auto-detect parameters of the disk which the file locates on
* and compare found device-ID with DISK.
* Return 0, if auto-detection succeeded, and it is proven that the
* file does NOT locate on DISK. Otherwise, return 1.
*/
static int file_is_on_disk(const char *filename, dev_t disk)
{
/*
* Retrieve info of the underlying disk without any user hints
*/
struct job_target_data tmp = {.source = source_unknown};
struct disk_info *info;
int rc;
rc = disk_get_info_from_file(filename, &tmp, &info);
free_target_data(&tmp);
if (rc) {
/*
* In some cases it is impossible to auto-detect
* disk parameters (e.g. when the file is on a
* mounted qcow2 image).
* Skip the check with warnings.
*/
fprintf(stderr,
"Warning: Could not auto-detect disk parameters for %s\n",
filename);
fprintf(stderr,
"Warning: Preparing a logical device for boot might fail\n");
return 1;
}
if (info->device != disk) {
disk_free_info(info);
return 0;
}
disk_free_info(info);
return 1;
}
static int add_component_file_range(struct install_set *bis,
const char *filename,
struct file_range *reg,
@@ -311,7 +352,6 @@ static int add_component_file_range(struct install_set *bis,
struct component_loc *location = &pc->loc;
disk_blockptr_t **list = &pc->list;
blocknum_t *count = &pc->count;
struct disk_info* file_info;
disk_blockptr_t segment;
char* buffer;
size_t size;
@@ -338,36 +378,13 @@ static int add_component_file_range(struct install_set *bis,
return -1;
}
} else {
/*
* Make sure that file is on target device.
* For this, retrieve info of the underlying disk without
* any user hints
*/
struct job_target_data tmp = {.source = source_unknown};
rc = disk_get_info_from_file(filename, &tmp, &file_info);
free_target_data(&tmp);
if (rc) {
/*
* In some cases it is impossible to auto-detect
* disk parameters (e.g. when the file is on a
* mounted qcow2 image).
* Skip the check with warnings.
*/
fprintf(stderr,
"Warning: Could not auto-detect disk parameters for %s\n",
filename);
fprintf(stderr,
"Warning: Preparing a logical device for boot might fail\n");
} else if (file_info->device != bis->info->device) {
disk_free_info(file_info);
if (!file_is_on_disk(filename, bis->info->device)) {
error_reason("File is not on target device");
return -1;
}
/* Get block list from existing file */
*count = disk_get_blocklist_from_file(filename, reg,
list, file_info);
disk_free_info(file_info);
list, bis->info);
if (*count == 0)
return -1;
*count -= DIV_ROUND_UP(trailer, bis->info->phy_block_size);