From eb852011ab3c56bd1f8e9d2c7d0dfb3eb321430a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 27 Oct 2009 18:41:44 +0100 Subject: [PATCH] Configurable block format whitelist We have code for a quite a few block formats. While I trust that all of these formats are useful at least for some people in some circumstances, some of them are of a kind that friends don't let friends use in production. This patch provides an optional block format whitelist, default off. If a whitelist is configured with --block-drv-whitelist, QEMU proper can use only whitelisted formats. Other programs, like qemu-img, are not affected. Drivers for formats off the whitelist still participate in format probing, to ensure all programs probe exactly the same. Without that, QEMU proper would be prone to treat images with a format off the whitelist as raw when the image's format is probed. Signed-off-by: Markus Armbruster Signed-off-by: Anthony Liguori --- block.c | 38 +++++++++++++++++++++++++++++++++++++- block.h | 2 ++ configure | 7 +++++++ create_config | 7 +++++++ hw/xen_disk.c | 3 ++- monitor.c | 2 +- vl.c | 4 ++-- 7 files changed, 58 insertions(+), 5 deletions(-) diff --git a/block.c b/block.c index 05c83115b..1e49bc05c 100644 --- a/block.c +++ b/block.c @@ -61,6 +61,9 @@ BlockDriverState *bdrv_first; static BlockDriver *first_drv; +/* If non-zero, use only whitelisted block drivers */ +static int use_bdrv_whitelist; + int path_is_absolute(const char *path) { const char *p; @@ -171,6 +174,30 @@ BlockDriver *bdrv_find_format(const char *format_name) return NULL; } +static int bdrv_is_whitelisted(BlockDriver *drv) +{ + static const char *whitelist[] = { + CONFIG_BDRV_WHITELIST + }; + const char **p; + + if (!whitelist[0]) + return 1; /* no whitelist, anything goes */ + + for (p = whitelist; *p; p++) { + if (!strcmp(drv->format_name, *p)) { + return 1; + } + } + return 0; +} + +BlockDriver *bdrv_find_whitelisted_format(const char *format_name) +{ + BlockDriver *drv = bdrv_find_format(format_name); + return drv && bdrv_is_whitelisted(drv) ? drv : NULL; +} + int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options) { @@ -427,7 +454,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO)); else open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); - ret = drv->bdrv_open(bs, filename, open_flags); + if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) + ret = -ENOTSUP; + else + ret = drv->bdrv_open(bs, filename, open_flags); if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) { ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR); bs->read_only = 1; @@ -1764,6 +1794,12 @@ void bdrv_init(void) module_call_init(MODULE_INIT_BLOCK); } +void bdrv_init_with_whitelist(void) +{ + use_bdrv_whitelist = 1; + bdrv_init(); +} + void *qemu_aio_get(AIOPool *pool, BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { diff --git a/block.h b/block.h index 302010d95..6b0146f7c 100644 --- a/block.h +++ b/block.h @@ -45,7 +45,9 @@ void bdrv_info(Monitor *mon); void bdrv_info_stats(Monitor *mon); void bdrv_init(void); +void bdrv_init_with_whitelist(void); BlockDriver *bdrv_find_format(const char *format_name); +BlockDriver *bdrv_find_whitelisted_format(const char *format_name); int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options); int bdrv_create2(BlockDriver *drv, diff --git a/configure b/configure index aa2cc4322..fb66246a7 100755 --- a/configure +++ b/configure @@ -38,6 +38,7 @@ cc="gcc" audio_drv_list="" audio_card_list="ac97 es1370 sb16" audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus" +block_drv_whitelist="" host_cc="gcc" ar="ar" make="make" @@ -430,6 +431,8 @@ for opt do ;; --audio-drv-list=*) audio_drv_list="$optarg" ;; + --block-drv-whitelist=*) block_drv_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` + ;; --enable-debug-tcg) debug_tcg="yes" ;; --disable-debug-tcg) debug_tcg="no" @@ -661,6 +664,8 @@ echo " --audio-drv-list=LIST set audio drivers list:" echo " Available drivers: $audio_possible_drivers" echo " --audio-card-list=LIST set list of emulated audio cards [$audio_card_list]" echo " Available cards: $audio_possible_cards" +echo " --block-drv-whitelist=L set block driver whitelist" +echo " (affects only QEMU, not qemu-img)" echo " --enable-mixemu enable mixer emulation" echo " --disable-xen disable xen backend driver support" echo " --enable-xen enable xen backend driver support" @@ -1826,6 +1831,7 @@ echo "check support $check_utests" echo "mingw32 support $mingw32" echo "Audio drivers $audio_drv_list" echo "Extra audio cards $audio_card_list" +echo "Block whitelist $block_drv_whitelist" echo "Mixer emulation $mixemu" echo "VNC TLS support $vnc_tls" echo "VNC SASL support $vnc_sasl" @@ -1948,6 +1954,7 @@ fi if test "$audio_win_int" = "yes" ; then echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak fi +echo "CONFIG_BDRV_WHITELIST=$block_drv_whitelist" >> $config_host_mak if test "$mixemu" = "yes" ; then echo "CONFIG_MIXEMU=y" >> $config_host_mak fi diff --git a/create_config b/create_config index 30d0487e2..2f052ae61 100755 --- a/create_config +++ b/create_config @@ -26,6 +26,13 @@ case $line in done echo "" ;; + CONFIG_BDRV_WHITELIST=*) + echo "#define CONFIG_BDRV_WHITELIST \\" + for drv in ${line#*=}; do + echo " \"${drv}\",\\" + done + echo " NULL" + ;; CONFIG_*=y) # configuration name=${line%=*} echo "#define $name 1" diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 74cde8069..5c5525132 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -630,7 +630,8 @@ static int blk_init(struct XenDevice *xendev) blkdev->bs = bdrv_new(blkdev->dev); if (blkdev->bs) { if (bdrv_open2(blkdev->bs, blkdev->filename, qflags, - bdrv_find_format(blkdev->fileproto)) != 0) { + bdrv_find_whitelisted_format(blkdev->fileproto)) + != 0) { bdrv_delete(blkdev->bs); blkdev->bs = NULL; } diff --git a/monitor.c b/monitor.c index 109ff5c44..132fb6e06 100644 --- a/monitor.c +++ b/monitor.c @@ -596,7 +596,7 @@ static void do_change_block(Monitor *mon, const char *device, return; } if (fmt) { - drv = bdrv_find_format(fmt); + drv = bdrv_find_whitelisted_format(fmt); if (!drv) { monitor_printf(mon, "invalid format %s\n", fmt); return; diff --git a/vl.c b/vl.c index 613cbdb63..402e78d98 100644 --- a/vl.c +++ b/vl.c @@ -2156,7 +2156,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque, fprintf(stderr, "\n"); return NULL; } - drv = bdrv_find_format(buf); + drv = bdrv_find_whitelisted_format(buf); if (!drv) { fprintf(stderr, "qemu: '%s' invalid format\n", buf); return NULL; @@ -5522,7 +5522,7 @@ int main(int argc, char **argv, char **envp) /* init the dynamic translator */ cpu_exec_init_all(tb_size * 1024 * 1024); - bdrv_init(); + bdrv_init_with_whitelist(); /* we always create the cdrom drive, even if no disk is there */ drive_add(NULL, CDROM_ALIAS); -- 2.39.2