Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 607

kvm-83-270.el5_11.src.rpm

From 5621d69ed32aac771903db963942c337f9031116 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
Date: Mon, 21 Feb 2011 09:47:39 -0300
Subject: [PATCH 5/8] monitor: Rework early disk password inquiry (Jan Kiszka)

RH-Author: Markus Armbruster <armbru@redhat.com>
Message-id: <1298281662-2327-6-git-send-email-armbru@redhat.com>
Patchwork-id: 18535
O-Subject: [PATCH RHEL5.7 qemu-kvm 5/8] monitor: Rework early disk password
	inquiry (Jan Kiszka)
Bugzilla: 644706
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>

From: aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>

Reading the passwords for encrypted hard disks during early startup is
broken (I guess for quiet a while now):
 - No monitor terminal is ready for input at this point
 - Forcing all mux'ed terminals into monitor mode can confuse other
   users of that channels

To overcome these issues and to lay the ground for a clean decoupling of
monitor terminals, this patch changes the initial password inquiry as
follows:
 - Prevent autostart if there is some encrypted disk
 - Once the user tries to resume the VM, prompt for all missing
   passwords
 - Only resume if all passwords were accepted

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6707 c046a42c-6fe2-441c-8c8c-71466251a162
Manually cherry-picked from commit c0f4ce7751f0b9a9a7815f931a09a6c3de127cee
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 qemu/block.c      |   14 ++++++++++-
 qemu/block.h      |    7 ++---
 qemu/block_int.h  |    1 +
 qemu/console.h    |    3 +-
 qemu/hw/usb-msd.c |    6 ++--
 qemu/hw/usb.h     |    5 +++-
 qemu/monitor.c    |   44 +++++++++++++++++++++++++++++++++---
 qemu/vl.c         |   64 +++++++++++++++--------------------------------------
 8 files changed, 83 insertions(+), 61 deletions(-)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qemu/block.c      |   14 ++++++++++-
 qemu/block.h      |    7 ++---
 qemu/block_int.h  |    1 +
 qemu/console.h    |    3 +-
 qemu/hw/usb-msd.c |    6 ++--
 qemu/hw/usb.h     |    5 +++-
 qemu/monitor.c    |   44 +++++++++++++++++++++++++++++++++---
 qemu/vl.c         |   64 +++++++++++++++--------------------------------------
 8 files changed, 83 insertions(+), 61 deletions(-)

diff --git a/qemu/block.c b/qemu/block.c
index a5b9a7e..e6b9da6 100644
--- a/qemu/block.c
+++ b/qemu/block.c
@@ -417,6 +417,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     bs->total_sectors = 0;
     bs->is_temporary = 0;
     bs->encrypted = 0;
+    bs->valid_key = 0;
     bs->open_flags = flags;
 
     if (flags & BDRV_O_SNAPSHOT) {
@@ -1243,6 +1244,15 @@ int bdrv_is_encrypted(BlockDriverState *bs)
     return bs->encrypted;
 }
 
+int bdrv_key_required(BlockDriverState *bs)
+{
+    BlockDriverState *backing_hd = bs->backing_hd;
+
+    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
+        return 1;
+    return (bs->encrypted && !bs->valid_key);
+}
+
 int bdrv_set_key(BlockDriverState *bs, const char *key)
 {
     int ret;
@@ -1255,7 +1265,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
     }
     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
         return -1;
-    return bs->drv->bdrv_set_key(bs, key);
+    ret = bs->drv->bdrv_set_key(bs, key);
+    bs->valid_key = (ret == 0);
+    return ret;
 }
 
 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
diff --git a/qemu/block.h b/qemu/block.h
index f9050d8..3878a5c 100644
--- a/qemu/block.h
+++ b/qemu/block.h
@@ -111,15 +111,12 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
                                  const uint8_t *buf, int nb_sectors,
                                  BlockDriverCompletionFunc *cb, void *opaque);
 BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
-				 BlockDriverCompletionFunc *cb, void *opaque);
+                                 BlockDriverCompletionFunc *cb, void *opaque);
 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
 
-int qemu_key_check(BlockDriverState *bs, const char *name);
-
 /* Ensure contents are flushed to disk.  */
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
-
 void bdrv_set_high_watermark(BlockDriverState *bs, uint64_t offset);
 
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
@@ -158,7 +155,9 @@ BlockDriverState *bdrv_find(const char *name);
 void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
                   void *opaque);
 int bdrv_is_encrypted(BlockDriverState *bs);
+int bdrv_key_required(BlockDriverState *bs);
 int bdrv_set_key(BlockDriverState *bs, const char *key);
+int bdrv_query_missing_keys(void);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque);
 const char *bdrv_get_device_name(BlockDriverState *bs);
diff --git a/qemu/block_int.h b/qemu/block_int.h
index a89c1a6..dd40c5d 100644
--- a/qemu/block_int.h
+++ b/qemu/block_int.h
@@ -120,6 +120,7 @@ struct BlockDriverState {
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
+    int valid_key; /* if true, a valid encryption key has been set */
     int sg;        /* if true, the device is a /dev/sg* */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
diff --git a/qemu/console.h b/qemu/console.h
index b2a2939..f01edd0 100644
--- a/qemu/console.h
+++ b/qemu/console.h
@@ -226,10 +226,9 @@ void term_printf_async(const int event, const char *fmt, ...)
 void term_print_filename(const char *filename);
 void term_flush(void);
 void term_print_help(void);
-void monitor_readline(const char *prompt, int is_password,
-                      char *buf, int buf_size);
 void monitor_suspend(void);
 void monitor_resume(void);
+int monitor_read_bdrv_key(BlockDriverState *bs);
 
 /* readline.c */
 typedef void ReadLineFunc(void *opaque, const char *str);
diff --git a/qemu/hw/usb-msd.c b/qemu/hw/usb-msd.c
index 143cdc5..d13c7ce 100644
--- a/qemu/hw/usb-msd.c
+++ b/qemu/hw/usb-msd.c
@@ -11,6 +11,7 @@
 #include "usb.h"
 #include "block.h"
 #include "scsi-disk.h"
+#include "console.h"
 
 //#define DEBUG_MSD
 
@@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
     qemu_free(s);
 }
 
-USBDevice *usb_msd_init(const char *filename)
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
 {
     MSDState *s;
     BlockDriverState *bdrv;
@@ -554,9 +555,8 @@ USBDevice *usb_msd_init(const char *filename)
     bdrv = bdrv_new("usb");
     if (bdrv_open2(bdrv, filename, 0, drv) < 0)
         goto fail;
-    if (qemu_key_check(bdrv, filename))
-        goto fail;
     s->bs = bdrv;
+    *pbs = bdrv;
 
     s->dev.speed = USB_SPEED_FULL;
     s->dev.handle_packet = usb_generic_handle_packet;
diff --git a/qemu/hw/usb.h b/qemu/hw/usb.h
index 4204808..4cd832d 100644
--- a/qemu/hw/usb.h
+++ b/qemu/hw/usb.h
@@ -21,6 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+
+#include "block.h"
+
 #define USB_TOKEN_SETUP 0x2d
 #define USB_TOKEN_IN    0x69 /* device -> host */
 #define USB_TOKEN_OUT   0xe1 /* host -> device */
@@ -250,7 +253,7 @@ USBDevice *usb_keyboard_init(void);
 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
 
 /* usb-msd.c */
-USBDevice *usb_msd_init(const char *filename);
+USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
 
 /* usb-net.c */
 USBDevice *usb_net_init(NICInfo *nd);
diff --git a/qemu/monitor.c b/qemu/monitor.c
index d226544..48cc4bf 100644
--- a/qemu/monitor.c
+++ b/qemu/monitor.c
@@ -89,6 +89,8 @@ static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
 
 static void monitor_start_input(void);
+static void monitor_readline(const char *prompt, int is_password,
+                             char *buf, int buf_size);
 
 static CPUState *mon_cpu = NULL;
 
@@ -556,7 +558,7 @@ static void do_change_block(const char *device, const char *filename, const char
         term_printf("Could not open '%s'\n", filename);
         return;
     }
-    qemu_key_check(bs, filename);
+    monitor_read_bdrv_key(bs);
 }
 
 static void do_change_vnc(const char *target, const char *arg)
@@ -618,9 +620,24 @@ static void do_stop(void)
     vm_stop(EXCP_INTERRUPT);
 }
 
+static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
+{
+    int *err = opaque;
+
+    if (bdrv_key_required(bs))
+        *err = monitor_read_bdrv_key(bs);
+    else
+        *err = 0;
+}
+
 static void do_cont(void)
 {
-    vm_start();
+    int err = 0;
+
+    bdrv_iterate(encrypted_bdrv_it, &err);
+    /* only resume the vm if all keys are set and valid */
+    if (!err)
+        vm_start();
 }
 
 #ifdef CONFIG_GDBSTUB
@@ -3175,8 +3192,8 @@ static void monitor_readline_cb(void *opaque, const char *input)
     monitor_readline_started = 0;
 }
 
-void monitor_readline(const char *prompt, int is_password,
-                      char *buf, int buf_size)
+static void monitor_readline(const char *prompt, int is_password,
+                             char *buf, int buf_size)
 {
     int i;
     int old_focus[MAX_MON];
@@ -3206,3 +3223,22 @@ void monitor_readline(const char *prompt, int is_password,
                 monitor_hd[i]->focus = old_focus[i];
     }
 }
+
+int monitor_read_bdrv_key(BlockDriverState *bs)
+{
+    char password[256];
+    int i;
+
+    if (!bdrv_is_encrypted(bs))
+        return 0;
+
+    term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
+                bdrv_get_encrypted_filename(bs));
+    for(i = 0; i < 3; i++) {
+        monitor_readline("Password: ", 1, password, sizeof(password));
+        if (bdrv_set_key(bs, password) == 0)
+            return 0;
+        term_printf("invalid password\n");
+    }
+    return -EPERM;
+}
diff --git a/qemu/vl.c b/qemu/vl.c
index 17e05ff..e653ed6 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -2779,11 +2779,13 @@ int drive_init(struct drive_opt *arg, int snapshot,
 
 int drive_open(DriveInfo drive)
 {
-    if (bdrv_open2(drive.bdrv, drive.file, drive.bdrv_flags, drive.drv) < 0 || qemu_key_check(drive.bdrv, drive.file)) {
+    if (bdrv_open2(drive.bdrv, drive.file, drive.bdrv_flags, drive.drv) < 0) {
         fprintf(stderr, "qemu: could not open disk image %s\n",
                         drive.file);
         return -1;
     }
+    if (bdrv_key_required(drive.bdrv))
+        autostart = 0;
     return 0;
 }
 
@@ -2895,7 +2897,7 @@ int usb_device_add_dev(USBDevice *dev)
     return 0;
 }
 
-static int usb_device_add(const char *devname)
+static int usb_device_add(const char *devname, int is_hotplug)
 {
     const char *p;
     USBDevice *dev;
@@ -2914,7 +2916,18 @@ static int usb_device_add(const char *devname)
     } else
 #ifdef CONFIG_USB_MSD
     if (strstart(devname, "disk:", &p)) {
-        dev = usb_msd_init(p);
+        BlockDriverState *bs;
+
+        dev = usb_msd_init(p, &bs);
+        if (!dev)
+            return -1;
+        if (bdrv_key_required(bs)) {
+            autostart = 0;
+            if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
+                dev->handle_destroy(dev);
+                return -1;
+            }
+        }
     } else
 #endif
 #ifdef CONFIG_USB_WACOM
@@ -3010,7 +3023,7 @@ static int usb_device_del(const char *devname)
 
 void do_usb_add(const char *devname)
 {
-    usb_device_add(devname);
+    usb_device_add(devname, 1);
 }
 
 void do_usb_del(const char *devname)
@@ -4774,45 +4787,6 @@ static const QEMUOption qemu_options[] = {
     { NULL },
 };
 
-/* password input */
-
-int qemu_key_check(BlockDriverState *bs, const char *name)
-{
-    char password[256];
-    int i;
-
-    if (!bdrv_is_encrypted(bs))
-        return 0;
-
-    term_printf("%s is encrypted.\n", name);
-    for(i = 0; i < 3; i++) {
-        monitor_readline("Password: ", 1, password, sizeof(password));
-        if (bdrv_set_key(bs, password) == 0)
-            return 0;
-        term_printf("invalid password\n");
-    }
-    return -EPERM;
-}
-
-static BlockDriverState *get_bdrv(int index)
-{
-    if (index > nb_drives)
-        return NULL;
-    return drives_table[index].bdrv;
-}
-
-static void read_passwords(void)
-{
-    BlockDriverState *bs;
-    int i;
-
-    for(i = 0; i < 6; i++) {
-        bs = get_bdrv(i);
-        if (bs)
-            qemu_key_check(bs, bdrv_get_device_name(bs));
-    }
-}
-
 #ifdef HAS_AUDIO
 struct soundhw soundhw[] = {
 #ifdef HAS_AUDIO_CHOICE
@@ -6478,7 +6452,7 @@ int main(int argc, char **argv, char **envp)
     /* init USB devices */
     if (usb_enabled) {
         for(i = 0; i < usb_devices_index; i++) {
-            if (usb_device_add(usb_devices[i]) < 0) {
+            if (usb_device_add(usb_devices[i], 0) < 0) {
                 fprintf(stderr, "Warning: could not add USB device %s\n",
                         usb_devices[i]);
             }
@@ -6512,8 +6486,6 @@ int main(int argc, char **argv, char **envp)
     if (incoming)
         qemu_start_incoming_migration(incoming);
 
-    /* XXX: simplify init */
-    read_passwords();
     if (!incoming && autostart)
         vm_start();
 
-- 
1.7.4.rc1.16.gd2f15e