From be97a3ca4d381b7d8686e6f3c68f056775e0cd0f Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Fam Zheng Date: Thu, 6 Jun 2013 07:43:29 +0200 Subject: [PATCH 3/6] block: add block driver read only whitelist RH-Author: Fam Zheng Message-id: <1370504610-14223-2-git-send-email-famz@redhat.com> Patchwork-id: 51758 O-Subject: [PATCH RHEL-6.5 qemu-kvm v3 1/2] block: add block driver read only whitelist Bugzilla: 960685 RH-Acked-by: Kevin Wolf RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Paolo Bonzini We may want to include a driver in the whitelist for read only tasks such as diagnosing or exporting guest data (with libguestfs as a good example). This patch introduces a readonly whitelist option, and for backward compatibility, the old configure option --block-drv-whitelist is now an alias to rw whitelist. Drivers in readonly list is only permitted to open file readonly, and returns -ENOTSUP for RW opening. E.g. To include vmdk readonly, and others read+write: ./configure --target-list=x86_64-softmmu \ --block-drv-rw-whitelist=qcow2,raw,file,qed \ --block-drv-ro-whitelist=vmdk Signed-off-by: Fam Zheng Signed-off-by: Kevin Wolf (cherry picked from commit b64ec4e4ade581d662753cdeb0d7e0e27aafbf81) Solved some conflicts because of file rename and xen_disk.c difference with upstream, but they are trivial enough. Signed-off-by: Fam Zheng --- block.c | 57 +++++++++++++++++++++++++++++++++++---------------------- block.h | 3 ++- blockdev.c | 4 ++-- configure | 20 +++++++++++++++----- create_config | 11 +++++++++-- hw/xen_disk.c | 3 ++- 6 files changed, 65 insertions(+), 33 deletions(-) Signed-off-by: Michal Novotny --- block.c | 57 +++++++++++++++++++++++++++++++++++---------------------- block.h | 3 ++- blockdev.c | 4 ++-- configure | 20 +++++++++++++++----- create_config | 11 +++++++++-- hw/xen_disk.c | 3 ++- 6 files changed, 65 insertions(+), 33 deletions(-) diff --git a/block.c b/block.c index 3812712..b873083 100644 --- a/block.c +++ b/block.c @@ -232,28 +232,40 @@ BlockDriver *bdrv_find_format(const char *format_name) return NULL; } -static int bdrv_is_whitelisted(BlockDriver *drv) +static int bdrv_is_whitelisted(BlockDriver *drv, bool read_only) { - static const char *whitelist[] = { - CONFIG_BDRV_WHITELIST + static const char *whitelist_rw[] = { + CONFIG_BDRV_RW_WHITELIST + }; + static const char *whitelist_ro[] = { + CONFIG_BDRV_RO_WHITELIST }; const char **p; - if (!whitelist[0]) + if (!whitelist_rw[0] && !whitelist_ro[0]) { return 1; /* no whitelist, anything goes */ + } - for (p = whitelist; *p; p++) { + for (p = whitelist_rw; *p; p++) { if (!strcmp(drv->format_name, *p)) { return 1; } } + if (read_only) { + for (p = whitelist_ro; *p; p++) { + if (!strcmp(drv->format_name, *p)) { + return 1; + } + } + } return 0; } -BlockDriver *bdrv_find_whitelisted_format(const char *format_name) +BlockDriver *bdrv_find_whitelisted_format(const char *format_name, + bool read_only) { BlockDriver *drv = bdrv_find_format(format_name); - return drv && bdrv_is_whitelisted(drv) ? drv : NULL; + return drv && bdrv_is_whitelisted(drv, read_only) ? drv : NULL; } int bdrv_create(BlockDriver *drv, const char* filename, @@ -477,17 +489,27 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, /* buffer_alignment defaulted to 512, drivers can change this value */ bs->buffer_alignment = 512; - assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ - if ((flags & BDRV_O_RDWR) && (flags & BDRV_O_COPY_ON_READ)) { - bdrv_enable_copy_on_read(bs); + open_flags = flags; + /* + * Snapshots should be writeable. + */ + if (bs->is_temporary) { + open_flags |= BDRV_O_RDWR; } - pstrcpy(bs->filename, sizeof(bs->filename), filename); + bs->read_only = !(open_flags & BDRV_O_RDWR); - if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) { + if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv, bs->read_only)) { return -ENOTSUP; } + assert(bs->copy_on_read == 0); /* bdrv_new() and bdrv_close() make it so */ + if (!bs->read_only && (flags & BDRV_O_COPY_ON_READ)) { + bdrv_enable_copy_on_read(bs); + } + + pstrcpy(bs->filename, sizeof(bs->filename), filename); + bs->drv = drv; bs->opaque = g_malloc0(drv->instance_size); @@ -498,16 +520,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, * Clear flags that are internal to the block layer before opening the * image. */ - open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); - - /* - * Snapshots should be writeable. - */ - if (bs->is_temporary) { - open_flags |= BDRV_O_RDWR; - } - - bs->read_only = !(open_flags & BDRV_O_RDWR); + open_flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); /* Open the image, either directly or using a protocol */ if (drv->bdrv_file_open) { diff --git a/block.h b/block.h index d69b1d6..b4af894 100644 --- a/block.h +++ b/block.h @@ -126,7 +126,8 @@ void bdrv_init(void); void bdrv_init_with_whitelist(void); BlockDriver *bdrv_find_protocol(const char *filename); BlockDriver *bdrv_find_format(const char *format_name); -BlockDriver *bdrv_find_whitelisted_format(const char *format_name); +BlockDriver *bdrv_find_whitelisted_format(const char *format_name, + bool readonly); int bdrv_create(BlockDriver *drv, const char* filename, QEMUOptionParameter *options); int bdrv_create_file(const char* filename, QEMUOptionParameter *options); diff --git a/blockdev.c b/blockdev.c index 34091d3..20f98cc 100644 --- a/blockdev.c +++ b/blockdev.c @@ -452,7 +452,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) error_printf("\n"); return NULL; } - drv = bdrv_find_whitelisted_format(buf); + drv = bdrv_find_whitelisted_format(buf, ro); if (!drv) { error_report("'%s' invalid format", buf); return NULL; @@ -1165,7 +1165,7 @@ int do_change_block(Monitor *mon, const char *device, return -1; } if (fmt) { - drv = bdrv_find_whitelisted_format(fmt); + drv = bdrv_find_whitelisted_format(fmt, bs->read_only); if (!drv) { qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt); return -1; diff --git a/configure b/configure index a82cfd5..ff58e9f 100755 --- a/configure +++ b/configure @@ -40,7 +40,8 @@ cc="gcc" audio_drv_list="" audio_card_list="ac97 es1370 sb16" audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus" -block_drv_whitelist="" +block_drv_rw_whitelist="" +block_drv_ro_whitelist="" host_cc="gcc" ar="ar" make="make" @@ -512,7 +513,9 @@ for opt do ;; --audio-drv-list=*) audio_drv_list="$optarg" ;; - --block-drv-whitelist=*) block_drv_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` + --block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` + ;; + --block-drv-ro-whitelist=*) block_drv_ro_whitelist=`echo "$optarg" | sed -e 's/,/ /g'` ;; --enable-debug-tcg) debug_tcg="yes" ;; @@ -808,7 +811,12 @@ 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 " --block-drv-whitelist=L Same as --block-drv-rw-whitelist=L" +echo " --block-drv-rw-whitelist=L" +echo " set block driver read-write whitelist" +echo " (affects only QEMU, not qemu-img)" +echo " --block-drv-ro-whitelist=L" +echo " set block driver read-only whitelist" echo " (affects only QEMU, not qemu-img)" echo " --enable-mixemu enable mixer emulation" echo " --disable-xen disable xen backend driver support" @@ -2292,7 +2300,8 @@ 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 "Block whitelist (rw) $block_drv_rw_whitelist" +echo "Block whitelist (ro) $block_drv_ro_whitelist" echo "Mixer emulation $mixemu" echo "VNC TLS support $vnc_tls" echo "VNC SASL support $vnc_sasl" @@ -2437,7 +2446,8 @@ 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 +echo "CONFIG_BDRV_RW_WHITELIST=$block_drv_rw_whitelist" >> $config_host_mak +echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_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 27d85e2..798b8dc 100755 --- a/create_config +++ b/create_config @@ -39,8 +39,15 @@ case $line in done echo "" ;; - CONFIG_BDRV_WHITELIST=*) - echo "#define CONFIG_BDRV_WHITELIST \\" + CONFIG_BDRV_RW_WHITELIST=*) + echo "#define CONFIG_BDRV_RW_WHITELIST\\" + for drv in ${line#*=}; do + echo " \"${drv}\",\\" + done + echo " NULL" + ;; + CONFIG_BDRV_RO_WHITELIST=*) + echo "#define CONFIG_BDRV_RO_WHITELIST\\" for drv in ${line#*=}; do echo " \"${drv}\",\\" done diff --git a/hw/xen_disk.c b/hw/xen_disk.c index a22b94d..7d9e8cb 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -633,7 +633,8 @@ static int blk_init(struct XenDevice *xendev) xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n"); blkdev->bs = bdrv_new(blkdev->dev); if (bdrv_open(blkdev->bs, blkdev->filename, qflags, - bdrv_find_whitelisted_format(blkdev->fileproto)) != 0) { + bdrv_find_whitelisted_format(blkdev->fileproto, + mode == O_RDONLY)) != 0) { bdrv_delete(blkdev->bs); return -1; } -- 1.7.11.7