Commit c0f4ce7751f0b9a9a7815f931a09a6c3de127cee

Authored by aliguori
1 parent 430eb509

monitor: Rework early disk password inquiry (Jan Kiszka)

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
... ... @@ -336,6 +336,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
336 336 bs->read_only = 0;
337 337 bs->is_temporary = 0;
338 338 bs->encrypted = 0;
  339 + bs->valid_key = 0;
339 340  
340 341 if (flags & BDRV_O_SNAPSHOT) {
341 342 BlockDriverState *bs1;
... ... @@ -966,6 +967,15 @@ int bdrv_is_encrypted(BlockDriverState *bs)
966 967 return bs->encrypted;
967 968 }
968 969  
  970 +int bdrv_key_required(BlockDriverState *bs)
  971 +{
  972 + BlockDriverState *backing_hd = bs->backing_hd;
  973 +
  974 + if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
  975 + return 1;
  976 + return (bs->encrypted && !bs->valid_key);
  977 +}
  978 +
969 979 int bdrv_set_key(BlockDriverState *bs, const char *key)
970 980 {
971 981 int ret;
... ... @@ -978,7 +988,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
978 988 }
979 989 if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
980 990 return -1;
981   - return bs->drv->bdrv_set_key(bs, key);
  991 + ret = bs->drv->bdrv_set_key(bs, key);
  992 + bs->valid_key = (ret == 0);
  993 + return ret;
982 994 }
983 995  
984 996 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
... ...
... ... @@ -103,8 +103,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
103 103 BlockDriverCompletionFunc *cb, void *opaque);
104 104 void bdrv_aio_cancel(BlockDriverAIOCB *acb);
105 105  
106   -int qemu_key_check(BlockDriverState *bs, const char *name);
107   -
108 106 /* Ensure contents are flushed to disk. */
109 107 void bdrv_flush(BlockDriverState *bs);
110 108 void bdrv_flush_all(void);
... ... @@ -144,7 +142,9 @@ BlockDriverState *bdrv_find(const char *name);
144 142 void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
145 143 void *opaque);
146 144 int bdrv_is_encrypted(BlockDriverState *bs);
  145 +int bdrv_key_required(BlockDriverState *bs);
147 146 int bdrv_set_key(BlockDriverState *bs, const char *key);
  147 +int bdrv_query_missing_keys(void);
148 148 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
149 149 void *opaque);
150 150 const char *bdrv_get_device_name(BlockDriverState *bs);
... ...
block_int.h
... ... @@ -96,6 +96,7 @@ struct BlockDriverState {
96 96 int removable; /* if true, the media can be removed */
97 97 int locked; /* if true, the media cannot temporarily be ejected */
98 98 int encrypted; /* if true, the media is encrypted */
  99 + int valid_key; /* if true, a valid encryption key has been set */
99 100 int sg; /* if true, the device is a /dev/sg* */
100 101 /* event callback when inserting/removing */
101 102 void (*change_cb)(void *opaque);
... ...
console.h
... ... @@ -302,10 +302,9 @@ void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1
302 302 void term_print_filename(const char *filename);
303 303 void term_flush(void);
304 304 void term_print_help(void);
305   -void monitor_readline(const char *prompt, int is_password,
306   - char *buf, int buf_size);
307 305 void monitor_suspend(void);
308 306 void monitor_resume(void);
  307 +int monitor_read_bdrv_key(BlockDriverState *bs);
309 308  
310 309 /* readline.c */
311 310 typedef void ReadLineFunc(void *opaque, const char *str);
... ...
hw/usb-msd.c
... ... @@ -11,6 +11,7 @@
11 11 #include "usb.h"
12 12 #include "block.h"
13 13 #include "scsi-disk.h"
  14 +#include "console.h"
14 15  
15 16 //#define DEBUG_MSD
16 17  
... ... @@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
513 514 qemu_free(s);
514 515 }
515 516  
516   -USBDevice *usb_msd_init(const char *filename)
  517 +USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
517 518 {
518 519 MSDState *s;
519 520 BlockDriverState *bdrv;
... ... @@ -552,9 +553,8 @@ USBDevice *usb_msd_init(const char *filename)
552 553 bdrv = bdrv_new("usb");
553 554 if (bdrv_open2(bdrv, filename, 0, drv) < 0)
554 555 goto fail;
555   - if (qemu_key_check(bdrv, filename))
556   - goto fail;
557 556 s->bs = bdrv;
  557 + *pbs = bdrv;
558 558  
559 559 s->dev.speed = USB_SPEED_FULL;
560 560 s->dev.handle_packet = usb_generic_handle_packet;
... ...
hw/usb.h
... ... @@ -21,6 +21,9 @@
21 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 22 * THE SOFTWARE.
23 23 */
  24 +
  25 +#include "block.h"
  26 +
24 27 #define USB_TOKEN_SETUP 0x2d
25 28 #define USB_TOKEN_IN 0x69 /* device -> host */
26 29 #define USB_TOKEN_OUT 0xe1 /* host -> device */
... ... @@ -250,7 +253,7 @@ USBDevice *usb_keyboard_init(void);
250 253 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
251 254  
252 255 /* usb-msd.c */
253   -USBDevice *usb_msd_init(const char *filename);
  256 +USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
254 257  
255 258 /* usb-net.c */
256 259 USBDevice *usb_net_init(NICInfo *nd);
... ...
monitor.c
... ... @@ -76,6 +76,8 @@ static uint8_t term_outbuf[1024];
76 76 static int term_outbuf_index;
77 77  
78 78 static void monitor_start_input(void);
  79 +static void monitor_readline(const char *prompt, int is_password,
  80 + char *buf, int buf_size);
79 81  
80 82 static CPUState *mon_cpu = NULL;
81 83  
... ... @@ -433,7 +435,7 @@ static void do_change_block(const char *device, const char *filename, const char
433 435 if (eject_device(bs, 0) < 0)
434 436 return;
435 437 bdrv_open2(bs, filename, 0, drv);
436   - qemu_key_check(bs, filename);
  438 + monitor_read_bdrv_key(bs);
437 439 }
438 440  
439 441 static void do_change_vnc(const char *target, const char *arg)
... ... @@ -494,9 +496,24 @@ static void do_stop(void)
494 496 vm_stop(EXCP_INTERRUPT);
495 497 }
496 498  
  499 +static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs)
  500 +{
  501 + int *err = opaque;
  502 +
  503 + if (bdrv_key_required(bs))
  504 + *err = monitor_read_bdrv_key(bs);
  505 + else
  506 + *err = 0;
  507 +}
  508 +
497 509 static void do_cont(void)
498 510 {
499   - vm_start();
  511 + int err = 0;
  512 +
  513 + bdrv_iterate(encrypted_bdrv_it, &err);
  514 + /* only resume the vm if all keys are set and valid */
  515 + if (!err)
  516 + vm_start();
500 517 }
501 518  
502 519 #ifdef CONFIG_GDBSTUB
... ... @@ -2892,8 +2909,8 @@ static void monitor_readline_cb(void *opaque, const char *input)
2892 2909 monitor_readline_started = 0;
2893 2910 }
2894 2911  
2895   -void monitor_readline(const char *prompt, int is_password,
2896   - char *buf, int buf_size)
  2912 +static void monitor_readline(const char *prompt, int is_password,
  2913 + char *buf, int buf_size)
2897 2914 {
2898 2915 int i;
2899 2916 int old_focus[MAX_MON];
... ... @@ -2923,3 +2940,22 @@ void monitor_readline(const char *prompt, int is_password,
2923 2940 monitor_hd[i]->focus = old_focus[i];
2924 2941 }
2925 2942 }
  2943 +
  2944 +int monitor_read_bdrv_key(BlockDriverState *bs)
  2945 +{
  2946 + char password[256];
  2947 + int i;
  2948 +
  2949 + if (!bdrv_is_encrypted(bs))
  2950 + return 0;
  2951 +
  2952 + term_printf("%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
  2953 + bdrv_get_encrypted_filename(bs));
  2954 + for(i = 0; i < 3; i++) {
  2955 + monitor_readline("Password: ", 1, password, sizeof(password));
  2956 + if (bdrv_set_key(bs, password) == 0)
  2957 + return 0;
  2958 + term_printf("invalid password\n");
  2959 + }
  2960 + return -EPERM;
  2961 +}
... ...
... ... @@ -201,6 +201,7 @@ ram_addr_t ram_size;
201 201 int nb_nics;
202 202 NICInfo nd_table[MAX_NICS];
203 203 int vm_running;
  204 +static int autostart;
204 205 static int rtc_utc = 1;
205 206 static int rtc_date_offset = -1; /* -1 means no change */
206 207 int cirrus_vga_enabled = 1;
... ... @@ -2607,11 +2608,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
2607 2608 bdrv_flags |= BDRV_O_CACHE_WB;
2608 2609 else if (cache == 3) /* not specified */
2609 2610 bdrv_flags |= BDRV_O_CACHE_DEF;
2610   - if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
  2611 + if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
2611 2612 fprintf(stderr, "qemu: could not open disk image %s\n",
2612 2613 file);
2613 2614 return -1;
2614 2615 }
  2616 + if (bdrv_key_required(bdrv))
  2617 + autostart = 0;
2615 2618 return drives_table_idx;
2616 2619 }
2617 2620  
... ... @@ -2658,7 +2661,7 @@ int usb_device_add_dev(USBDevice *dev)
2658 2661 return 0;
2659 2662 }
2660 2663  
2661   -static int usb_device_add(const char *devname)
  2664 +static int usb_device_add(const char *devname, int is_hotplug)
2662 2665 {
2663 2666 const char *p;
2664 2667 USBDevice *dev;
... ... @@ -2675,7 +2678,18 @@ static int usb_device_add(const char *devname)
2675 2678 } else if (!strcmp(devname, "keyboard")) {
2676 2679 dev = usb_keyboard_init();
2677 2680 } else if (strstart(devname, "disk:", &p)) {
2678   - dev = usb_msd_init(p);
  2681 + BlockDriverState *bs;
  2682 +
  2683 + dev = usb_msd_init(p, &bs);
  2684 + if (!dev)
  2685 + return -1;
  2686 + if (bdrv_key_required(bs)) {
  2687 + autostart = 0;
  2688 + if (is_hotplug && monitor_read_bdrv_key(bs) < 0) {
  2689 + dev->handle_destroy(dev);
  2690 + return -1;
  2691 + }
  2692 + }
2679 2693 } else if (!strcmp(devname, "wacom-tablet")) {
2680 2694 dev = usb_wacom_init();
2681 2695 } else if (strstart(devname, "serial:", &p)) {
... ... @@ -2756,7 +2770,7 @@ static int usb_device_del(const char *devname)
2756 2770  
2757 2771 void do_usb_add(const char *devname)
2758 2772 {
2759   - usb_device_add(devname);
  2773 + usb_device_add(devname, 1);
2760 2774 }
2761 2775  
2762 2776 void do_usb_del(const char *devname)
... ... @@ -4334,45 +4348,6 @@ static const QEMUOption qemu_options[] = {
4334 4348 { NULL },
4335 4349 };
4336 4350  
4337   -/* password input */
4338   -
4339   -int qemu_key_check(BlockDriverState *bs, const char *name)
4340   -{
4341   - char password[256];
4342   - int i;
4343   -
4344   - if (!bdrv_is_encrypted(bs))
4345   - return 0;
4346   -
4347   - term_printf("%s is encrypted.\n", name);
4348   - for(i = 0; i < 3; i++) {
4349   - monitor_readline("Password: ", 1, password, sizeof(password));
4350   - if (bdrv_set_key(bs, password) == 0)
4351   - return 0;
4352   - term_printf("invalid password\n");
4353   - }
4354   - return -EPERM;
4355   -}
4356   -
4357   -static BlockDriverState *get_bdrv(int index)
4358   -{
4359   - if (index > nb_drives)
4360   - return NULL;
4361   - return drives_table[index].bdrv;
4362   -}
4363   -
4364   -static void read_passwords(void)
4365   -{
4366   - BlockDriverState *bs;
4367   - int i;
4368   -
4369   - for(i = 0; i < 6; i++) {
4370   - bs = get_bdrv(i);
4371   - if (bs)
4372   - qemu_key_check(bs, bdrv_get_device_name(bs));
4373   - }
4374   -}
4375   -
4376 4351 #ifdef HAS_AUDIO
4377 4352 struct soundhw soundhw[] = {
4378 4353 #ifdef HAS_AUDIO_CHOICE
... ... @@ -4639,7 +4614,6 @@ int main(int argc, char **argv, char **envp)
4639 4614 int fds[2];
4640 4615 int tb_size;
4641 4616 const char *pid_file = NULL;
4642   - int autostart;
4643 4617 const char *incoming = NULL;
4644 4618 int fd = 0;
4645 4619 struct passwd *pwd = NULL;
... ... @@ -5637,7 +5611,7 @@ int main(int argc, char **argv, char **envp)
5637 5611 /* init USB devices */
5638 5612 if (usb_enabled) {
5639 5613 for(i = 0; i < usb_devices_index; i++) {
5640   - if (usb_device_add(usb_devices[i]) < 0) {
  5614 + if (usb_device_add(usb_devices[i], 0) < 0) {
5641 5615 fprintf(stderr, "Warning: could not add USB device %s\n",
5642 5616 usb_devices[i]);
5643 5617 }
... ... @@ -5748,13 +5722,8 @@ int main(int argc, char **argv, char **envp)
5748 5722 qemu_start_incoming_migration(incoming);
5749 5723 }
5750 5724  
5751   - {
5752   - /* XXX: simplify init */
5753   - read_passwords();
5754   - if (autostart) {
5755   - vm_start();
5756   - }
5757   - }
  5725 + if (autostart)
  5726 + vm_start();
5758 5727  
5759 5728 if (daemonize) {
5760 5729 uint8_t status = 0;
... ...