Hi,

Recently I needed to sandbox some software, running it inside Qemu off
of a disk image of the USB stick it came on.
However, Qemu's USB mass storage device emulation (-usbdevice disk)
shows up as a "QEMU USB HARDDRIVE" with VID:PID of 46f4:0001.
The sandboxed software didn't like that at all, and refused to run. So
I patched Qemu to take VID, PID, serial etc. from the command line
arguments, like so:
"-usbdevice 
disk:format=raw:vid=0a6b:pid=0001:manufacturer=Whoever:product=Whatever:serial=324324:/path/to/stick.img"

I'm posting the patch here for other people to find, should they
develop the same VID-faking needs.
I've read http://wiki.qemu.org/Contribute/SubmitAPatch and decided
to not post the patch to -dev as this is a one-off single-purpose
hack, not a proper solution. For instance, with this patch, adding more than one
'-usbdevice disk' type device will lead to spectacular failures. Beware!

Cheers, Wicher Minnaard
diff -Naur qemu-2.3.0_orig/hw/usb/dev-storage.c qemu-2.3.0/hw/usb/dev-storage.c
--- qemu-2.3.0_orig/hw/usb/dev-storage.c	2015-04-27 16:08:25.000000000 +0200
+++ qemu-2.3.0/hw/usb/dev-storage.c	2015-07-23 10:26:42.556779948 +0200
@@ -83,7 +83,7 @@
     STR_CONFIG_SUPER,
 };
 
-static const USBDescStrings desc_strings = {
+static USBDescStrings desc_strings = {
     [STR_MANUFACTURER] = "QEMU",
     [STR_PRODUCT]      = "QEMU USB HARDDRIVE",
     [STR_SERIALNUMBER] = "1",
@@ -199,7 +199,7 @@
     },
 };
 
-static const USBDesc desc = {
+static USBDesc desc = {
     .id = {
         .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
         .idProduct         = 0x0001,
@@ -675,7 +675,6 @@
     QemuOpts *opts;
     DriveInfo *dinfo;
     USBDevice *dev;
-    const char *p1;
     char fmt[32];
 
     /* parse -usbdevice disk: syntax into drive opts */
@@ -684,20 +683,53 @@
         opts = qemu_opts_create(qemu_find_opts("drive"), id, 1, NULL);
     } while (!opts);
 
-    p1 = strchr(filename, ':');
-    if (p1++) {
-        const char *p2;
-
-        if (strstart(filename, "format=", &p2)) {
-            int len = MIN(p1 - p2, sizeof(fmt));
-            pstrcpy(fmt, len, p2);
+    int filename_len = strlen(filename)+1;
+    char c_filename[filename_len];
+    pstrcpy(c_filename, filename_len, filename);
+    char* comp;
+    char delim = ':';
+    char subdelim = '=';
+
+    comp = strtok(c_filename, &delim); //this actually modifies the parsee in place, hence the copy.
+    while(comp){
+        const char *p;
+        if (strstart(comp, "format=", &p)) {
+            int len = MIN(comp - p, sizeof(fmt));
+            pstrcpy(fmt, len, p);
             qemu_opt_set(opts, "format", fmt, &error_abort);
-        } else if (*filename != ':') {
+        }
+        else if (strstart(comp, "vid=", &p)) {
+            desc.id.idVendor = (uint16_t) strtol(p, NULL, 16);
+        }
+        else if (strstart(comp, "pid=", &p)) {
+            desc.id.idProduct = (uint16_t) strtol(p, NULL, 16);
+        }
+        else if (strstart(comp, "manufacturer=", &p)) {
+            char* manuf = malloc(strlen(p)+1);
+            pstrcpy(manuf, strlen(p)+1, p);
+            desc_strings[STR_MANUFACTURER] = manuf;
+        }
+        else if (strstart(comp, "product=", &p)) {
+            char* product = malloc(strlen(p)+1);
+            pstrcpy(product, strlen(p)+1, p);
+            desc_strings[STR_PRODUCT] = product;
+        }
+        else if (strstart(comp, "serial=", &p)) {
+            char* serial = malloc(strlen(p)+1);
+            pstrcpy(serial, strlen(p)+1, p);
+            desc_strings[STR_SERIALNUMBER] = serial;
+        }
+        else if (index(comp, (int) subdelim) != NULL) {
             error_report("unrecognized USB mass-storage option %s", filename);
             return NULL;
         }
-        filename = p1;
+        else {
+            filename = comp;
+        }
+        comp = strtok(NULL, &delim); //advance to next token
     }
+
+
     if (!*filename) {
         error_report("block device specification needed");
         return NULL;

Reply via email to