]> git.proxmox.com Git - qemu.git/commitdiff
Configurable block format whitelist
authorMarkus Armbruster <armbru@redhat.com>
Tue, 27 Oct 2009 17:41:44 +0000 (18:41 +0100)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 9 Nov 2009 14:43:02 +0000 (08:43 -0600)
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 <armbru@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
block.c
block.h
configure
create_config
hw/xen_disk.c
monitor.c
vl.c

diff --git a/block.c b/block.c
index 05c83115b3bdb9238ba67be8d2a095f4362484e7..1e49bc05cca4c4355eec6d05e8999c814033490a 100644 (file)
--- 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 302010d953ad68ac532e21d1302d700608d99d7b..6b0146f7cffa2f796c66746ea8631a2de01dbf2a 100644 (file)
--- 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,
index aa2cc4322718b9eb0c4bb55c24c866b386867dde..fb66246a74e803b3569c446806fcf1cb10413aa2 100755 (executable)
--- 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
index 30d0487e24821812a0ff784ce992d17051795435..2f052ae615b5a53ab28d2722c5bfb87ccc1fedc8 100755 (executable)
@@ -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"
index 74cde806911351ab619678ade151c0e28d941b99..5c552513205b394a03829613298148a632862d4f 100644 (file)
@@ -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;
            }
index 109ff5c448683a675259b955d45224d7d90925c6..132fb6e0682d773c8be61b504d4ba96342382976 100644 (file)
--- 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 613cbdb63f0fce0f22936b97f37feb6a53938b0f..402e78d98740a9e3a892e28797726d4f9cba622f 100644 (file)
--- 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);