From e8e2f417c96a74e9dce56ed8ab9e9165e739aba2 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 25 Nov 2021 10:49:50 +0100 Subject: [PATCH] daemon/mkfs: disable creation of fake MBR partition table with "mkfs.fat" Search the usage output of "mkfs.fat" for "--mbr[="; cache the result for further invocations. If the option is supported, pass "--mbr=n" to "mkfs.fat". This will prevent the creation of a bogus partition table whose first (and only) entry describes a partition that contains the partition table. (Such a bogus partition table breaks "parted", which is a tool used by libguestfs extensively, both internally and in public libguestfs APIs.) Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1931821 Signed-off-by: Laszlo Ersek Acked-by: Richard W.M. Jones Message-Id: <20211125094954.9713-2-lersek@redhat.com> --- daemon/mkfs.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/daemon/mkfs.c b/daemon/mkfs.c index ba90cef21..4cb216cab 100644 --- a/daemon/mkfs.c +++ b/daemon/mkfs.c @@ -30,6 +30,14 @@ #define MAX_ARGS 64 +enum fat_mbr_option { + FMO_UNCHECKED, + FMO_DOESNT_EXIST, + FMO_EXISTS, +}; + +static enum fat_mbr_option fat_mbr_option = FMO_UNCHECKED; + /* Takes optional arguments, consult optargs_bitmask. */ int do_mkfs (const char *fstype, const char *device, int blocksize, @@ -101,6 +109,25 @@ do_mkfs (const char *fstype, const char *device, int blocksize, STREQ (fstype, "msdos")) ADD_ARG (argv, i, "-I"); + /* Prevent mkfs.fat from creating a bogus partition table (RHBZ#1931821). */ + if (STREQ (fstype, "fat") || STREQ (fstype, "vfat") || + STREQ (fstype, "msdos")) { + if (fat_mbr_option == FMO_UNCHECKED) { + CLEANUP_FREE char *usage_err = NULL; + + fat_mbr_option = FMO_DOESNT_EXIST; + /* Invoking either version 3 of version 4 of mkfs.fat without any options + * will make it (a) print a usage summary to stderr, (b) exit with status + * 1. + */ + r = commandr (NULL, &usage_err, "mkfs.fat", (char *)NULL); + if (r == 1 && strstr (usage_err, "--mbr[=") != NULL) + fat_mbr_option = FMO_EXISTS; + } + if (fat_mbr_option == FMO_EXISTS) + ADD_ARG (argv, i, "--mbr=n"); + } + /* Process blocksize parameter if set. */ if (optargs_bitmask & GUESTFS_MKFS_BLOCKSIZE_BITMASK) { if (blocksize <= 0 || !is_power_of_2 (blocksize)) {