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
This commit is contained in:
parent
430eb509d2
commit
c0f4ce7751
14
block.c
14
block.c
|
@ -336,6 +336,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
|
||||||
bs->read_only = 0;
|
bs->read_only = 0;
|
||||||
bs->is_temporary = 0;
|
bs->is_temporary = 0;
|
||||||
bs->encrypted = 0;
|
bs->encrypted = 0;
|
||||||
|
bs->valid_key = 0;
|
||||||
|
|
||||||
if (flags & BDRV_O_SNAPSHOT) {
|
if (flags & BDRV_O_SNAPSHOT) {
|
||||||
BlockDriverState *bs1;
|
BlockDriverState *bs1;
|
||||||
|
@ -966,6 +967,15 @@ int bdrv_is_encrypted(BlockDriverState *bs)
|
||||||
return bs->encrypted;
|
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 bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -978,7 +988,9 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
|
||||||
}
|
}
|
||||||
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
|
if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
|
||||||
return -1;
|
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)
|
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
|
||||||
|
|
4
block.h
4
block.h
|
@ -103,8 +103,6 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
|
||||||
BlockDriverCompletionFunc *cb, void *opaque);
|
BlockDriverCompletionFunc *cb, void *opaque);
|
||||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
|
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
|
||||||
|
|
||||||
int qemu_key_check(BlockDriverState *bs, const char *name);
|
|
||||||
|
|
||||||
/* Ensure contents are flushed to disk. */
|
/* Ensure contents are flushed to disk. */
|
||||||
void bdrv_flush(BlockDriverState *bs);
|
void bdrv_flush(BlockDriverState *bs);
|
||||||
void bdrv_flush_all(void);
|
void bdrv_flush_all(void);
|
||||||
|
@ -144,7 +142,9 @@ BlockDriverState *bdrv_find(const char *name);
|
||||||
void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
|
void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
|
||||||
void *opaque);
|
void *opaque);
|
||||||
int bdrv_is_encrypted(BlockDriverState *bs);
|
int bdrv_is_encrypted(BlockDriverState *bs);
|
||||||
|
int bdrv_key_required(BlockDriverState *bs);
|
||||||
int bdrv_set_key(BlockDriverState *bs, const char *key);
|
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 bdrv_iterate_format(void (*it)(void *opaque, const char *name),
|
||||||
void *opaque);
|
void *opaque);
|
||||||
const char *bdrv_get_device_name(BlockDriverState *bs);
|
const char *bdrv_get_device_name(BlockDriverState *bs);
|
||||||
|
|
|
@ -96,6 +96,7 @@ struct BlockDriverState {
|
||||||
int removable; /* if true, the media can be removed */
|
int removable; /* if true, the media can be removed */
|
||||||
int locked; /* if true, the media cannot temporarily be ejected */
|
int locked; /* if true, the media cannot temporarily be ejected */
|
||||||
int encrypted; /* if true, the media is encrypted */
|
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* */
|
int sg; /* if true, the device is a /dev/sg* */
|
||||||
/* event callback when inserting/removing */
|
/* event callback when inserting/removing */
|
||||||
void (*change_cb)(void *opaque);
|
void (*change_cb)(void *opaque);
|
||||||
|
|
|
@ -302,10 +302,9 @@ void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1
|
||||||
void term_print_filename(const char *filename);
|
void term_print_filename(const char *filename);
|
||||||
void term_flush(void);
|
void term_flush(void);
|
||||||
void term_print_help(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_suspend(void);
|
||||||
void monitor_resume(void);
|
void monitor_resume(void);
|
||||||
|
int monitor_read_bdrv_key(BlockDriverState *bs);
|
||||||
|
|
||||||
/* readline.c */
|
/* readline.c */
|
||||||
typedef void ReadLineFunc(void *opaque, const char *str);
|
typedef void ReadLineFunc(void *opaque, const char *str);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
#include "scsi-disk.h"
|
#include "scsi-disk.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
//#define DEBUG_MSD
|
//#define DEBUG_MSD
|
||||||
|
|
||||||
|
@ -513,7 +514,7 @@ static void usb_msd_handle_destroy(USBDevice *dev)
|
||||||
qemu_free(s);
|
qemu_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice *usb_msd_init(const char *filename)
|
USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs)
|
||||||
{
|
{
|
||||||
MSDState *s;
|
MSDState *s;
|
||||||
BlockDriverState *bdrv;
|
BlockDriverState *bdrv;
|
||||||
|
@ -552,9 +553,8 @@ USBDevice *usb_msd_init(const char *filename)
|
||||||
bdrv = bdrv_new("usb");
|
bdrv = bdrv_new("usb");
|
||||||
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
if (bdrv_open2(bdrv, filename, 0, drv) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
if (qemu_key_check(bdrv, filename))
|
|
||||||
goto fail;
|
|
||||||
s->bs = bdrv;
|
s->bs = bdrv;
|
||||||
|
*pbs = bdrv;
|
||||||
|
|
||||||
s->dev.speed = USB_SPEED_FULL;
|
s->dev.speed = USB_SPEED_FULL;
|
||||||
s->dev.handle_packet = usb_generic_handle_packet;
|
s->dev.handle_packet = usb_generic_handle_packet;
|
||||||
|
|
5
hw/usb.h
5
hw/usb.h
|
@ -21,6 +21,9 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "block.h"
|
||||||
|
|
||||||
#define USB_TOKEN_SETUP 0x2d
|
#define USB_TOKEN_SETUP 0x2d
|
||||||
#define USB_TOKEN_IN 0x69 /* device -> host */
|
#define USB_TOKEN_IN 0x69 /* device -> host */
|
||||||
#define USB_TOKEN_OUT 0xe1 /* host -> device */
|
#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 *));
|
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
|
||||||
|
|
||||||
/* usb-msd.c */
|
/* usb-msd.c */
|
||||||
USBDevice *usb_msd_init(const char *filename);
|
USBDevice *usb_msd_init(const char *filename, BlockDriverState **pbs);
|
||||||
|
|
||||||
/* usb-net.c */
|
/* usb-net.c */
|
||||||
USBDevice *usb_net_init(NICInfo *nd);
|
USBDevice *usb_net_init(NICInfo *nd);
|
||||||
|
|
44
monitor.c
44
monitor.c
|
@ -76,6 +76,8 @@ static uint8_t term_outbuf[1024];
|
||||||
static int term_outbuf_index;
|
static int term_outbuf_index;
|
||||||
|
|
||||||
static void monitor_start_input(void);
|
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;
|
static CPUState *mon_cpu = NULL;
|
||||||
|
|
||||||
|
@ -433,7 +435,7 @@ static void do_change_block(const char *device, const char *filename, const char
|
||||||
if (eject_device(bs, 0) < 0)
|
if (eject_device(bs, 0) < 0)
|
||||||
return;
|
return;
|
||||||
bdrv_open2(bs, filename, 0, drv);
|
bdrv_open2(bs, filename, 0, drv);
|
||||||
qemu_key_check(bs, filename);
|
monitor_read_bdrv_key(bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_change_vnc(const char *target, const char *arg)
|
static void do_change_vnc(const char *target, const char *arg)
|
||||||
|
@ -494,9 +496,24 @@ static void do_stop(void)
|
||||||
vm_stop(EXCP_INTERRUPT);
|
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)
|
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
|
#ifdef CONFIG_GDBSTUB
|
||||||
|
@ -2892,8 +2909,8 @@ static void monitor_readline_cb(void *opaque, const char *input)
|
||||||
monitor_readline_started = 0;
|
monitor_readline_started = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitor_readline(const char *prompt, int is_password,
|
static void monitor_readline(const char *prompt, int is_password,
|
||||||
char *buf, int buf_size)
|
char *buf, int buf_size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int old_focus[MAX_MON];
|
int old_focus[MAX_MON];
|
||||||
|
@ -2923,3 +2940,22 @@ void monitor_readline(const char *prompt, int is_password,
|
||||||
monitor_hd[i]->focus = old_focus[i];
|
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;
|
||||||
|
}
|
||||||
|
|
73
vl.c
73
vl.c
|
@ -201,6 +201,7 @@ ram_addr_t ram_size;
|
||||||
int nb_nics;
|
int nb_nics;
|
||||||
NICInfo nd_table[MAX_NICS];
|
NICInfo nd_table[MAX_NICS];
|
||||||
int vm_running;
|
int vm_running;
|
||||||
|
static int autostart;
|
||||||
static int rtc_utc = 1;
|
static int rtc_utc = 1;
|
||||||
static int rtc_date_offset = -1; /* -1 means no change */
|
static int rtc_date_offset = -1; /* -1 means no change */
|
||||||
int cirrus_vga_enabled = 1;
|
int cirrus_vga_enabled = 1;
|
||||||
|
@ -2607,11 +2608,13 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
|
||||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||||
else if (cache == 3) /* not specified */
|
else if (cache == 3) /* not specified */
|
||||||
bdrv_flags |= BDRV_O_CACHE_DEF;
|
bdrv_flags |= BDRV_O_CACHE_DEF;
|
||||||
if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
|
if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
|
||||||
fprintf(stderr, "qemu: could not open disk image %s\n",
|
fprintf(stderr, "qemu: could not open disk image %s\n",
|
||||||
file);
|
file);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (bdrv_key_required(bdrv))
|
||||||
|
autostart = 0;
|
||||||
return drives_table_idx;
|
return drives_table_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2658,7 +2661,7 @@ int usb_device_add_dev(USBDevice *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_device_add(const char *devname)
|
static int usb_device_add(const char *devname, int is_hotplug)
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
USBDevice *dev;
|
USBDevice *dev;
|
||||||
|
@ -2675,7 +2678,18 @@ static int usb_device_add(const char *devname)
|
||||||
} else if (!strcmp(devname, "keyboard")) {
|
} else if (!strcmp(devname, "keyboard")) {
|
||||||
dev = usb_keyboard_init();
|
dev = usb_keyboard_init();
|
||||||
} else if (strstart(devname, "disk:", &p)) {
|
} else 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 if (!strcmp(devname, "wacom-tablet")) {
|
} else if (!strcmp(devname, "wacom-tablet")) {
|
||||||
dev = usb_wacom_init();
|
dev = usb_wacom_init();
|
||||||
} else if (strstart(devname, "serial:", &p)) {
|
} else if (strstart(devname, "serial:", &p)) {
|
||||||
|
@ -2756,7 +2770,7 @@ static int usb_device_del(const char *devname)
|
||||||
|
|
||||||
void do_usb_add(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)
|
void do_usb_del(const char *devname)
|
||||||
|
@ -4334,45 +4348,6 @@ static const QEMUOption qemu_options[] = {
|
||||||
{ NULL },
|
{ 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
|
#ifdef HAS_AUDIO
|
||||||
struct soundhw soundhw[] = {
|
struct soundhw soundhw[] = {
|
||||||
#ifdef HAS_AUDIO_CHOICE
|
#ifdef HAS_AUDIO_CHOICE
|
||||||
|
@ -4639,7 +4614,6 @@ int main(int argc, char **argv, char **envp)
|
||||||
int fds[2];
|
int fds[2];
|
||||||
int tb_size;
|
int tb_size;
|
||||||
const char *pid_file = NULL;
|
const char *pid_file = NULL;
|
||||||
int autostart;
|
|
||||||
const char *incoming = NULL;
|
const char *incoming = NULL;
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
struct passwd *pwd = NULL;
|
struct passwd *pwd = NULL;
|
||||||
|
@ -5637,7 +5611,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
/* init USB devices */
|
/* init USB devices */
|
||||||
if (usb_enabled) {
|
if (usb_enabled) {
|
||||||
for(i = 0; i < usb_devices_index; i++) {
|
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",
|
fprintf(stderr, "Warning: could not add USB device %s\n",
|
||||||
usb_devices[i]);
|
usb_devices[i]);
|
||||||
}
|
}
|
||||||
|
@ -5748,13 +5722,8 @@ int main(int argc, char **argv, char **envp)
|
||||||
qemu_start_incoming_migration(incoming);
|
qemu_start_incoming_migration(incoming);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (autostart)
|
||||||
/* XXX: simplify init */
|
vm_start();
|
||||||
read_passwords();
|
|
||||||
if (autostart) {
|
|
||||||
vm_start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemonize) {
|
if (daemonize) {
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
|
|
Loading…
Reference in New Issue