Compare commits
278 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f92cc4a3a0 | |||
| 823c0cc7e3 | |||
| 4502524d76 | |||
| 96dfc352ed | |||
| 382105ed17 | |||
| e5fa1c00d2 | |||
| 18f7b8c79c | |||
| 782468f8e9 | |||
| 202e7d9569 | |||
| 0676a07265 | |||
| f57ce74947 | |||
| 851cfde15b | |||
| 06123137eb | |||
| 6ccf3cb58c | |||
| 030ddaa4ef | |||
| a8886736c4 | |||
| 4fd635e537 | |||
| 6210c457fc | |||
| 82926cfdf0 | |||
| e7a3ca6f6b | |||
| 1ae6f647b7 | |||
| 48941c011f | |||
| a3c4cc6f3d | |||
| 90fbcbd48f | |||
| 6efd96d995 | |||
| 21316e7a45 | |||
| 8adbb7a402 | |||
| 3f19d41908 | |||
| 34da93e0c9 | |||
| 208f506190 | |||
| 0ca715cad9 | |||
| 0f5d8c1c22 | |||
| a56bcbd063 | |||
| 89c3fa751c | |||
| 051644ffcb | |||
| 2a9c282548 | |||
| 2ae80af461 | |||
| 7335ede0e1 | |||
| 6c92ba3805 | |||
| 446f680673 | |||
| 3f56aa2870 | |||
| 3cec91694f | |||
| cb0cfa566f | |||
| a27acebf66 | |||
| 99d3a0ca1a | |||
| 9c962ebc4f | |||
| 99cbbf6606 | |||
| b73e509648 | |||
| b23ff9c0f7 | |||
| 20f9ed9c4c | |||
| 04cb28c315 | |||
| a74ea318d1 | |||
| 98ed6b4e36 | |||
| 2c49d1fd11 | |||
| 6e7bca6631 | |||
| 2fe145bb02 | |||
| 10b7d235e3 | |||
| 232e2e7de2 | |||
| fb1e4b061e | |||
| 0b1a013081 | |||
| a972457f43 | |||
| 67cfa34a05 | |||
| fc2ebb7646 | |||
| e92b461b4f | |||
| b1ac7b5791 | |||
| 88424efe85 | |||
| 4e2aab98a2 | |||
| f4bc1a2fe2 | |||
| a4bf2768b8 | |||
| 47cd44e9da | |||
| 731c6b90ff | |||
| 47ca46905d | |||
| 860ffc5b13 | |||
| 611b2ee520 | |||
| edcb926f9d | |||
| caebff8304 | |||
| 8fa41135ca | |||
| 0debbff964 | |||
| d6cc78be66 | |||
| 8d9645735e | |||
| 4c65f08330 | |||
| 2427f8f078 | |||
| d168e4f934 | |||
| 4dd365589f | |||
| 50e253df29 | |||
| cb71801a2b | |||
| 4a9c74e91d | |||
| 281508ec99 | |||
| feb92626e1 | |||
| 93cadb0880 | |||
| dd6b57aa60 | |||
| b8cb754e9d | |||
| dbe61507bd | |||
| ce7b23d9d0 | |||
| 8ded6ff93e | |||
| 1ef96f3488 | |||
| ee3bf37900 | |||
| 7452a06938 | |||
| fe8f9ed9c4 | |||
| 1b64f74c82 | |||
| c81949046d | |||
| 19dcb913e6 | |||
| e4b5ba1a9d | |||
| 5f1a422d83 | |||
| c5b0b3ef9d | |||
| c0a04cb876 | |||
| 3cc7cdf12f | |||
| 6b531d9967 | |||
| 4d05ac021c | |||
| d29aa84b17 | |||
| a075adc818 | |||
| 4d0e63f99c | |||
| 9e11936ec5 | |||
| a4075ec632 | |||
| dadb59c95f | |||
| e73cc6a9d8 | |||
| 10cd84e37f | |||
| e63e2040cd | |||
| 91063332d7 | |||
| 503330ba5d | |||
| 0a64085f47 | |||
| 1073e2447a | |||
| 5b1a906ace | |||
| aff97e0146 | |||
| a4b41a378b | |||
| 3ec523d168 | |||
| 622cf0d642 | |||
| a540751e83 | |||
| 11b596669a | |||
| fefbae879b | |||
| 695b281409 | |||
| 9f9eae34c1 | |||
| ae37ed3500 | |||
| f7f509999b | |||
| 419bcc4b2f | |||
| 7b59d4f7eb | |||
| 03326e9c04 | |||
| f40b464d1e | |||
| 810ca6c207 | |||
| 8df3aef6aa | |||
| 0223d5a656 | |||
| aad810a204 | |||
| 1b8b7567b1 | |||
| 442040caac | |||
| 65efaafca2 | |||
| e87c8ab0c7 | |||
| be6bda45b4 | |||
| 8c9e40d383 | |||
| 0f6f9b973a | |||
| 3db6039b2b | |||
| 4051217c8b | |||
| c5c28baba1 | |||
| 43618df1d4 | |||
| a2951dccb5 | |||
| b884323c03 | |||
| adeaf839fd | |||
| 40d99010e1 | |||
| 11755d8663 | |||
| 2daa92daf9 | |||
| db2858c661 | |||
| 53adb9aaba | |||
| 168df8b606 | |||
| f9085f2538 | |||
| b159bbdc98 | |||
| a5af3cf105 | |||
| 27ca069db7 | |||
| 000a3274d2 | |||
| 19c7799c31 | |||
| 198ff818c6 | |||
| e80c83ad06 | |||
| 660e0112c6 | |||
| 45c1cabef6 | |||
| 56be2c5e38 | |||
| 4aa9c4f1a3 | |||
| 7be420ad22 | |||
| 40b00623a4 | |||
| ce09ec66c7 | |||
| 97d7c80e2e | |||
| b856ae03bf | |||
| 803b3b891a | |||
| 350081d1a9 | |||
| 1b71b68bb9 | |||
| 4084288dd5 | |||
| d1cd1b7ceb | |||
| 5ed69704b9 | |||
| be6e136cb1 | |||
| d3109abfa4 | |||
| f5ff4a2393 | |||
| 8cc50838dc | |||
| 2c2e71c0ce | |||
| 96b1b18b42 | |||
| f7763bfd17 | |||
| 404e58cb18 | |||
| cd3767e3b9 | |||
| f1867a5ecc | |||
| b5548f62cb | |||
| 52f3bedee7 | |||
| f87237919c | |||
| e8969fb913 | |||
| 74d46bc7dd | |||
| 4b6ea94306 | |||
| 963754bc8c | |||
| 7b5483236c | |||
| 438006407c | |||
| 76c8282ee2 | |||
| f463598b24 | |||
| f4e752a385 | |||
| c37cb21dea | |||
| e0bfc1f8aa | |||
| 544ad4a787 | |||
| 8f163760ed | |||
| 565427cf89 | |||
| e10da2f6d4 | |||
| aa386576d5 | |||
| c73c129b48 | |||
| afe729ac3c | |||
| b6038bae4f | |||
| e6d9787587 | |||
| 44699dc495 | |||
| 991d719dde | |||
| 96a520b555 | |||
| e31df5e9de | |||
| 6763b267b9 | |||
| 24e91208a4 | |||
| 15dec999e7 | |||
| d6b0635d3d | |||
| 336a93264e | |||
| 6398d1cff5 | |||
| 6926ed26ea | |||
| 6253f97a2d | |||
| 37ddbd0eac | |||
| 95fe7c8df2 | |||
| 79ae809020 | |||
| f19e302ba9 | |||
| e9c1d3f4b0 | |||
| 0f577d932b | |||
| 21a02c2e90 | |||
| 4e460d5f09 | |||
| f9de2f6bc6 | |||
| 2daa1b7814 | |||
| f99eeb8567 | |||
| 7069f75cb8 | |||
| 2cac7dac46 | |||
| 913c3c6554 | |||
| a5a4c0c89b | |||
| 8c8aca2fab | |||
| daf8e124ca | |||
| 38c4b724fe | |||
| 4d00487275 | |||
| a6831c26c1 | |||
| c363c7ebdb | |||
| 18ee6daf8a | |||
| 459eb426c3 | |||
| a0d670d2bf | |||
| d7b41212c1 | |||
| 2e1539eba4 | |||
| ee9521d87c | |||
| 8d8fc08bac | |||
| e79d304c79 | |||
| db03f03fd9 | |||
| 957403ebec | |||
| 6c32e1aaeb | |||
| 362e335c0b | |||
| ed6c49f874 | |||
| 47fcec5405 | |||
| d7239a45b6 | |||
| f13fb18c58 | |||
| d29644418d | |||
| ed9e426b26 | |||
| 659febf9ff | |||
| fca1fccfad | |||
| f713d63bab | |||
| 5a45e466cf | |||
| 742b24eb23 | |||
| 03369d2383 | |||
| 2605d662e0 | |||
| e8394ab5b5 | |||
| 8ad156a5c2 |
@@ -2,4 +2,4 @@
|
||||
*.rpm
|
||||
i686
|
||||
x86_64
|
||||
libvirt-*.tar.gz
|
||||
libvirt-*.tar.xz
|
||||
@@ -0,0 +1,112 @@
|
||||
From: Andrea Bolognani <abologna@redhat.com>
|
||||
Date: Wed, 27 Feb 2019 18:41:35 +0100
|
||||
Subject: [PATCH] qemu: Allow creating ppc64 guests with graphics and no USB
|
||||
mouse
|
||||
|
||||
The existing behavior for ppc64 guests is to always add a USB
|
||||
keyboard and mouse combo if graphics are present; unfortunately,
|
||||
this means any attempt to use a USB tablet will cause both pointing
|
||||
devices to show up in the guest, which in turn will result in poor
|
||||
user experience.
|
||||
|
||||
We can't just stop adding the USB mouse or start adding a USB tablet
|
||||
instead, because existing applications and users might rely on the
|
||||
current behavior; however, we can avoid adding the USB mouse if a USB
|
||||
tablet is already present, thus allowing users and applications to
|
||||
create guests that contain a single pointing device.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1683681
|
||||
|
||||
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
||||
Reviewed-by: Cole Robinson <crobinso@redhat.com>
|
||||
(cherry picked from commit 186bb479d0f409dc75175bea48a760838c479a6c)
|
||||
---
|
||||
src/qemu/qemu_domain.c | 20 ++++++++
|
||||
.../ppc64-pseries-graphics.ppc64-latest.args | 47 +++++++++++++++++++
|
||||
2 files changed, 67 insertions(+)
|
||||
create mode 100644 tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args
|
||||
|
||||
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
||||
index f161cf6c84..764ffacb2e 100644
|
||||
--- a/src/qemu/qemu_domain.c
|
||||
+++ b/src/qemu/qemu_domain.c
|
||||
@@ -3384,6 +3384,26 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def,
|
||||
def->memballoon = memballoon;
|
||||
}
|
||||
|
||||
+ if (addDefaultUSBMouse) {
|
||||
+ bool hasUSBTablet = false;
|
||||
+ size_t j;
|
||||
+
|
||||
+ for (j = 0; j < def->ninputs; j++) {
|
||||
+ if (def->inputs[j]->type == VIR_DOMAIN_INPUT_TYPE_TABLET &&
|
||||
+ def->inputs[j]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
|
||||
+ hasUSBTablet = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Historically, we have automatically added USB keyboard and
|
||||
+ * mouse to some guests. While the former device is generally
|
||||
+ * safe to have, adding the latter is undesiderable if a USB
|
||||
+ * tablet is already present in the guest */
|
||||
+ if (hasUSBTablet)
|
||||
+ addDefaultUSBMouse = false;
|
||||
+ }
|
||||
+
|
||||
if (addDefaultUSBKBD &&
|
||||
def->ngraphics > 0 &&
|
||||
virDomainDefMaybeAddInput(def,
|
||||
diff --git a/tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args b/tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args
|
||||
new file mode 100644
|
||||
index 0000000000..b81648f078
|
||||
--- /dev/null
|
||||
+++ b/tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args
|
||||
@@ -0,0 +1,47 @@
|
||||
+LC_ALL=C \
|
||||
+PATH=/bin \
|
||||
+HOME=/home/test \
|
||||
+USER=test \
|
||||
+LOGNAME=test \
|
||||
+QEMU_AUDIO_DRV=none \
|
||||
+/usr/bin/qemu-system-ppc64 \
|
||||
+-name guest=guest,debug-threads=on \
|
||||
+-S \
|
||||
+-object secret,id=masterKey0,format=raw,\
|
||||
+file=/tmp/lib/domain--1-guest/master-key.aes \
|
||||
+-machine pseries,accel=tcg,usb=off,dump-guest-core=off \
|
||||
+-m 4096 \
|
||||
+-realtime mlock=off \
|
||||
+-smp 4,sockets=4,cores=1,threads=1 \
|
||||
+-uuid b35969f7-e7cf-4d90-a9a0-4dd9000f9824 \
|
||||
+-no-user-config \
|
||||
+-nodefaults \
|
||||
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
|
||||
+-mon chardev=charmonitor,id=monitor,mode=control \
|
||||
+-rtc base=utc \
|
||||
+-no-shutdown \
|
||||
+-boot strict=on \
|
||||
+-device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.0,addr=0x2 \
|
||||
+-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 \
|
||||
+-drive file=/var/lib/libvirt/images/guest.qcow2,format=qcow2,if=none,\
|
||||
+id=drive-virtio-disk0 \
|
||||
+-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,\
|
||||
+id=virtio-disk0,bootindex=1 \
|
||||
+-netdev user,id=hostnet0 \
|
||||
+-device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:a2:44:92,bus=pci.0,\
|
||||
+addr=0x1 \
|
||||
+-chardev pty,id=charserial0 \
|
||||
+-device spapr-vty,chardev=charserial0,id=serial0,reg=0x30000000 \
|
||||
+-chardev socket,id=charchannel0,fd=1729,server,nowait \
|
||||
+-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,\
|
||||
+id=channel0,name=org.qemu.guest_agent.0 \
|
||||
+-device usb-tablet,id=input0,bus=usb.0,port=1 \
|
||||
+-device usb-kbd,id=input1,bus=usb.0,port=2 \
|
||||
+-vnc 127.0.0.1:0 \
|
||||
+-device VGA,id=video0,vgamem_mb=16,bus=pci.0,addr=0x7 \
|
||||
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 \
|
||||
+-object rng-random,id=objrng0,filename=/dev/urandom \
|
||||
+-device virtio-rng-pci,rng=objrng0,id=rng0,bus=pci.0,addr=0x6 \
|
||||
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
|
||||
+resourcecontrol=deny \
|
||||
+-msg timestamp=on
|
||||
@@ -0,0 +1,34 @@
|
||||
From: John Ferlan <jferlan@redhat.com>
|
||||
Date: Fri, 7 Sep 2018 16:01:27 -0400
|
||||
Subject: [PATCH] qemu: Remove duplicated qemuAgentCheckError
|
||||
|
||||
Commit 5b3492fadb moved qemuAgentCheckError calls into
|
||||
qemuAgentCommand for various reasons; however, subsequent
|
||||
commit 0977b8aa0 adding a new command made call again
|
||||
So let's just remove the duplicitous call from
|
||||
qemuAgentGetInterfaces.
|
||||
|
||||
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
||||
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
(cherry picked from commit 9ed175fbc2deecfdaeabca7bc77c7e7ae33a3377)
|
||||
---
|
||||
src/qemu/qemu_agent.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
|
||||
index bf08871f18..d235c058a5 100644
|
||||
--- a/src/qemu/qemu_agent.c
|
||||
+++ b/src/qemu/qemu_agent.c
|
||||
@@ -1987,10 +1987,9 @@ qemuAgentGetInterfaces(qemuAgentPtr mon,
|
||||
if (!(cmd = qemuAgentMakeCommand("guest-network-get-interfaces", NULL)))
|
||||
goto cleanup;
|
||||
|
||||
- if (qemuAgentCommand(mon, cmd, &reply, false, VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0 ||
|
||||
- qemuAgentCheckError(cmd, reply) < 0) {
|
||||
+ if (qemuAgentCommand(mon, cmd, &reply, false,
|
||||
+ VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
|
||||
goto cleanup;
|
||||
- }
|
||||
|
||||
if (!(ret_array = virJSONValueObjectGet(reply, "return"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
@@ -0,0 +1,40 @@
|
||||
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
|
||||
Date: Fri, 4 Jan 2019 10:17:46 +0100
|
||||
Subject: [PATCH] qemu: require reply from guest agent in
|
||||
qemuAgentGetInterfaces
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Since its introduction in commit 0977b8aa071 (released in v1.2.14)
|
||||
qemuAgentGetInterfaces calls qemuAgentCommand with needReply=false,
|
||||
which allows qemuAgentCommand to return 0 even when it did not get
|
||||
any reply from the agent.
|
||||
|
||||
Set needReply to true, since we dereference it right after.
|
||||
|
||||
This can be hit if libvirt is waiting for an event from the agent
|
||||
(e.g. shutdown) and the agent cannot reply in time (e.g. due to
|
||||
the guest being shut down), as reported in:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1663051
|
||||
|
||||
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
||||
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit 7cfd1fbb1332ae5df678b9f41a62156cb2e88c73)
|
||||
---
|
||||
src/qemu/qemu_agent.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
|
||||
index d235c058a5..af0c054f99 100644
|
||||
--- a/src/qemu/qemu_agent.c
|
||||
+++ b/src/qemu/qemu_agent.c
|
||||
@@ -1987,7 +1987,7 @@ qemuAgentGetInterfaces(qemuAgentPtr mon,
|
||||
if (!(cmd = qemuAgentMakeCommand("guest-network-get-interfaces", NULL)))
|
||||
goto cleanup;
|
||||
|
||||
- if (qemuAgentCommand(mon, cmd, &reply, false,
|
||||
+ if (qemuAgentCommand(mon, cmd, &reply, true,
|
||||
VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
|
||||
goto cleanup;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Apr 2019 11:33:32 +0200
|
||||
Subject: [PATCH] cpu_x86: Do not cache microcode version
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The microcode version checks are used to invalidate cached CPU data we
|
||||
get from QEMU. To minimize /proc/cpuinfo parsing the microcode version
|
||||
was only read when libvirtd started and cached for the daemon's
|
||||
lifetime. However, the CPU microcode can change anytime (updating the
|
||||
microcode package can automatically upload it to the CPU) and we need to
|
||||
stop caching it to avoid using stale CPU model data.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit be46f613261d3b655a1f15afd635087e68a9c39b)
|
||||
---
|
||||
src/cpu/cpu_x86.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
||||
index cb27550025..ce48ca6867 100644
|
||||
--- a/src/cpu/cpu_x86.c
|
||||
+++ b/src/cpu/cpu_x86.c
|
||||
@@ -163,7 +163,6 @@ struct _virCPUx86Map {
|
||||
};
|
||||
|
||||
static virCPUx86MapPtr cpuMap;
|
||||
-static unsigned int microcodeVersion;
|
||||
|
||||
int virCPUx86DriverOnceInit(void);
|
||||
VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
|
||||
@@ -1331,8 +1330,6 @@ virCPUx86DriverOnceInit(void)
|
||||
if (!(cpuMap = virCPUx86LoadMap()))
|
||||
return -1;
|
||||
|
||||
- microcodeVersion = virHostCPUGetMicrocodeVersion();
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2372,7 +2369,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
||||
goto cleanup;
|
||||
|
||||
ret = x86DecodeCPUData(cpu, cpuData, models);
|
||||
- cpu->microcodeVersion = microcodeVersion;
|
||||
+ cpu->microcodeVersion = virHostCPUGetMicrocodeVersion();
|
||||
|
||||
cleanup:
|
||||
virCPUx86DataFree(cpuData);
|
||||
@@ -0,0 +1,147 @@
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 12 Apr 2019 21:21:05 +0200
|
||||
Subject: [PATCH] qemu: Don't cache microcode version
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
My earlier commit be46f61326 was incomplete. It removed caching of
|
||||
microcode version in the CPU driver, which means the capabilities XML
|
||||
will see the correct microcode version. But it is also cached in the
|
||||
QEMU capabilities cache where it is used to detect whether we need to
|
||||
reprobe QEMU. By missing the second place, the original commit
|
||||
be46f61326 made the situation even worse since libvirt would report
|
||||
correct microcode version while still using the old host CPU model
|
||||
(visible in domain capabilities XML).
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
(cherry picked from commit 673c62a3b7855a0685d8f116e227c402720b9ee9)
|
||||
|
||||
Conflicts:
|
||||
src/qemu/qemu_capabilities.c
|
||||
- virQEMUCapsCacheLookupByArch refactoring (commits
|
||||
7948ad4129a and 1a3de67001c) are missing
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
---
|
||||
src/qemu/qemu_capabilities.c | 12 ++++++++----
|
||||
src/qemu/qemu_capabilities.h | 3 +--
|
||||
src/qemu/qemu_driver.c | 9 +--------
|
||||
tests/testutilsqemu.c | 2 +-
|
||||
4 files changed, 11 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
||||
index a075677421..eaf369f5b1 100644
|
||||
--- a/src/qemu/qemu_capabilities.c
|
||||
+++ b/src/qemu/qemu_capabilities.c
|
||||
@@ -4700,7 +4700,7 @@ virQEMUCapsNewData(const char *binary,
|
||||
priv->libDir,
|
||||
priv->runUid,
|
||||
priv->runGid,
|
||||
- priv->microcodeVersion,
|
||||
+ virHostCPUGetMicrocodeVersion(),
|
||||
priv->kernelVersion);
|
||||
}
|
||||
|
||||
@@ -4783,8 +4783,7 @@ virFileCachePtr
|
||||
virQEMUCapsCacheNew(const char *libDir,
|
||||
const char *cacheDir,
|
||||
uid_t runUid,
|
||||
- gid_t runGid,
|
||||
- unsigned int microcodeVersion)
|
||||
+ gid_t runGid)
|
||||
{
|
||||
char *capsCacheDir = NULL;
|
||||
virFileCachePtr cache = NULL;
|
||||
@@ -4808,7 +4807,6 @@ virQEMUCapsCacheNew(const char *libDir,
|
||||
|
||||
priv->runUid = runUid;
|
||||
priv->runGid = runGid;
|
||||
- priv->microcodeVersion = microcodeVersion;
|
||||
|
||||
if (uname(&uts) == 0 &&
|
||||
virAsprintf(&priv->kernelVersion, "%s %s", uts.release, uts.version) < 0)
|
||||
@@ -4829,8 +4827,11 @@ virQEMUCapsPtr
|
||||
virQEMUCapsCacheLookup(virFileCachePtr cache,
|
||||
const char *binary)
|
||||
{
|
||||
+ virQEMUCapsCachePrivPtr priv = virFileCacheGetPriv(cache);
|
||||
virQEMUCapsPtr ret = NULL;
|
||||
|
||||
+ priv->microcodeVersion = virHostCPUGetMicrocodeVersion();
|
||||
+
|
||||
ret = virFileCacheLookup(cache, binary);
|
||||
|
||||
VIR_DEBUG("Returning caps %p for %s", ret, binary);
|
||||
@@ -4876,10 +4877,13 @@ virQEMUCapsPtr
|
||||
virQEMUCapsCacheLookupByArch(virFileCachePtr cache,
|
||||
virArch arch)
|
||||
{
|
||||
+ virQEMUCapsCachePrivPtr priv = virFileCacheGetPriv(cache);
|
||||
virQEMUCapsPtr ret = NULL;
|
||||
virArch target;
|
||||
struct virQEMUCapsSearchData data = { .arch = arch };
|
||||
|
||||
+ priv->microcodeVersion = virHostCPUGetMicrocodeVersion();
|
||||
+
|
||||
ret = virFileCacheLookupByFunc(cache, virQEMUCapsCompareArch, &data);
|
||||
if (!ret) {
|
||||
/* If the first attempt at finding capabilities has failed, try
|
||||
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
|
||||
index 3d3a978759..956babc7eb 100644
|
||||
--- a/src/qemu/qemu_capabilities.h
|
||||
+++ b/src/qemu/qemu_capabilities.h
|
||||
@@ -574,8 +574,7 @@ void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
|
||||
virFileCachePtr virQEMUCapsCacheNew(const char *libDir,
|
||||
const char *cacheDir,
|
||||
uid_t uid,
|
||||
- gid_t gid,
|
||||
- unsigned int microcodeVersion);
|
||||
+ gid_t gid);
|
||||
virQEMUCapsPtr virQEMUCapsCacheLookup(virFileCachePtr cache,
|
||||
const char *binary);
|
||||
virQEMUCapsPtr virQEMUCapsCacheLookupCopy(virFileCachePtr cache,
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index a0f7c71675..75f8699e7d 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -592,8 +592,6 @@ qemuStateInitialize(bool privileged,
|
||||
char *hugepagePath = NULL;
|
||||
char *memoryBackingPath = NULL;
|
||||
size_t i;
|
||||
- virCPUDefPtr hostCPU = NULL;
|
||||
- unsigned int microcodeVersion = 0;
|
||||
|
||||
if (VIR_ALLOC(qemu_driver) < 0)
|
||||
return -1;
|
||||
@@ -813,15 +811,10 @@ qemuStateInitialize(bool privileged,
|
||||
run_gid = cfg->group;
|
||||
}
|
||||
|
||||
- if ((hostCPU = virCPUProbeHost(virArchFromHost())))
|
||||
- microcodeVersion = hostCPU->microcodeVersion;
|
||||
- virCPUDefFree(hostCPU);
|
||||
-
|
||||
qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
|
||||
cfg->cacheDir,
|
||||
run_uid,
|
||||
- run_gid,
|
||||
- microcodeVersion);
|
||||
+ run_gid);
|
||||
if (!qemu_driver->qemuCapsCache)
|
||||
goto error;
|
||||
|
||||
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
|
||||
index 8438613f28..4e53f03f9e 100644
|
||||
--- a/tests/testutilsqemu.c
|
||||
+++ b/tests/testutilsqemu.c
|
||||
@@ -707,7 +707,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
|
||||
|
||||
/* Using /dev/null for libDir and cacheDir automatically produces errors
|
||||
* upon attempt to use any of them */
|
||||
- driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0, 0);
|
||||
+ driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0);
|
||||
if (!driver->qemuCapsCache)
|
||||
goto error;
|
||||
|
||||
@@ -0,0 +1,880 @@
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Apr 2019 11:19:30 +0200
|
||||
Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) CPU E3-1225 v5
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit 5cd9db3ac11e88846cbcf95fad9f6fae9d880dee)
|
||||
|
||||
CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
|
||||
|
||||
Conflicts:
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
- intel-pt feature is missing
|
||||
- stibp feature is missing
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
---
|
||||
tests/cputest.c | 1 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5-disabled.xml | 7 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml | 8 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5-guest.xml | 26 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5-host.xml | 27 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5-json.xml | 10 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5.json | 652 ++++++++++++++++++
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5.sig | 4 +
|
||||
.../x86_64-cpuid-Xeon-E3-1225-v5.xml | 47 ++
|
||||
9 files changed, 782 insertions(+)
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-disabled.xml
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.json
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.sig
|
||||
create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.xml
|
||||
|
||||
diff --git a/tests/cputest.c b/tests/cputest.c
|
||||
index baf2b3c648..fbb2a86af8 100644
|
||||
--- a/tests/cputest.c
|
||||
+++ b/tests/cputest.c
|
||||
@@ -1190,6 +1190,7 @@ mymain(void)
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Phenom-B95", JSON_HOST);
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", JSON_HOST);
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", JSON_NONE);
|
||||
+ DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1225-v5", JSON_MODELS);
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245-v5", JSON_MODELS);
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2609-v3", JSON_MODELS);
|
||||
DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2623-v4", JSON_MODELS);
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-disabled.xml
|
||||
new file mode 100644
|
||||
index 0000000000..ce51903e53
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-disabled.xml
|
||||
@@ -0,0 +1,7 @@
|
||||
+<!-- Features disabled by QEMU -->
|
||||
+<cpudata arch='x86'>
|
||||
+ <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1fc' edx='0xb0600000'/>
|
||||
+ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
|
||||
+</cpudata>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
new file mode 100644
|
||||
index 0000000000..0deca9fba6
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
@@ -0,0 +1,8 @@
|
||||
+<!-- Features enabled by QEMU -->
|
||||
+<cpudata arch='x86'>
|
||||
+ <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
|
||||
+ <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000000' edx='0x8c000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000007' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
|
||||
+</cpudata>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
new file mode 100644
|
||||
index 0000000000..993db80cc9
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
@@ -0,0 +1,26 @@
|
||||
+<cpu mode='custom' match='exact'>
|
||||
+ <model fallback='forbid'>Skylake-Client-IBRS</model>
|
||||
+ <vendor>Intel</vendor>
|
||||
+ <feature policy='require' name='ds'/>
|
||||
+ <feature policy='require' name='acpi'/>
|
||||
+ <feature policy='require' name='ss'/>
|
||||
+ <feature policy='require' name='ht'/>
|
||||
+ <feature policy='require' name='tm'/>
|
||||
+ <feature policy='require' name='pbe'/>
|
||||
+ <feature policy='require' name='dtes64'/>
|
||||
+ <feature policy='require' name='monitor'/>
|
||||
+ <feature policy='require' name='ds_cpl'/>
|
||||
+ <feature policy='require' name='vmx'/>
|
||||
+ <feature policy='require' name='smx'/>
|
||||
+ <feature policy='require' name='est'/>
|
||||
+ <feature policy='require' name='tm2'/>
|
||||
+ <feature policy='require' name='xtpr'/>
|
||||
+ <feature policy='require' name='pdcm'/>
|
||||
+ <feature policy='require' name='osxsave'/>
|
||||
+ <feature policy='require' name='tsc_adjust'/>
|
||||
+ <feature policy='require' name='clflushopt'/>
|
||||
+ <feature policy='require' name='ssbd'/>
|
||||
+ <feature policy='require' name='xsaves'/>
|
||||
+ <feature policy='require' name='pdpe1gb'/>
|
||||
+ <feature policy='require' name='invtsc'/>
|
||||
+</cpu>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
new file mode 100644
|
||||
index 0000000000..074a39ba1d
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
@@ -0,0 +1,27 @@
|
||||
+<cpu>
|
||||
+ <arch>x86_64</arch>
|
||||
+ <model>Skylake-Client-IBRS</model>
|
||||
+ <vendor>Intel</vendor>
|
||||
+ <feature name='ds'/>
|
||||
+ <feature name='acpi'/>
|
||||
+ <feature name='ss'/>
|
||||
+ <feature name='ht'/>
|
||||
+ <feature name='tm'/>
|
||||
+ <feature name='pbe'/>
|
||||
+ <feature name='dtes64'/>
|
||||
+ <feature name='monitor'/>
|
||||
+ <feature name='ds_cpl'/>
|
||||
+ <feature name='vmx'/>
|
||||
+ <feature name='smx'/>
|
||||
+ <feature name='est'/>
|
||||
+ <feature name='tm2'/>
|
||||
+ <feature name='xtpr'/>
|
||||
+ <feature name='pdcm'/>
|
||||
+ <feature name='osxsave'/>
|
||||
+ <feature name='tsc_adjust'/>
|
||||
+ <feature name='clflushopt'/>
|
||||
+ <feature name='ssbd'/>
|
||||
+ <feature name='xsaves'/>
|
||||
+ <feature name='pdpe1gb'/>
|
||||
+ <feature name='invtsc'/>
|
||||
+</cpu>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
new file mode 100644
|
||||
index 0000000000..1984bd4cf2
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
@@ -0,0 +1,10 @@
|
||||
+<cpu mode='custom' match='exact'>
|
||||
+ <model fallback='forbid'>Skylake-Client-IBRS</model>
|
||||
+ <vendor>Intel</vendor>
|
||||
+ <feature policy='require' name='ss'/>
|
||||
+ <feature policy='require' name='hypervisor'/>
|
||||
+ <feature policy='require' name='tsc_adjust'/>
|
||||
+ <feature policy='require' name='clflushopt'/>
|
||||
+ <feature policy='require' name='ssbd'/>
|
||||
+ <feature policy='require' name='pdpe1gb'/>
|
||||
+</cpu>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.json b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.json
|
||||
new file mode 100644
|
||||
index 0000000000..084747556b
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.json
|
||||
@@ -0,0 +1,652 @@
|
||||
+{
|
||||
+ "return": {
|
||||
+ "model": {
|
||||
+ "name": "base",
|
||||
+ "props": {
|
||||
+ "phys-bits": 0,
|
||||
+ "core-id": -1,
|
||||
+ "xlevel": 2147483656,
|
||||
+ "cmov": true,
|
||||
+ "ia64": false,
|
||||
+ "aes": true,
|
||||
+ "mmx": true,
|
||||
+ "rdpid": false,
|
||||
+ "arat": true,
|
||||
+ "gfni": false,
|
||||
+ "pause-filter": false,
|
||||
+ "xsavec": true,
|
||||
+ "intel-pt": false,
|
||||
+ "osxsave": false,
|
||||
+ "hv-frequencies": false,
|
||||
+ "tsc-frequency": 0,
|
||||
+ "xd": true,
|
||||
+ "hv-vendor-id": "",
|
||||
+ "kvm-asyncpf": true,
|
||||
+ "kvm_asyncpf": true,
|
||||
+ "perfctr_core": false,
|
||||
+ "perfctr-core": false,
|
||||
+ "mpx": true,
|
||||
+ "pbe": false,
|
||||
+ "decodeassists": false,
|
||||
+ "avx512cd": false,
|
||||
+ "sse4_1": true,
|
||||
+ "sse4.1": true,
|
||||
+ "sse4-1": true,
|
||||
+ "family": 6,
|
||||
+ "legacy-cache": true,
|
||||
+ "vmware-cpuid-freq": true,
|
||||
+ "avx512f": false,
|
||||
+ "msr": true,
|
||||
+ "mce": true,
|
||||
+ "mca": true,
|
||||
+ "hv-runtime": false,
|
||||
+ "xcrypt": false,
|
||||
+ "thread-id": -1,
|
||||
+ "min-level": 13,
|
||||
+ "xgetbv1": true,
|
||||
+ "cid": false,
|
||||
+ "hv-relaxed": false,
|
||||
+ "hv-crash": false,
|
||||
+ "ds": false,
|
||||
+ "fxsr": true,
|
||||
+ "xsaveopt": true,
|
||||
+ "xtpr": false,
|
||||
+ "avx512vl": false,
|
||||
+ "avx512-vpopcntdq": false,
|
||||
+ "phe": false,
|
||||
+ "extapic": false,
|
||||
+ "3dnowprefetch": true,
|
||||
+ "avx512vbmi2": false,
|
||||
+ "cr8legacy": false,
|
||||
+ "stibp": true,
|
||||
+ "cpuid-0xb": true,
|
||||
+ "xcrypt-en": false,
|
||||
+ "kvm_pv_eoi": true,
|
||||
+ "apic-id": 4294967295,
|
||||
+ "pn": false,
|
||||
+ "dca": false,
|
||||
+ "vendor": "GenuineIntel",
|
||||
+ "pku": false,
|
||||
+ "smx": false,
|
||||
+ "cmp_legacy": false,
|
||||
+ "cmp-legacy": false,
|
||||
+ "node-id": -1,
|
||||
+ "avx512-4fmaps": false,
|
||||
+ "vmcb_clean": false,
|
||||
+ "vmcb-clean": false,
|
||||
+ "3dnowext": false,
|
||||
+ "hle": true,
|
||||
+ "npt": false,
|
||||
+ "memory": "/machine/unattached/system[0]",
|
||||
+ "clwb": false,
|
||||
+ "lbrv": false,
|
||||
+ "adx": true,
|
||||
+ "ss": true,
|
||||
+ "pni": true,
|
||||
+ "svm_lock": false,
|
||||
+ "svm-lock": false,
|
||||
+ "pfthreshold": false,
|
||||
+ "smep": true,
|
||||
+ "smap": true,
|
||||
+ "x2apic": true,
|
||||
+ "avx512vbmi": false,
|
||||
+ "avx512vnni": false,
|
||||
+ "hv-stimer": false,
|
||||
+ "i64": true,
|
||||
+ "flushbyasid": false,
|
||||
+ "f16c": true,
|
||||
+ "ace2-en": false,
|
||||
+ "pat": true,
|
||||
+ "pae": true,
|
||||
+ "sse": true,
|
||||
+ "phe-en": false,
|
||||
+ "kvm_nopiodelay": true,
|
||||
+ "kvm-nopiodelay": true,
|
||||
+ "tm": false,
|
||||
+ "kvmclock-stable-bit": true,
|
||||
+ "hypervisor": true,
|
||||
+ "socket-id": -1,
|
||||
+ "pcommit": false,
|
||||
+ "syscall": true,
|
||||
+ "level": 13,
|
||||
+ "avx512dq": false,
|
||||
+ "svm": false,
|
||||
+ "full-cpuid-auto-level": true,
|
||||
+ "hv-reset": false,
|
||||
+ "invtsc": false,
|
||||
+ "sse3": true,
|
||||
+ "sse2": true,
|
||||
+ "ssbd": true,
|
||||
+ "est": false,
|
||||
+ "avx512ifma": false,
|
||||
+ "tm2": false,
|
||||
+ "kvm-pv-eoi": true,
|
||||
+ "cx8": true,
|
||||
+ "kvm_mmu": false,
|
||||
+ "kvm-mmu": false,
|
||||
+ "sse4_2": true,
|
||||
+ "sse4.2": true,
|
||||
+ "sse4-2": true,
|
||||
+ "pge": true,
|
||||
+ "fill-mtrr-mask": true,
|
||||
+ "avx512bitalg": false,
|
||||
+ "nodeid_msr": false,
|
||||
+ "pdcm": false,
|
||||
+ "movbe": true,
|
||||
+ "model": 94,
|
||||
+ "nrip_save": false,
|
||||
+ "nrip-save": false,
|
||||
+ "kvm_pv_unhalt": true,
|
||||
+ "ssse3": true,
|
||||
+ "sse4a": false,
|
||||
+ "invpcid": true,
|
||||
+ "pdpe1gb": true,
|
||||
+ "tsc-deadline": true,
|
||||
+ "fma": true,
|
||||
+ "cx16": true,
|
||||
+ "de": true,
|
||||
+ "enforce": false,
|
||||
+ "stepping": 3,
|
||||
+ "xsave": true,
|
||||
+ "clflush": true,
|
||||
+ "skinit": false,
|
||||
+ "tsc": true,
|
||||
+ "tce": false,
|
||||
+ "fpu": true,
|
||||
+ "ibs": false,
|
||||
+ "ds_cpl": false,
|
||||
+ "ds-cpl": false,
|
||||
+ "host-phys-bits": true,
|
||||
+ "fma4": false,
|
||||
+ "la57": false,
|
||||
+ "osvw": false,
|
||||
+ "check": true,
|
||||
+ "hv-spinlocks": -1,
|
||||
+ "pmu": false,
|
||||
+ "pmm": false,
|
||||
+ "apic": true,
|
||||
+ "spec-ctrl": true,
|
||||
+ "min-xlevel2": 0,
|
||||
+ "tsc-adjust": true,
|
||||
+ "tsc_adjust": true,
|
||||
+ "kvm-steal-time": true,
|
||||
+ "kvm_steal_time": true,
|
||||
+ "kvmclock": true,
|
||||
+ "l3-cache": true,
|
||||
+ "lwp": false,
|
||||
+ "ibpb": false,
|
||||
+ "xop": false,
|
||||
+ "avx": true,
|
||||
+ "ospke": false,
|
||||
+ "ace2": false,
|
||||
+ "avx512bw": false,
|
||||
+ "acpi": false,
|
||||
+ "hv-vapic": false,
|
||||
+ "fsgsbase": true,
|
||||
+ "ht": false,
|
||||
+ "nx": true,
|
||||
+ "pclmulqdq": true,
|
||||
+ "mmxext": false,
|
||||
+ "vaes": false,
|
||||
+ "popcnt": true,
|
||||
+ "xsaves": false,
|
||||
+ "tcg-cpuid": true,
|
||||
+ "lm": true,
|
||||
+ "umip": false,
|
||||
+ "pse": true,
|
||||
+ "avx2": true,
|
||||
+ "sep": true,
|
||||
+ "pclmuldq": true,
|
||||
+ "virt-ssbd": false,
|
||||
+ "x-hv-max-vps": -1,
|
||||
+ "nodeid-msr": false,
|
||||
+ "md-clear": true,
|
||||
+ "kvm": true,
|
||||
+ "misalignsse": false,
|
||||
+ "min-xlevel": 2147483656,
|
||||
+ "kvm-pv-unhalt": true,
|
||||
+ "bmi2": true,
|
||||
+ "bmi1": true,
|
||||
+ "realized": false,
|
||||
+ "tsc_scale": false,
|
||||
+ "tsc-scale": false,
|
||||
+ "topoext": false,
|
||||
+ "hv-vpindex": false,
|
||||
+ "xlevel2": 0,
|
||||
+ "clflushopt": true,
|
||||
+ "kvm-no-smi-migration": false,
|
||||
+ "monitor": false,
|
||||
+ "avx512er": false,
|
||||
+ "pmm-en": false,
|
||||
+ "pcid": true,
|
||||
+ "3dnow": false,
|
||||
+ "erms": true,
|
||||
+ "lahf-lm": true,
|
||||
+ "lahf_lm": true,
|
||||
+ "vpclmulqdq": false,
|
||||
+ "fxsr-opt": false,
|
||||
+ "hv-synic": false,
|
||||
+ "xstore": false,
|
||||
+ "fxsr_opt": false,
|
||||
+ "kvm-hint-dedicated": false,
|
||||
+ "rtm": true,
|
||||
+ "lmce": true,
|
||||
+ "hv-time": false,
|
||||
+ "perfctr-nb": false,
|
||||
+ "perfctr_nb": false,
|
||||
+ "ffxsr": false,
|
||||
+ "rdrand": true,
|
||||
+ "rdseed": true,
|
||||
+ "avx512-4vnniw": false,
|
||||
+ "vmx": false,
|
||||
+ "vme": true,
|
||||
+ "dtes64": false,
|
||||
+ "mtrr": true,
|
||||
+ "rdtscp": true,
|
||||
+ "pse36": true,
|
||||
+ "kvm-pv-tlb-flush": false,
|
||||
+ "tbm": false,
|
||||
+ "wdt": false,
|
||||
+ "pause_filter": false,
|
||||
+ "sha-ni": false,
|
||||
+ "model-id": "Intel(R) Xeon(R) CPU E3-1225 v5 @ 3.30GHz",
|
||||
+ "abm": true,
|
||||
+ "avx512pf": false,
|
||||
+ "xstore-en": false
|
||||
+ }
|
||||
+ }
|
||||
+ },
|
||||
+ "id": "model-expansion"
|
||||
+}
|
||||
+
|
||||
+{
|
||||
+ "return": [
|
||||
+ {
|
||||
+ "name": "max",
|
||||
+ "typename": "max-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": false
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "host",
|
||||
+ "typename": "host-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": false
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "base",
|
||||
+ "typename": "base-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": true,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "qemu64",
|
||||
+ "typename": "qemu64-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "qemu32",
|
||||
+ "typename": "qemu32-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "phenom",
|
||||
+ "typename": "phenom-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "mmxext",
|
||||
+ "fxsr-opt",
|
||||
+ "3dnowext",
|
||||
+ "3dnow",
|
||||
+ "sse4a",
|
||||
+ "npt"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "pentium3",
|
||||
+ "typename": "pentium3-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "pentium2",
|
||||
+ "typename": "pentium2-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "pentium",
|
||||
+ "typename": "pentium-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "n270",
|
||||
+ "typename": "n270-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "kvm64",
|
||||
+ "typename": "kvm64-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "kvm32",
|
||||
+ "typename": "kvm32-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "cpu64-rhel6",
|
||||
+ "typename": "cpu64-rhel6-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sse4a"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "coreduo",
|
||||
+ "typename": "coreduo-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "core2duo",
|
||||
+ "typename": "core2duo-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "athlon",
|
||||
+ "typename": "athlon-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "mmxext",
|
||||
+ "3dnowext",
|
||||
+ "3dnow"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Westmere",
|
||||
+ "typename": "Westmere-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Westmere-IBRS",
|
||||
+ "typename": "Westmere-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Skylake-Server",
|
||||
+ "typename": "Skylake-Server-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "avx512f",
|
||||
+ "avx512dq",
|
||||
+ "clwb",
|
||||
+ "avx512cd",
|
||||
+ "avx512bw",
|
||||
+ "avx512vl",
|
||||
+ "avx512f",
|
||||
+ "avx512f",
|
||||
+ "avx512f"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Skylake-Server-IBRS",
|
||||
+ "typename": "Skylake-Server-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "avx512f",
|
||||
+ "avx512dq",
|
||||
+ "clwb",
|
||||
+ "avx512cd",
|
||||
+ "avx512bw",
|
||||
+ "avx512vl",
|
||||
+ "avx512f",
|
||||
+ "avx512f",
|
||||
+ "avx512f"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Skylake-Client",
|
||||
+ "typename": "Skylake-Client-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Skylake-Client-IBRS",
|
||||
+ "typename": "Skylake-Client-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "SandyBridge",
|
||||
+ "typename": "SandyBridge-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "SandyBridge-IBRS",
|
||||
+ "typename": "SandyBridge-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Penryn",
|
||||
+ "typename": "Penryn-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Opteron_G5",
|
||||
+ "typename": "Opteron_G5-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sse4a",
|
||||
+ "misalignsse",
|
||||
+ "xop",
|
||||
+ "fma4",
|
||||
+ "tbm"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Opteron_G4",
|
||||
+ "typename": "Opteron_G4-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sse4a",
|
||||
+ "misalignsse",
|
||||
+ "xop",
|
||||
+ "fma4"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Opteron_G3",
|
||||
+ "typename": "Opteron_G3-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sse4a",
|
||||
+ "misalignsse"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Opteron_G2",
|
||||
+ "typename": "Opteron_G2-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Opteron_G1",
|
||||
+ "typename": "Opteron_G1-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Nehalem",
|
||||
+ "typename": "Nehalem-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Nehalem-IBRS",
|
||||
+ "typename": "Nehalem-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "IvyBridge",
|
||||
+ "typename": "IvyBridge-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "IvyBridge-IBRS",
|
||||
+ "typename": "IvyBridge-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Haswell",
|
||||
+ "typename": "Haswell-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Haswell-noTSX",
|
||||
+ "typename": "Haswell-noTSX-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Haswell-noTSX-IBRS",
|
||||
+ "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Haswell-IBRS",
|
||||
+ "typename": "Haswell-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "EPYC",
|
||||
+ "typename": "EPYC-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sha-ni",
|
||||
+ "mmxext",
|
||||
+ "fxsr-opt",
|
||||
+ "cr8legacy",
|
||||
+ "sse4a",
|
||||
+ "misalignsse",
|
||||
+ "osvw"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "EPYC-IBPB",
|
||||
+ "typename": "EPYC-IBPB-x86_64-cpu",
|
||||
+ "unavailable-features": [
|
||||
+ "sha-ni",
|
||||
+ "mmxext",
|
||||
+ "fxsr-opt",
|
||||
+ "cr8legacy",
|
||||
+ "sse4a",
|
||||
+ "misalignsse",
|
||||
+ "osvw",
|
||||
+ "ibpb"
|
||||
+ ],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Conroe",
|
||||
+ "typename": "Conroe-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Broadwell",
|
||||
+ "typename": "Broadwell-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Broadwell-noTSX",
|
||||
+ "typename": "Broadwell-noTSX-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Broadwell-noTSX-IBRS",
|
||||
+ "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "Broadwell-IBRS",
|
||||
+ "typename": "Broadwell-IBRS-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "486",
|
||||
+ "typename": "486-x86_64-cpu",
|
||||
+ "unavailable-features": [],
|
||||
+ "static": false,
|
||||
+ "migration-safe": true
|
||||
+ }
|
||||
+ ],
|
||||
+ "id": "definitions"
|
||||
+}
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.sig
|
||||
new file mode 100644
|
||||
index 0000000000..7e57c2ded6
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.sig
|
||||
@@ -0,0 +1,4 @@
|
||||
+0506e3
|
||||
+family: 6 (0x06)
|
||||
+model: 94 (0x5e)
|
||||
+stepping: 3 (0x03)
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.xml
|
||||
new file mode 100644
|
||||
index 0000000000..437429d61d
|
||||
--- /dev/null
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5.xml
|
||||
@@ -0,0 +1,47 @@
|
||||
+<!-- Intel(R) Xeon(R) CPU E3-1225 v5 @ 3.30GHz -->
|
||||
+<cpudata arch='x86'>
|
||||
+ <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
|
||||
+ <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000506e3' ebx='0x06100800' ecx='0x7ffafbff' edx='0xbfebfbff'/>
|
||||
+ <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b6ff' ecx='0x00000000' edx='0x00c30000'/>
|
||||
+ <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x1c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x1c004143' ebx='0x00c0003f' ecx='0x000003ff' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x1c03c163' ebx='0x03c0003f' ecx='0x00001fff' edx='0x00000006'/>
|
||||
+ <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00142120'/>
|
||||
+ <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x000027f7' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x029c6fbf' ecx='0x00000000' edx='0x9c002400'/>
|
||||
+ <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300804' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
|
||||
+ <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000001' ecx='0x00000100' edx='0x00000006'/>
|
||||
+ <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000004' ecx='0x00000201' edx='0x00000006'/>
|
||||
+ <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x0000001f' ebx='0x00000440' ecx='0x00000440' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x000003c0' ecx='0x00000100' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000001' ebx='0x0000000f' ecx='0x00000007' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000014' ecx_in='0x01' eax='0x02490002' ebx='0x003f3fff' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000015' ecx_in='0x00' eax='0x00000002' ebx='0x00000114' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x00000016' ecx_in='0x00' eax='0x00000ce4' ebx='0x00000e74' ecx='0x00000064' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
|
||||
+ <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/>
|
||||
+ <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x55504320' ebx='0x2d334520' ecx='0x35323231' edx='0x20357620'/>
|
||||
+ <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x2e332040' ebx='0x48473033' ecx='0x0000007a' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
|
||||
+ <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x00003027' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000ce4' ebx='0x00000e74' ecx='0x00000064' edx='0x00000000'/>
|
||||
+ <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000ce4' ebx='0x00000e74' ecx='0x00000064' edx='0x00000000'/>
|
||||
+</cpudata>
|
||||
@@ -0,0 +1,102 @@
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Tue, 9 Apr 2019 12:35:52 +0200
|
||||
Subject: [PATCH] cpu_map: Define md-clear CPUID bit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
|
||||
|
||||
The bit is set when microcode provides the mechanism to invoke a flush
|
||||
of various exploitable CPU buffers by invoking the VERW instruction.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 538d873571d7a682852dc1d70e5f4478f4d64e85)
|
||||
|
||||
Conflicts:
|
||||
src/cpu_map/x86_features.xml
|
||||
- missing pconfig feature
|
||||
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
|
||||
- test data missing downstream
|
||||
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
- intel-pt feature is missing
|
||||
- stibp feature is missing
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
---
|
||||
src/cpu_map/x86_features.xml | 3 +++
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml | 2 +-
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml | 1 +
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml | 1 +
|
||||
tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml | 1 +
|
||||
5 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cpu_map/x86_features.xml b/src/cpu_map/x86_features.xml
|
||||
index 109c653dbc..c8ae540ccc 100644
|
||||
--- a/src/cpu_map/x86_features.xml
|
||||
+++ b/src/cpu_map/x86_features.xml
|
||||
@@ -290,6 +290,9 @@
|
||||
<feature name='avx512-4fmaps'>
|
||||
<cpuid eax_in='0x07' ecx_in='0x00' edx='0x00000008'/>
|
||||
</feature>
|
||||
+ <feature name='md-clear'> <!-- md_clear -->
|
||||
+ <cpuid eax_in='0x07' ecx_in='0x00' edx='0x00000400'/>
|
||||
+ </feature>
|
||||
<feature name='spec-ctrl'>
|
||||
<cpuid eax_in='0x07' ecx_in='0x00' edx='0x04000000'/>
|
||||
</feature>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
index 0deca9fba6..74763a462b 100644
|
||||
--- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-enabled.xml
|
||||
@@ -2,7 +2,7 @@
|
||||
<cpudata arch='x86'>
|
||||
<cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
|
||||
<cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
- <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000000' edx='0x8c000000'/>
|
||||
+ <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000000' edx='0x8c000400'/>
|
||||
<cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000007' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
|
||||
<cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
|
||||
</cpudata>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
index 993db80cc9..29c1fdb80a 100644
|
||||
--- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-guest.xml
|
||||
@@ -19,6 +19,7 @@
|
||||
<feature policy='require' name='osxsave'/>
|
||||
<feature policy='require' name='tsc_adjust'/>
|
||||
<feature policy='require' name='clflushopt'/>
|
||||
+ <feature policy='require' name='md-clear'/>
|
||||
<feature policy='require' name='ssbd'/>
|
||||
<feature policy='require' name='xsaves'/>
|
||||
<feature policy='require' name='pdpe1gb'/>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
index 074a39ba1d..2003ca9ef6 100644
|
||||
--- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-host.xml
|
||||
@@ -20,6 +20,7 @@
|
||||
<feature name='osxsave'/>
|
||||
<feature name='tsc_adjust'/>
|
||||
<feature name='clflushopt'/>
|
||||
+ <feature name='md-clear'/>
|
||||
<feature name='ssbd'/>
|
||||
<feature name='xsaves'/>
|
||||
<feature name='pdpe1gb'/>
|
||||
diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
index 1984bd4cf2..d6529c59a3 100644
|
||||
--- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
+++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1225-v5-json.xml
|
||||
@@ -5,6 +5,7 @@
|
||||
<feature policy='require' name='hypervisor'/>
|
||||
<feature policy='require' name='tsc_adjust'/>
|
||||
<feature policy='require' name='clflushopt'/>
|
||||
+ <feature policy='require' name='md-clear'/>
|
||||
<feature policy='require' name='ssbd'/>
|
||||
<feature policy='require' name='pdpe1gb'/>
|
||||
</cpu>
|
||||
@@ -0,0 +1,54 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Tue, 30 Apr 2019 17:26:13 +0100
|
||||
Subject: [PATCH] admin: reject clients unless their UID matches the current
|
||||
UID
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The admin protocol RPC messages are only intended for use by the user
|
||||
running the daemon. As such they should not be allowed for any client
|
||||
UID that does not match the server UID.
|
||||
|
||||
Fixes CVE-2019-10132
|
||||
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 96f41cd765c9e525fe28ee5abbfbf4a79b3720c7)
|
||||
---
|
||||
src/admin/admin_server_dispatch.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/src/admin/admin_server_dispatch.c b/src/admin/admin_server_dispatch.c
|
||||
index b78ff902c0..9f25813ae3 100644
|
||||
--- a/src/admin/admin_server_dispatch.c
|
||||
+++ b/src/admin/admin_server_dispatch.c
|
||||
@@ -66,6 +66,28 @@ remoteAdmClientNew(virNetServerClientPtr client ATTRIBUTE_UNUSED,
|
||||
void *opaque)
|
||||
{
|
||||
struct daemonAdmClientPrivate *priv;
|
||||
+ uid_t clientuid;
|
||||
+ gid_t clientgid;
|
||||
+ pid_t clientpid;
|
||||
+ unsigned long long timestamp;
|
||||
+
|
||||
+ if (virNetServerClientGetUNIXIdentity(client,
|
||||
+ &clientuid,
|
||||
+ &clientgid,
|
||||
+ &clientpid,
|
||||
+ ×tamp) < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ VIR_DEBUG("New client pid %lld uid %lld",
|
||||
+ (long long)clientpid,
|
||||
+ (long long)clientuid);
|
||||
+
|
||||
+ if (geteuid() != clientuid) {
|
||||
+ virReportRestrictedError(_("Disallowing client %lld with uid %lld"),
|
||||
+ (long long)clientpid,
|
||||
+ (long long)clientuid);
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
if (VIR_ALLOC(priv) < 0)
|
||||
return NULL;
|
||||
@@ -0,0 +1,47 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Tue, 30 Apr 2019 16:51:37 +0100
|
||||
Subject: [PATCH] locking: restrict sockets to mode 0600
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The virtlockd daemon's only intended client is the libvirtd daemon. As
|
||||
such it should never allow clients from other user accounts to connect.
|
||||
The code already enforces this and drops clients from other UIDs, but
|
||||
we can get earlier (and thus stronger) protection against DoS by setting
|
||||
the socket permissions to 0600
|
||||
|
||||
Fixes CVE-2019-10132
|
||||
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit f111e09468693909b1f067aa575efdafd9a262a1)
|
||||
---
|
||||
src/locking/virtlockd-admin.socket.in | 1 +
|
||||
src/locking/virtlockd.socket.in | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/locking/virtlockd-admin.socket.in b/src/locking/virtlockd-admin.socket.in
|
||||
index 2a7500f3d0..f674c492f7 100644
|
||||
--- a/src/locking/virtlockd-admin.socket.in
|
||||
+++ b/src/locking/virtlockd-admin.socket.in
|
||||
@@ -5,6 +5,7 @@ Before=libvirtd.service
|
||||
[Socket]
|
||||
ListenStream=@localstatedir@/run/libvirt/virtlockd-admin-sock
|
||||
Service=virtlockd.service
|
||||
+SocketMode=0600
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
diff --git a/src/locking/virtlockd.socket.in b/src/locking/virtlockd.socket.in
|
||||
index 45e0f20235..d701b27516 100644
|
||||
--- a/src/locking/virtlockd.socket.in
|
||||
+++ b/src/locking/virtlockd.socket.in
|
||||
@@ -4,6 +4,7 @@ Before=libvirtd.service
|
||||
|
||||
[Socket]
|
||||
ListenStream=@localstatedir@/run/libvirt/virtlockd-sock
|
||||
+SocketMode=0600
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
@@ -0,0 +1,47 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Tue, 30 Apr 2019 17:27:41 +0100
|
||||
Subject: [PATCH] logging: restrict sockets to mode 0600
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The virtlogd daemon's only intended client is the libvirtd daemon. As
|
||||
such it should never allow clients from other user accounts to connect.
|
||||
The code already enforces this and drops clients from other UIDs, but
|
||||
we can get earlier (and thus stronger) protection against DoS by setting
|
||||
the socket permissions to 0600
|
||||
|
||||
Fixes CVE-2019-10132
|
||||
|
||||
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit e37bd65f9948c1185456b2cdaa3bd6e875af680f)
|
||||
---
|
||||
src/logging/virtlogd-admin.socket.in | 1 +
|
||||
src/logging/virtlogd.socket.in | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/logging/virtlogd-admin.socket.in b/src/logging/virtlogd-admin.socket.in
|
||||
index 595e6c4c4b..5c41dfeb7b 100644
|
||||
--- a/src/logging/virtlogd-admin.socket.in
|
||||
+++ b/src/logging/virtlogd-admin.socket.in
|
||||
@@ -5,6 +5,7 @@ Before=libvirtd.service
|
||||
[Socket]
|
||||
ListenStream=@localstatedir@/run/libvirt/virtlogd-admin-sock
|
||||
Service=virtlogd.service
|
||||
+SocketMode=0600
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
diff --git a/src/logging/virtlogd.socket.in b/src/logging/virtlogd.socket.in
|
||||
index 22b9360c8d..ae48cdab9a 100644
|
||||
--- a/src/logging/virtlogd.socket.in
|
||||
+++ b/src/logging/virtlogd.socket.in
|
||||
@@ -4,6 +4,7 @@ Before=libvirtd.service
|
||||
|
||||
[Socket]
|
||||
ListenStream=@localstatedir@/run/libvirt/virtlogd-sock
|
||||
+SocketMode=0600
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
@@ -0,0 +1,80 @@
|
||||
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
|
||||
Date: Fri, 14 Jun 2019 08:47:42 +0200
|
||||
Subject: [PATCH] api: disallow virDomainSaveImageGetXMLDesc on read-only
|
||||
connections
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The virDomainSaveImageGetXMLDesc API is taking a path parameter,
|
||||
which can point to any path on the system. This file will then be
|
||||
read and parsed by libvirtd running with root privileges.
|
||||
|
||||
Forbid it on read-only connections.
|
||||
|
||||
Fixes: CVE-2019-10161
|
||||
Reported-by: Matthias Gerstner <mgerstner@suse.de>
|
||||
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit aed6a032cead4386472afb24b16196579e239580)
|
||||
---
|
||||
src/libvirt-domain.c | 10 ++--------
|
||||
src/qemu/qemu_driver.c | 2 +-
|
||||
src/remote/remote_protocol.x | 3 +--
|
||||
3 files changed, 4 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
|
||||
index ef460277f7..cda579180b 100644
|
||||
--- a/src/libvirt-domain.c
|
||||
+++ b/src/libvirt-domain.c
|
||||
@@ -1073,8 +1073,7 @@ virDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml,
|
||||
* previously by virDomainSave() or virDomainSaveFlags().
|
||||
*
|
||||
* No security-sensitive data will be included unless @flags contains
|
||||
- * VIR_DOMAIN_XML_SECURE; this flag is rejected on read-only
|
||||
- * connections. For this API, @flags should not contain either
|
||||
+ * VIR_DOMAIN_XML_SECURE
|
||||
* VIR_DOMAIN_XML_INACTIVE or VIR_DOMAIN_XML_UPDATE_CPU.
|
||||
*
|
||||
* Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of
|
||||
@@ -1091,12 +1090,7 @@ virDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *file,
|
||||
|
||||
virCheckConnectReturn(conn, NULL);
|
||||
virCheckNonNullArgGoto(file, error);
|
||||
-
|
||||
- if ((conn->flags & VIR_CONNECT_RO) && (flags & VIR_DOMAIN_XML_SECURE)) {
|
||||
- virReportError(VIR_ERR_OPERATION_DENIED, "%s",
|
||||
- _("virDomainSaveImageGetXMLDesc with secure flag"));
|
||||
- goto error;
|
||||
- }
|
||||
+ virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (conn->driver->domainSaveImageGetXMLDesc) {
|
||||
char *ret;
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 75f8699e7d..933f71c7b8 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -6791,7 +6791,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path,
|
||||
if (fd < 0)
|
||||
goto cleanup;
|
||||
|
||||
- if (virDomainSaveImageGetXMLDescEnsureACL(conn, def, flags) < 0)
|
||||
+ if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = qemuDomainDefFormatXML(driver, def, flags);
|
||||
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
|
||||
index 28c8febabd..52b92334fa 100644
|
||||
--- a/src/remote/remote_protocol.x
|
||||
+++ b/src/remote/remote_protocol.x
|
||||
@@ -5226,8 +5226,7 @@ enum remote_procedure {
|
||||
/**
|
||||
* @generate: both
|
||||
* @priority: high
|
||||
- * @acl: domain:read
|
||||
- * @acl: domain:read_secure:VIR_DOMAIN_XML_SECURE
|
||||
+ * @acl: domain:write
|
||||
*/
|
||||
REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
|
||||
Date: Fri, 14 Jun 2019 09:14:53 +0200
|
||||
Subject: [PATCH] api: disallow virDomainManagedSaveDefineXML on read-only
|
||||
connections
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The virDomainManagedSaveDefineXML can be used to alter the domain's
|
||||
config used for managedsave or even execute arbitrary emulator binaries.
|
||||
Forbid it on read-only connections.
|
||||
|
||||
Fixes: CVE-2019-10166
|
||||
Reported-by: Matthias Gerstner <mgerstner@suse.de>
|
||||
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit db0b78457f183e4c7ac45bc94de86044a1e2056a)
|
||||
---
|
||||
src/libvirt-domain.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
|
||||
index cda579180b..4c0355180e 100644
|
||||
--- a/src/libvirt-domain.c
|
||||
+++ b/src/libvirt-domain.c
|
||||
@@ -9483,6 +9483,7 @@ virDomainManagedSaveDefineXML(virDomainPtr domain, const char *dxml,
|
||||
|
||||
virCheckDomainReturn(domain, -1);
|
||||
conn = domain->conn;
|
||||
+ virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (conn->driver->domainManagedSaveDefineXML) {
|
||||
int ret;
|
||||
@@ -0,0 +1,31 @@
|
||||
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
|
||||
Date: Fri, 14 Jun 2019 09:16:14 +0200
|
||||
Subject: [PATCH] api: disallow virConnectGetDomainCapabilities on read-only
|
||||
connections
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This API can be used to execute arbitrary emulators.
|
||||
Forbid it on read-only connections.
|
||||
|
||||
Fixes: CVE-2019-10167
|
||||
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 8afa68bac0cf99d1f8aaa6566685c43c22622f26)
|
||||
---
|
||||
src/libvirt-domain.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
|
||||
index 4c0355180e..8ecb964381 100644
|
||||
--- a/src/libvirt-domain.c
|
||||
+++ b/src/libvirt-domain.c
|
||||
@@ -11275,6 +11275,7 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
|
||||
virResetLastError();
|
||||
|
||||
virCheckConnectReturn(conn, NULL);
|
||||
+ virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (conn->driver->connectGetDomainCapabilities) {
|
||||
char *ret;
|
||||
@@ -0,0 +1,39 @@
|
||||
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
|
||||
Date: Fri, 14 Jun 2019 09:17:39 +0200
|
||||
Subject: [PATCH] api: disallow virConnect*HypervisorCPU on read-only
|
||||
connections
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
These APIs can be used to execute arbitrary emulators.
|
||||
Forbid them on read-only connections.
|
||||
|
||||
Fixes: CVE-2019-10168
|
||||
Signed-off-by: Ján Tomko <jtomko@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit bf6c2830b6c338b1f5699b095df36f374777b291)
|
||||
---
|
||||
src/libvirt-host.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
|
||||
index e20d6ee250..2978825d22 100644
|
||||
--- a/src/libvirt-host.c
|
||||
+++ b/src/libvirt-host.c
|
||||
@@ -1041,6 +1041,7 @@ virConnectCompareHypervisorCPU(virConnectPtr conn,
|
||||
|
||||
virCheckConnectReturn(conn, VIR_CPU_COMPARE_ERROR);
|
||||
virCheckNonNullArgGoto(xmlCPU, error);
|
||||
+ virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (conn->driver->connectCompareHypervisorCPU) {
|
||||
int ret;
|
||||
@@ -1234,6 +1235,7 @@ virConnectBaselineHypervisorCPU(virConnectPtr conn,
|
||||
|
||||
virCheckConnectReturn(conn, NULL);
|
||||
virCheckNonNullArgGoto(xmlCPUs, error);
|
||||
+ virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (conn->driver->connectBaselineHypervisorCPU) {
|
||||
char *cpu;
|
||||
@@ -0,0 +1,32 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 27 Mar 2019 10:59:58 +0000
|
||||
Subject: [PATCH] api: disallow virDomainGetHostname for read-only connections
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The virDomainGetHostname API is fetching guest information and this may
|
||||
involve use of an untrusted guest agent. As such its use must be
|
||||
forbidden on a read-only connection to libvirt.
|
||||
|
||||
Fixes CVE-2019-3886
|
||||
Reviewed-by: Jim Fehlig <jfehlig@suse.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 2a07c990bd9143d7a0fe8d1b6b7c763c52185240)
|
||||
---
|
||||
src/libvirt-domain.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
|
||||
index 8ecb964381..cc2f61275d 100644
|
||||
--- a/src/libvirt-domain.c
|
||||
+++ b/src/libvirt-domain.c
|
||||
@@ -10940,6 +10940,8 @@ virDomainGetHostname(virDomainPtr domain, unsigned int flags)
|
||||
virCheckDomainReturn(domain, NULL);
|
||||
conn = domain->conn;
|
||||
|
||||
+ virCheckReadOnlyGoto(domain->conn->flags, error);
|
||||
+
|
||||
if (conn->driver->domainGetHostname) {
|
||||
char *ret;
|
||||
ret = conn->driver->domainGetHostname(domain, flags);
|
||||
@@ -0,0 +1,42 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 27 Mar 2019 11:22:49 +0000
|
||||
Subject: [PATCH] remote: enforce ACL write permission for getting guest time &
|
||||
hostname
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Getting the guest time and hostname both require use of guest agent
|
||||
commands. These must not be allowed for read-only users, so the
|
||||
permissions check must validate "write" permission not "read".
|
||||
|
||||
Fixes CVE-2019-3886
|
||||
Reviewed-by: Jim Fehlig <jfehlig@suse.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit ae076bb40e0e150aef41361b64001138d04d6c60)
|
||||
---
|
||||
src/remote/remote_protocol.x | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
|
||||
index 52b92334fa..58ab4ab039 100644
|
||||
--- a/src/remote/remote_protocol.x
|
||||
+++ b/src/remote/remote_protocol.x
|
||||
@@ -5496,7 +5496,7 @@ enum remote_procedure {
|
||||
|
||||
/**
|
||||
* @generate: both
|
||||
- * @acl: domain:read
|
||||
+ * @acl: domain:write
|
||||
*/
|
||||
REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277,
|
||||
|
||||
@@ -5891,7 +5891,7 @@ enum remote_procedure {
|
||||
|
||||
/**
|
||||
* @generate: none
|
||||
- * @acl: domain:read
|
||||
+ * @acl: domain:write
|
||||
*/
|
||||
REMOTE_PROC_DOMAIN_GET_TIME = 337,
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Mon, 24 Sep 2018 16:49:01 +0200
|
||||
Subject: [PATCH] Revert "qemu: hotplug: Prepare disk source in
|
||||
qemuDomainAttachDeviceDiskLive"
|
||||
|
||||
Preparing the storage source prior to assigning the alias will not work
|
||||
as the names of the certain objects depend on the alias for the legacy
|
||||
hotplug case as we generate the object names for the secrets based on
|
||||
the alias.
|
||||
|
||||
This reverts commit 192fdaa614e3800255048a8a70c1292ccf18397a.
|
||||
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
(cherry picked from commit 9ac196997839a29486029a02d8f519df54ae0186)
|
||||
---
|
||||
src/qemu/qemu_hotplug.c | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
||||
index 4f290b5648..421cc2c174 100644
|
||||
--- a/src/qemu/qemu_hotplug.c
|
||||
+++ b/src/qemu/qemu_hotplug.c
|
||||
@@ -781,6 +781,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
qemuHotplugDiskSourceDataPtr diskdata = NULL;
|
||||
char *devstr = NULL;
|
||||
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
|
||||
if (qemuHotplugPrepareDiskAccess(driver, vm, disk, NULL, false) < 0)
|
||||
goto cleanup;
|
||||
@@ -788,6 +789,9 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
|
||||
if (qemuAssignDeviceDiskAlias(vm->def, disk, priv->qemuCaps) < 0)
|
||||
goto error;
|
||||
|
||||
+ if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
||||
+ goto error;
|
||||
+
|
||||
if (!(diskdata = qemuHotplugDiskSourceAttachPrepare(disk, priv->qemuCaps)))
|
||||
goto error;
|
||||
|
||||
@@ -822,6 +826,7 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
|
||||
qemuHotplugDiskSourceDataFree(diskdata);
|
||||
qemuDomainSecretDiskDestroy(disk);
|
||||
VIR_FREE(devstr);
|
||||
+ virObjectUnref(cfg);
|
||||
return ret;
|
||||
|
||||
exit_monitor:
|
||||
@@ -1062,8 +1067,6 @@ qemuDomainAttachDeviceDiskLive(virQEMUDriverPtr driver,
|
||||
bool forceMediaChange)
|
||||
{
|
||||
size_t i;
|
||||
- virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||
- qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
virDomainDiskDefPtr disk = dev->data.disk;
|
||||
virDomainDiskDefPtr orig_disk = NULL;
|
||||
int ret = -1;
|
||||
@@ -1080,9 +1083,6 @@ qemuDomainAttachDeviceDiskLive(virQEMUDriverPtr driver,
|
||||
if (qemuDomainDetermineDiskChain(driver, vm, disk, true) < 0)
|
||||
goto cleanup;
|
||||
|
||||
- if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
switch ((virDomainDiskDevice) disk->device) {
|
||||
case VIR_DOMAIN_DISK_DEVICE_CDROM:
|
||||
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
|
||||
@@ -1153,7 +1153,6 @@ qemuDomainAttachDeviceDiskLive(virQEMUDriverPtr driver,
|
||||
cleanup:
|
||||
if (ret != 0)
|
||||
ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name));
|
||||
- virObjectUnref(cfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From: Radoslaw Biernacki <radoslaw.biernacki@linaro.org>
|
||||
Date: Tue, 22 Jan 2019 12:26:15 -0700
|
||||
Subject: [PATCH] util: Fixing invalid error checking from virPCIGetNetname()
|
||||
|
||||
The @linkdev is In/Out function parameter as second order
|
||||
reference pointer so requires first order dereference for
|
||||
checking NULL which can be the result of virPCIGetNetName().
|
||||
|
||||
Fixes: d6ee56d7237 (util: change virPCIGetNetName() to not return error if device has no net name)
|
||||
Signed-off-by: Radoslaw Biernacki <radoslaw.biernacki@linaro.org>
|
||||
Signed-off-by: dann frazier <dann.frazier@canonical.com>
|
||||
(cherry picked from commit 04983c3c6a821f67994b1c65d4d6175f3ac49d69)
|
||||
---
|
||||
src/util/virhostdev.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
|
||||
index ca79c37787..d9a3711386 100644
|
||||
--- a/src/util/virhostdev.c
|
||||
+++ b/src/util/virhostdev.c
|
||||
@@ -319,7 +319,7 @@ virHostdevNetDevice(virDomainHostdevDefPtr hostdev,
|
||||
if (virPCIGetNetName(sysfs_path, 0, NULL, linkdev) < 0)
|
||||
return -1;
|
||||
|
||||
- if (!linkdev) {
|
||||
+ if (!(*linkdev)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("The device at %s has no network device name"),
|
||||
sysfs_path);
|
||||
@@ -0,0 +1,203 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Tue, 1 May 2018 11:34:51 +0100
|
||||
Subject: [PATCH] tests: merge code for UNIX and TCP socket testing
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The test code for UNIX and TCP sockets will need to be rewritten and
|
||||
extended later, and will benefit from code sharing.
|
||||
|
||||
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 9e2fad87b429060842a536de26d6af61ea3d96ea)
|
||||
---
|
||||
tests/virnetsockettest.c | 120 +++++++++++++++++----------------------
|
||||
1 file changed, 51 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c
|
||||
index 9f9a243484..e463d432ff 100644
|
||||
--- a/tests/virnetsockettest.c
|
||||
+++ b/tests/virnetsockettest.c
|
||||
@@ -116,38 +116,67 @@ checkProtocols(bool *hasIPv4, bool *hasIPv6,
|
||||
}
|
||||
|
||||
|
||||
-struct testTCPData {
|
||||
+struct testSocketData {
|
||||
const char *lnode;
|
||||
int port;
|
||||
const char *cnode;
|
||||
};
|
||||
|
||||
-static int testSocketTCPAccept(const void *opaque)
|
||||
+static int testSocketAccept(const void *opaque)
|
||||
{
|
||||
virNetSocketPtr *lsock = NULL; /* Listen socket */
|
||||
size_t nlsock = 0, i;
|
||||
virNetSocketPtr ssock = NULL; /* Server socket */
|
||||
virNetSocketPtr csock = NULL; /* Client socket */
|
||||
- const struct testTCPData *data = opaque;
|
||||
+ const struct testSocketData *data = opaque;
|
||||
int ret = -1;
|
||||
char portstr[100];
|
||||
+ char *tmpdir = NULL;
|
||||
+ char *path = NULL;
|
||||
+ char template[] = "/tmp/libvirt_XXXXXX";
|
||||
|
||||
- snprintf(portstr, sizeof(portstr), "%d", data->port);
|
||||
+ if (!data) {
|
||||
+ virNetSocketPtr usock;
|
||||
+ tmpdir = mkdtemp(template);
|
||||
+ if (tmpdir == NULL) {
|
||||
+ VIR_WARN("Failed to create temporary directory");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (virAsprintf(&path, "%s/test.sock", tmpdir) < 0)
|
||||
+ goto cleanup;
|
||||
|
||||
- if (virNetSocketNewListenTCP(data->lnode, portstr,
|
||||
- AF_UNSPEC,
|
||||
- &lsock, &nlsock) < 0)
|
||||
- goto cleanup;
|
||||
+ if (virNetSocketNewListenUNIX(path, 0700, -1, getegid(), &usock) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (VIR_ALLOC_N(lsock, 1) < 0) {
|
||||
+ virObjectUnref(usock);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ lsock[0] = usock;
|
||||
+ nlsock = 1;
|
||||
+ } else {
|
||||
+ snprintf(portstr, sizeof(portstr), "%d", data->port);
|
||||
+ if (virNetSocketNewListenTCP(data->lnode, portstr,
|
||||
+ AF_UNSPEC,
|
||||
+ &lsock, &nlsock) < 0)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < nlsock; i++) {
|
||||
if (virNetSocketListen(lsock[i], 0) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- if (virNetSocketNewConnectTCP(data->cnode, portstr,
|
||||
- AF_UNSPEC,
|
||||
- &csock) < 0)
|
||||
- goto cleanup;
|
||||
+ if (!data) {
|
||||
+ if (virNetSocketNewConnectUNIX(path, false, NULL, &csock) < 0)
|
||||
+ goto cleanup;
|
||||
+ } else {
|
||||
+ if (virNetSocketNewConnectTCP(data->cnode, portstr,
|
||||
+ AF_UNSPEC,
|
||||
+ &csock) < 0)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
virObjectUnref(csock);
|
||||
|
||||
@@ -171,62 +200,15 @@ static int testSocketTCPAccept(const void *opaque)
|
||||
for (i = 0; i < nlsock; i++)
|
||||
virObjectUnref(lsock[i]);
|
||||
VIR_FREE(lsock);
|
||||
- return ret;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
-#ifndef WIN32
|
||||
-static int testSocketUNIXAccept(const void *data ATTRIBUTE_UNUSED)
|
||||
-{
|
||||
- virNetSocketPtr lsock = NULL; /* Listen socket */
|
||||
- virNetSocketPtr ssock = NULL; /* Server socket */
|
||||
- virNetSocketPtr csock = NULL; /* Client socket */
|
||||
- int ret = -1;
|
||||
-
|
||||
- char *path = NULL;
|
||||
- char *tmpdir;
|
||||
- char template[] = "/tmp/libvirt_XXXXXX";
|
||||
-
|
||||
- tmpdir = mkdtemp(template);
|
||||
- if (tmpdir == NULL) {
|
||||
- VIR_WARN("Failed to create temporary directory");
|
||||
- goto cleanup;
|
||||
- }
|
||||
- if (virAsprintf(&path, "%s/test.sock", tmpdir) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- if (virNetSocketNewListenUNIX(path, 0700, -1, getegid(), &lsock) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- if (virNetSocketListen(lsock, 0) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- if (virNetSocketNewConnectUNIX(path, false, NULL, &csock) < 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- virObjectUnref(csock);
|
||||
-
|
||||
- if (virNetSocketAccept(lsock, &ssock) != -1) {
|
||||
- char c = 'a';
|
||||
- if (virNetSocketWrite(ssock, &c, 1) != -1) {
|
||||
- VIR_DEBUG("Unexpected client socket present");
|
||||
- goto cleanup;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ret = 0;
|
||||
-
|
||||
- cleanup:
|
||||
VIR_FREE(path);
|
||||
- virObjectUnref(lsock);
|
||||
- virObjectUnref(ssock);
|
||||
if (tmpdir)
|
||||
rmdir(tmpdir);
|
||||
return ret;
|
||||
}
|
||||
+#endif
|
||||
|
||||
|
||||
+#ifndef WIN32
|
||||
static int testSocketUNIXAddrs(const void *data ATTRIBUTE_UNUSED)
|
||||
{
|
||||
virNetSocketPtr lsock = NULL; /* Listen socket */
|
||||
@@ -456,28 +438,28 @@ mymain(void)
|
||||
}
|
||||
|
||||
if (hasIPv4) {
|
||||
- struct testTCPData tcpData = { "127.0.0.1", freePort, "127.0.0.1" };
|
||||
- if (virTestRun("Socket TCP/IPv4 Accept", testSocketTCPAccept, &tcpData) < 0)
|
||||
+ struct testSocketData tcpData = { "127.0.0.1", freePort, "127.0.0.1" };
|
||||
+ if (virTestRun("Socket TCP/IPv4 Accept", testSocketAccept, &tcpData) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
if (hasIPv6) {
|
||||
- struct testTCPData tcpData = { "::1", freePort, "::1" };
|
||||
- if (virTestRun("Socket TCP/IPv6 Accept", testSocketTCPAccept, &tcpData) < 0)
|
||||
+ struct testSocketData tcpData = { "::1", freePort, "::1" };
|
||||
+ if (virTestRun("Socket TCP/IPv6 Accept", testSocketAccept, &tcpData) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
if (hasIPv6 && hasIPv4) {
|
||||
- struct testTCPData tcpData = { NULL, freePort, "127.0.0.1" };
|
||||
- if (virTestRun("Socket TCP/IPv4+IPv6 Accept", testSocketTCPAccept, &tcpData) < 0)
|
||||
+ struct testSocketData tcpData = { NULL, freePort, "127.0.0.1" };
|
||||
+ if (virTestRun("Socket TCP/IPv4+IPv6 Accept", testSocketAccept, &tcpData) < 0)
|
||||
ret = -1;
|
||||
|
||||
tcpData.cnode = "::1";
|
||||
- if (virTestRun("Socket TCP/IPv4+IPv6 Accept", testSocketTCPAccept, &tcpData) < 0)
|
||||
+ if (virTestRun("Socket TCP/IPv4+IPv6 Accept", testSocketAccept, &tcpData) < 0)
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
- if (virTestRun("Socket UNIX Accept", testSocketUNIXAccept, NULL) < 0)
|
||||
+ if (virTestRun("Socket UNIX Accept", testSocketAccept, NULL) < 0)
|
||||
ret = -1;
|
||||
|
||||
if (virTestRun("Socket UNIX Addrs", testSocketUNIXAddrs, NULL) < 0)
|
||||
@@ -0,0 +1,241 @@
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Tue, 1 May 2018 11:55:02 +0100
|
||||
Subject: [PATCH] tests: rewrite socket to do something sensible and reliable
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The current socket test is rather crazy in that it sets up a server
|
||||
listening for sockets and then runs a client connect call, relying on
|
||||
the fact that the kernel will accept this despite the application
|
||||
not having called accept() yet. It then closes the client socket and
|
||||
calls accept() on the server. On Linux accept() will always see that
|
||||
the client has gone and so skip the rest of the code. On FreeBSD,
|
||||
however, the accept sometimes succeeds, causing us to then go into
|
||||
code that attempts to read and write to the client which will fail
|
||||
aborting the test. The accept() never succeeds on FreeBSD guests
|
||||
with a single CPU, but as you add more CPUs, accept() becomes more and
|
||||
more likely to succeed, giving a 100% failure rate for the test when
|
||||
using 8 CPUs.
|
||||
|
||||
This completely rewrites the test so that it is avoids this designed in
|
||||
race condition. We simply spawn a background thread to act as the
|
||||
client, which will read a byte from the server and write it back again.
|
||||
The main thread can now properly listen and accept the client in a
|
||||
synchronous manner avoiding any races.
|
||||
|
||||
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
(cherry picked from commit 39015a6f3a0d4f9ca2041b9227094f0bcc2217e9)
|
||||
---
|
||||
tests/virnetsockettest.c | 141 +++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 120 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c
|
||||
index e463d432ff..cccb90d0be 100644
|
||||
--- a/tests/virnetsockettest.c
|
||||
+++ b/tests/virnetsockettest.c
|
||||
@@ -115,6 +115,56 @@ checkProtocols(bool *hasIPv4, bool *hasIPv6,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+struct testClientData {
|
||||
+ const char *path;
|
||||
+ const char *cnode;
|
||||
+ const char *portstr;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+testSocketClient(void *opaque)
|
||||
+{
|
||||
+ struct testClientData *data = opaque;
|
||||
+ char c;
|
||||
+ virNetSocketPtr csock = NULL;
|
||||
+
|
||||
+ if (data->path) {
|
||||
+ if (virNetSocketNewConnectUNIX(data->path, false,
|
||||
+ NULL, &csock) < 0)
|
||||
+ return;
|
||||
+ } else {
|
||||
+ if (virNetSocketNewConnectTCP(data->cnode, data->portstr,
|
||||
+ AF_UNSPEC,
|
||||
+ &csock) < 0)
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ virNetSocketSetBlocking(csock, true);
|
||||
+
|
||||
+ if (virNetSocketRead(csock, &c, 1) != 1) {
|
||||
+ VIR_DEBUG("Cannot read from server");
|
||||
+ goto done;
|
||||
+ }
|
||||
+ if (virNetSocketWrite(csock, &c, 1) != 1) {
|
||||
+ VIR_DEBUG("Cannot write to server");
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ virObjectUnref(csock);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
+testSocketIncoming(virNetSocketPtr sock,
|
||||
+ int events ATTRIBUTE_UNUSED,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ virNetSocketPtr *retsock = opaque;
|
||||
+ VIR_DEBUG("Incoming sock=%p events=%d\n", sock, events);
|
||||
+ *retsock = sock;
|
||||
+}
|
||||
+
|
||||
|
||||
struct testSocketData {
|
||||
const char *lnode;
|
||||
@@ -122,18 +172,25 @@ struct testSocketData {
|
||||
const char *cnode;
|
||||
};
|
||||
|
||||
-static int testSocketAccept(const void *opaque)
|
||||
+
|
||||
+static int
|
||||
+testSocketAccept(const void *opaque)
|
||||
{
|
||||
virNetSocketPtr *lsock = NULL; /* Listen socket */
|
||||
size_t nlsock = 0, i;
|
||||
virNetSocketPtr ssock = NULL; /* Server socket */
|
||||
- virNetSocketPtr csock = NULL; /* Client socket */
|
||||
+ virNetSocketPtr rsock = NULL; /* Incoming client socket */
|
||||
const struct testSocketData *data = opaque;
|
||||
int ret = -1;
|
||||
char portstr[100];
|
||||
char *tmpdir = NULL;
|
||||
char *path = NULL;
|
||||
char template[] = "/tmp/libvirt_XXXXXX";
|
||||
+ virThread th;
|
||||
+ struct testClientData cdata = { 0 };
|
||||
+ bool goodsock = false;
|
||||
+ char a = 'a';
|
||||
+ char b = '\0';
|
||||
|
||||
if (!data) {
|
||||
virNetSocketPtr usock;
|
||||
@@ -155,50 +212,90 @@ static int testSocketAccept(const void *opaque)
|
||||
|
||||
lsock[0] = usock;
|
||||
nlsock = 1;
|
||||
+
|
||||
+ cdata.path = path;
|
||||
} else {
|
||||
snprintf(portstr, sizeof(portstr), "%d", data->port);
|
||||
if (virNetSocketNewListenTCP(data->lnode, portstr,
|
||||
AF_UNSPEC,
|
||||
&lsock, &nlsock) < 0)
|
||||
goto cleanup;
|
||||
+
|
||||
+ cdata.cnode = data->cnode;
|
||||
+ cdata.portstr = portstr;
|
||||
}
|
||||
|
||||
for (i = 0; i < nlsock; i++) {
|
||||
if (virNetSocketListen(lsock[i], 0) < 0)
|
||||
goto cleanup;
|
||||
- }
|
||||
|
||||
- if (!data) {
|
||||
- if (virNetSocketNewConnectUNIX(path, false, NULL, &csock) < 0)
|
||||
- goto cleanup;
|
||||
- } else {
|
||||
- if (virNetSocketNewConnectTCP(data->cnode, portstr,
|
||||
- AF_UNSPEC,
|
||||
- &csock) < 0)
|
||||
+ if (virNetSocketAddIOCallback(lsock[i],
|
||||
+ VIR_EVENT_HANDLE_READABLE,
|
||||
+ testSocketIncoming,
|
||||
+ &rsock,
|
||||
+ NULL) < 0) {
|
||||
goto cleanup;
|
||||
+ }
|
||||
}
|
||||
|
||||
- virObjectUnref(csock);
|
||||
+ if (virThreadCreate(&th, true,
|
||||
+ testSocketClient,
|
||||
+ &cdata) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ while (rsock == NULL)
|
||||
+ virEventRunDefaultImpl();
|
||||
|
||||
for (i = 0; i < nlsock; i++) {
|
||||
- if (virNetSocketAccept(lsock[i], &ssock) != -1 && ssock) {
|
||||
- char c = 'a';
|
||||
- if (virNetSocketWrite(ssock, &c, 1) != -1 &&
|
||||
- virNetSocketRead(ssock, &c, 1) != -1) {
|
||||
- VIR_DEBUG("Unexpected client socket present");
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ if (lsock[i] == rsock) {
|
||||
+ goodsock = true;
|
||||
+ break;
|
||||
}
|
||||
- virObjectUnref(ssock);
|
||||
- ssock = NULL;
|
||||
}
|
||||
|
||||
+ if (!goodsock) {
|
||||
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
+ "Unexpected server socket seen");
|
||||
+ goto join;
|
||||
+ }
|
||||
+
|
||||
+ if (virNetSocketAccept(rsock, &ssock) < 0)
|
||||
+ goto join;
|
||||
+
|
||||
+ if (!ssock) {
|
||||
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
+ "Client went away unexpectedly");
|
||||
+ goto join;
|
||||
+ }
|
||||
+
|
||||
+ virNetSocketSetBlocking(ssock, true);
|
||||
+
|
||||
+ if (virNetSocketWrite(ssock, &a, 1) < 0 ||
|
||||
+ virNetSocketRead(ssock, &b, 1) < 0) {
|
||||
+ goto join;
|
||||
+ }
|
||||
+
|
||||
+ if (a != b) {
|
||||
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ "Bad data received '%x' != '%x'", a, b);
|
||||
+ goto join;
|
||||
+ }
|
||||
+
|
||||
+ virObjectUnref(ssock);
|
||||
+ ssock = NULL;
|
||||
+
|
||||
ret = 0;
|
||||
|
||||
+ join:
|
||||
+ virThreadJoin(&th);
|
||||
+
|
||||
cleanup:
|
||||
virObjectUnref(ssock);
|
||||
- for (i = 0; i < nlsock; i++)
|
||||
+ for (i = 0; i < nlsock; i++) {
|
||||
+ virNetSocketRemoveIOCallback(lsock[i]);
|
||||
+ virNetSocketClose(lsock[i]);
|
||||
virObjectUnref(lsock[i]);
|
||||
+ }
|
||||
VIR_FREE(lsock);
|
||||
VIR_FREE(path);
|
||||
if (tmpdir)
|
||||
@@ -431,6 +528,8 @@ mymain(void)
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
+ virEventRegisterDefaultImpl();
|
||||
+
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
if (checkProtocols(&hasIPv4, &hasIPv6, &freePort) < 0) {
|
||||
fprintf(stderr, "Cannot identify IPv4/6 availability\n");
|
||||
@@ -0,0 +1,34 @@
|
||||
From: John Ferlan <jferlan@redhat.com>
|
||||
Date: Fri, 7 Sep 2018 08:20:15 -0400
|
||||
Subject: [PATCH] test: Remove possible infinite loop in virnetsockettest
|
||||
|
||||
Commit 39015a6f3 modified the test to be more reliable/realistic,
|
||||
but without checking the return status of virEventRunDefaultImpl
|
||||
it's possible that the test could run infinitely.
|
||||
|
||||
Found by Coverity
|
||||
|
||||
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
||||
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
(cherry picked from commit a0ba31c0069e89f178f064e724ddbc8540b64d32)
|
||||
---
|
||||
tests/virnetsockettest.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/virnetsockettest.c b/tests/virnetsockettest.c
|
||||
index cccb90d0be..5927be1f80 100644
|
||||
--- a/tests/virnetsockettest.c
|
||||
+++ b/tests/virnetsockettest.c
|
||||
@@ -243,8 +243,10 @@ testSocketAccept(const void *opaque)
|
||||
&cdata) < 0)
|
||||
goto cleanup;
|
||||
|
||||
- while (rsock == NULL)
|
||||
- virEventRunDefaultImpl();
|
||||
+ while (rsock == NULL) {
|
||||
+ if (virEventRunDefaultImpl() < 0)
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < nlsock; i++) {
|
||||
if (lsock[i] == rsock) {
|
||||
@@ -1,356 +0,0 @@
|
||||
From 953440bd12608a20007ee5da5ab69fbbe910bd28 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 15:53:59 +0100
|
||||
Subject: [PATCH 01/11] Extract the backing store format as well as name, if available
|
||||
|
||||
When QEMU opens a backing store for a QCow2 file, it will
|
||||
normally auto-probe for the format of the backing store,
|
||||
rather than assuming it has the same format as the referencing
|
||||
file. There is a QCow2 extension that allows an explicit format
|
||||
for the backing store to be embedded in the referencing file.
|
||||
This closes the auto-probing security hole in QEMU.
|
||||
|
||||
This backing store format can be useful for libvirt users
|
||||
of virStorageFileGetMetadata, so extract this data and report
|
||||
it.
|
||||
|
||||
QEMU does not require disk image backing store files to be in
|
||||
the same format the file linkee. It will auto-probe the disk
|
||||
format for the backing store when opening it. If the backing
|
||||
store was intended to be a raw file this could be a security
|
||||
hole, because a guest may have written data into its disk that
|
||||
then makes the backing store look like a qcow2 file. If it can
|
||||
trick QEMU into thinking the raw file is a qcow2 file, it can
|
||||
access arbitrary files on the host by adding further backing
|
||||
store links.
|
||||
|
||||
To address this, callers of virStorageFileGetMeta need to be
|
||||
told of the backing store format. If no format is declared,
|
||||
they can make a decision whether to allow format probing or
|
||||
not.
|
||||
---
|
||||
src/util/storage_file.c | 206 +++++++++++++++++++++++++++++++++++++++++------
|
||||
src/util/storage_file.h | 2 +
|
||||
2 files changed, 183 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
|
||||
index 0adea40..80f743e 100644
|
||||
--- a/src/util/storage_file.c
|
||||
+++ b/src/util/storage_file.c
|
||||
@@ -78,12 +78,33 @@ struct FileTypeInfo {
|
||||
int qcowCryptOffset; /* Byte offset from start of file
|
||||
* where to find encryption mode,
|
||||
* -1 if encryption is not used */
|
||||
- int (*getBackingStore)(char **res, const unsigned char *buf, size_t buf_size);
|
||||
+ int (*getBackingStore)(char **res, int *format,
|
||||
+ const unsigned char *buf, size_t buf_size);
|
||||
};
|
||||
|
||||
-static int cowGetBackingStore(char **, const unsigned char *, size_t);
|
||||
-static int qcowXGetBackingStore(char **, const unsigned char *, size_t);
|
||||
-static int vmdk4GetBackingStore(char **, const unsigned char *, size_t);
|
||||
+static int cowGetBackingStore(char **, int *,
|
||||
+ const unsigned char *, size_t);
|
||||
+static int qcow1GetBackingStore(char **, int *,
|
||||
+ const unsigned char *, size_t);
|
||||
+static int qcow2GetBackingStore(char **, int *,
|
||||
+ const unsigned char *, size_t);
|
||||
+static int vmdk4GetBackingStore(char **, int *,
|
||||
+ const unsigned char *, size_t);
|
||||
+
|
||||
+#define QCOWX_HDR_VERSION (4)
|
||||
+#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4)
|
||||
+#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8)
|
||||
+#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4)
|
||||
+
|
||||
+#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1)
|
||||
+#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8)
|
||||
+
|
||||
+#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8)
|
||||
+#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8)
|
||||
+
|
||||
+#define QCOW2_HDR_EXTENSION_END 0
|
||||
+#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
|
||||
+
|
||||
|
||||
|
||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
||||
@@ -119,11 +140,11 @@ static struct FileTypeInfo const fileTypeInfo[] = {
|
||||
/* QCow */
|
||||
{ VIR_STORAGE_FILE_QCOW, "QFI", NULL,
|
||||
LV_BIG_ENDIAN, 4, 1,
|
||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8+1+1+2, qcowXGetBackingStore },
|
||||
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore },
|
||||
/* QCow 2 */
|
||||
{ VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
|
||||
LV_BIG_ENDIAN, 4, 2,
|
||||
- 4+4+8+4+4, 8, 1, 4+4+8+4+4+8, qcowXGetBackingStore },
|
||||
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore },
|
||||
/* VMDK 3 */
|
||||
/* XXX Untested
|
||||
{ VIR_STORAGE_FILE_VMDK, "COWD", NULL,
|
||||
@@ -142,11 +163,14 @@ static struct FileTypeInfo const fileTypeInfo[] = {
|
||||
|
||||
static int
|
||||
cowGetBackingStore(char **res,
|
||||
+ int *format,
|
||||
const unsigned char *buf,
|
||||
size_t buf_size)
|
||||
{
|
||||
#define COW_FILENAME_MAXLEN 1024
|
||||
*res = NULL;
|
||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
||||
+
|
||||
if (buf_size < 4+4+ COW_FILENAME_MAXLEN)
|
||||
return BACKING_STORE_INVALID;
|
||||
if (buf[4+4] == '\0') /* cow_header_v2.backing_file[0] */
|
||||
@@ -160,31 +184,98 @@ cowGetBackingStore(char **res,
|
||||
return BACKING_STORE_OK;
|
||||
}
|
||||
|
||||
+
|
||||
+static int
|
||||
+qcow2GetBackingStoreFormat(int *format,
|
||||
+ const unsigned char *buf,
|
||||
+ size_t buf_size,
|
||||
+ size_t extension_start,
|
||||
+ size_t extension_end)
|
||||
+{
|
||||
+ size_t offset = extension_start;
|
||||
+
|
||||
+ /*
|
||||
+ * The extensions take format of
|
||||
+ *
|
||||
+ * int32: magic
|
||||
+ * int32: length
|
||||
+ * byte[length]: payload
|
||||
+ *
|
||||
+ * Unknown extensions can be ignored by skipping
|
||||
+ * over "length" bytes in the data stream.
|
||||
+ */
|
||||
+ while (offset < (buf_size-8) &&
|
||||
+ offset < (extension_end-8)) {
|
||||
+ unsigned int magic =
|
||||
+ (buf[offset] << 24) +
|
||||
+ (buf[offset+1] << 16) +
|
||||
+ (buf[offset+2] << 8) +
|
||||
+ (buf[offset+3]);
|
||||
+ unsigned int len =
|
||||
+ (buf[offset+4] << 24) +
|
||||
+ (buf[offset+5] << 16) +
|
||||
+ (buf[offset+6] << 8) +
|
||||
+ (buf[offset+7]);
|
||||
+
|
||||
+ offset += 8;
|
||||
+
|
||||
+ if ((offset + len) < offset)
|
||||
+ break;
|
||||
+
|
||||
+ if ((offset + len) > buf_size)
|
||||
+ break;
|
||||
+
|
||||
+ switch (magic) {
|
||||
+ case QCOW2_HDR_EXTENSION_END:
|
||||
+ goto done;
|
||||
+
|
||||
+ case QCOW2_HDR_EXTENSION_BACKING_FORMAT:
|
||||
+ if (buf[offset+len] != '\0')
|
||||
+ break;
|
||||
+ *format = virStorageFileFormatTypeFromString(
|
||||
+ ((const char *)buf)+offset);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ offset += len;
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int
|
||||
qcowXGetBackingStore(char **res,
|
||||
+ int *format,
|
||||
const unsigned char *buf,
|
||||
- size_t buf_size)
|
||||
+ size_t buf_size,
|
||||
+ bool isQCow2)
|
||||
{
|
||||
unsigned long long offset;
|
||||
unsigned long size;
|
||||
|
||||
*res = NULL;
|
||||
- if (buf_size < 4+4+8+4)
|
||||
+ if (format)
|
||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
||||
+
|
||||
+ if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4)
|
||||
return BACKING_STORE_INVALID;
|
||||
- offset = (((unsigned long long)buf[4+4] << 56)
|
||||
- | ((unsigned long long)buf[4+4+1] << 48)
|
||||
- | ((unsigned long long)buf[4+4+2] << 40)
|
||||
- | ((unsigned long long)buf[4+4+3] << 32)
|
||||
- | ((unsigned long long)buf[4+4+4] << 24)
|
||||
- | ((unsigned long long)buf[4+4+5] << 16)
|
||||
- | ((unsigned long long)buf[4+4+6] << 8)
|
||||
- | buf[4+4+7]); /* QCowHeader.backing_file_offset */
|
||||
+ offset = (((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET] << 56)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+1] << 48)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+2] << 40)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+3] << 32)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+4] << 24)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+5] << 16)
|
||||
+ | ((unsigned long long)buf[QCOWX_HDR_BACKING_FILE_OFFSET+6] << 8)
|
||||
+ | buf[QCOWX_HDR_BACKING_FILE_OFFSET+7]); /* QCowHeader.backing_file_offset */
|
||||
if (offset > buf_size)
|
||||
return BACKING_STORE_INVALID;
|
||||
- size = ((buf[4+4+8] << 24)
|
||||
- | (buf[4+4+8+1] << 16)
|
||||
- | (buf[4+4+8+2] << 8)
|
||||
- | buf[4+4+8+3]); /* QCowHeader.backing_file_size */
|
||||
+ size = ((buf[QCOWX_HDR_BACKING_FILE_SIZE] << 24)
|
||||
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+1] << 16)
|
||||
+ | (buf[QCOWX_HDR_BACKING_FILE_SIZE+2] << 8)
|
||||
+ | buf[QCOWX_HDR_BACKING_FILE_SIZE+3]); /* QCowHeader.backing_file_size */
|
||||
if (size == 0)
|
||||
return BACKING_STORE_OK;
|
||||
if (offset + size > buf_size || offset + size < offset)
|
||||
@@ -197,12 +288,63 @@ qcowXGetBackingStore(char **res,
|
||||
}
|
||||
memcpy(*res, buf + offset, size);
|
||||
(*res)[size] = '\0';
|
||||
+
|
||||
+ /*
|
||||
+ * Traditionally QCow2 files had a layout of
|
||||
+ *
|
||||
+ * [header]
|
||||
+ * [backingStoreName]
|
||||
+ *
|
||||
+ * Although the backingStoreName typically followed
|
||||
+ * the header immediately, this was not required by
|
||||
+ * the format. By specifying a higher byte offset for
|
||||
+ * the backing file offset in the header, it was
|
||||
+ * possible to leave space between the header and
|
||||
+ * start of backingStore.
|
||||
+ *
|
||||
+ * This hack is now used to store extensions to the
|
||||
+ * qcow2 format:
|
||||
+ *
|
||||
+ * [header]
|
||||
+ * [extensions]
|
||||
+ * [backingStoreName]
|
||||
+ *
|
||||
+ * Thus the file region to search for extensions is
|
||||
+ * between the end of the header (QCOW2_HDR_TOTAL_SIZE)
|
||||
+ * and the start of the backingStoreName (offset)
|
||||
+ */
|
||||
+ if (isQCow2)
|
||||
+ qcow2GetBackingStoreFormat(format, buf, buf_size, QCOW2_HDR_TOTAL_SIZE, offset);
|
||||
+
|
||||
return BACKING_STORE_OK;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
+qcow1GetBackingStore(char **res,
|
||||
+ int *format,
|
||||
+ const unsigned char *buf,
|
||||
+ size_t buf_size)
|
||||
+{
|
||||
+ /* QCow1 doesn't have the extensions capability
|
||||
+ * used to store backing format */
|
||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
||||
+ return qcowXGetBackingStore(res, NULL, buf, buf_size, false);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qcow2GetBackingStore(char **res,
|
||||
+ int *format,
|
||||
+ const unsigned char *buf,
|
||||
+ size_t buf_size)
|
||||
+{
|
||||
+ return qcowXGetBackingStore(res, format, buf, buf_size, true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
vmdk4GetBackingStore(char **res,
|
||||
+ int *format,
|
||||
const unsigned char *buf,
|
||||
size_t buf_size)
|
||||
{
|
||||
@@ -212,6 +354,14 @@ vmdk4GetBackingStore(char **res,
|
||||
size_t len;
|
||||
|
||||
*res = NULL;
|
||||
+ /*
|
||||
+ * Technically this should have been VMDK, since
|
||||
+ * VMDK spec / VMWare impl only support VMDK backed
|
||||
+ * by VMDK. QEMU isn't following this though and
|
||||
+ * does probing on VMDK backing files, hence we set
|
||||
+ * AUTO
|
||||
+ */
|
||||
+ *format = VIR_STORAGE_FILE_AUTO;
|
||||
|
||||
if (buf_size <= 0x200)
|
||||
return BACKING_STORE_INVALID;
|
||||
@@ -358,9 +508,12 @@ virStorageFileGetMetadataFromFD(const char *path,
|
||||
/* Validation passed, we know the file format now */
|
||||
meta->format = fileTypeInfo[i].type;
|
||||
if (fileTypeInfo[i].getBackingStore != NULL) {
|
||||
- char *base;
|
||||
+ char *backing;
|
||||
+ int backingFormat;
|
||||
|
||||
- switch (fileTypeInfo[i].getBackingStore(&base, head, len)) {
|
||||
+ switch (fileTypeInfo[i].getBackingStore(&backing,
|
||||
+ &backingFormat,
|
||||
+ head, len)) {
|
||||
case BACKING_STORE_OK:
|
||||
break;
|
||||
|
||||
@@ -370,13 +523,16 @@ virStorageFileGetMetadataFromFD(const char *path,
|
||||
case BACKING_STORE_ERROR:
|
||||
return -1;
|
||||
}
|
||||
- if (base != NULL) {
|
||||
- meta->backingStore = absolutePathFromBaseFile(path, base);
|
||||
- VIR_FREE(base);
|
||||
+ if (backing != NULL) {
|
||||
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
|
||||
+ VIR_FREE(backing);
|
||||
if (meta->backingStore == NULL) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
+ meta->backingStoreFormat = backingFormat;
|
||||
+ } else {
|
||||
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
|
||||
index 58533ee..6328ba7 100644
|
||||
--- a/src/util/storage_file.h
|
||||
+++ b/src/util/storage_file.h
|
||||
@@ -28,6 +28,7 @@
|
||||
# include <stdbool.h>
|
||||
|
||||
enum virStorageFileFormat {
|
||||
+ VIR_STORAGE_FILE_AUTO = -1,
|
||||
VIR_STORAGE_FILE_RAW = 0,
|
||||
VIR_STORAGE_FILE_DIR,
|
||||
VIR_STORAGE_FILE_BOCHS,
|
||||
@@ -47,6 +48,7 @@ VIR_ENUM_DECL(virStorageFileFormat);
|
||||
typedef struct _virStorageFileMetadata {
|
||||
int format;
|
||||
char *backingStore;
|
||||
+ int backingStoreFormat;
|
||||
unsigned long long capacity;
|
||||
bool encrypted;
|
||||
} virStorageFileMetadata;
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
From cab428b1d4d432965cee6f5afb67265557706715 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 16:39:32 +0100
|
||||
Subject: [PATCH 02/11] Remove 'type' field from FileTypeInfo struct
|
||||
|
||||
Instead of including a field in FileTypeInfo struct for the
|
||||
disk format, rely on the array index matching the format.
|
||||
Use verify() to assert the correct number of elements in the
|
||||
array.
|
||||
|
||||
* src/util/storage_file.c: remove type field from FileTypeInfo
|
||||
---
|
||||
src/util/storage_file.c | 108 +++++++++++++++++++++++-----------------------
|
||||
1 files changed, 54 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
|
||||
index 80f743e..df0e3a1 100644
|
||||
--- a/src/util/storage_file.c
|
||||
+++ b/src/util/storage_file.c
|
||||
@@ -58,7 +58,6 @@ enum {
|
||||
|
||||
/* Either 'magic' or 'extension' *must* be provided */
|
||||
struct FileTypeInfo {
|
||||
- int type; /* One of the constants above */
|
||||
const char *magic; /* Optional string of file magic
|
||||
* to check at head of file */
|
||||
const char *extension; /* Optional file extension to check */
|
||||
@@ -108,58 +107,59 @@ static int vmdk4GetBackingStore(char **, int *,
|
||||
|
||||
|
||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
||||
- /* Bochs */
|
||||
- /* XXX Untested
|
||||
- { VIR_STORAGE_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
|
||||
- LV_LITTLE_ENDIAN, 64, 0x20000,
|
||||
- 32+16+16+4+4+4+4+4, 8, 1, -1, NULL },*/
|
||||
- /* CLoop */
|
||||
- /* XXX Untested
|
||||
- { VIR_STORAGE_VOL_CLOOP, "#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", NULL,
|
||||
- LV_LITTLE_ENDIAN, -1, 0,
|
||||
- -1, 0, 0, -1, NULL }, */
|
||||
- /* Cow */
|
||||
- { VIR_STORAGE_FILE_COW, "OOOM", NULL,
|
||||
- LV_BIG_ENDIAN, 4, 2,
|
||||
- 4+4+1024+4, 8, 1, -1, cowGetBackingStore },
|
||||
- /* DMG */
|
||||
- /* XXX QEMU says there's no magic for dmg, but we should check... */
|
||||
- { VIR_STORAGE_FILE_DMG, NULL, ".dmg",
|
||||
- 0, -1, 0,
|
||||
- -1, 0, 0, -1, NULL },
|
||||
- /* XXX there's probably some magic for iso we can validate too... */
|
||||
- { VIR_STORAGE_FILE_ISO, NULL, ".iso",
|
||||
- 0, -1, 0,
|
||||
- -1, 0, 0, -1, NULL },
|
||||
- /* Parallels */
|
||||
- /* XXX Untested
|
||||
- { VIR_STORAGE_FILE_PARALLELS, "WithoutFreeSpace", NULL,
|
||||
- LV_LITTLE_ENDIAN, 16, 2,
|
||||
- 16+4+4+4+4, 4, 512, -1, NULL },
|
||||
- */
|
||||
- /* QCow */
|
||||
- { VIR_STORAGE_FILE_QCOW, "QFI", NULL,
|
||||
- LV_BIG_ENDIAN, 4, 1,
|
||||
- QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore },
|
||||
- /* QCow 2 */
|
||||
- { VIR_STORAGE_FILE_QCOW2, "QFI", NULL,
|
||||
- LV_BIG_ENDIAN, 4, 2,
|
||||
- QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore },
|
||||
- /* VMDK 3 */
|
||||
- /* XXX Untested
|
||||
- { VIR_STORAGE_FILE_VMDK, "COWD", NULL,
|
||||
- LV_LITTLE_ENDIAN, 4, 1,
|
||||
- 4+4+4, 4, 512, -1, NULL },
|
||||
- */
|
||||
- /* VMDK 4 */
|
||||
- { VIR_STORAGE_FILE_VMDK, "KDMV", NULL,
|
||||
- LV_LITTLE_ENDIAN, 4, 1,
|
||||
- 4+4+4, 8, 512, -1, vmdk4GetBackingStore },
|
||||
- /* Connectix / VirtualPC */
|
||||
- { VIR_STORAGE_FILE_VPC, "conectix", NULL,
|
||||
- LV_BIG_ENDIAN, 12, 0x10000,
|
||||
- 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL},
|
||||
+ [VIR_STORAGE_FILE_RAW] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
|
||||
+ [VIR_STORAGE_FILE_DIR] = { NULL, NULL, LV_LITTLE_ENDIAN, -1, 0, 0, 0, 0, 0, NULL },
|
||||
+ [VIR_STORAGE_FILE_BOCHS] = {
|
||||
+ /*"Bochs Virtual HD Image", */ /* Untested */ NULL,
|
||||
+ NULL,
|
||||
+ LV_LITTLE_ENDIAN, 64, 0x20000,
|
||||
+ 32+16+16+4+4+4+4+4, 8, 1, -1, NULL
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_CLOOP] = {
|
||||
+ /*"#!/bin/sh\n#V2.0 Format\nmodprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n", */ /* Untested */ NULL,
|
||||
+ NULL,
|
||||
+ LV_LITTLE_ENDIAN, -1, 0,
|
||||
+ -1, 0, 0, -1, NULL
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_COW] = {
|
||||
+ "OOOM", NULL,
|
||||
+ LV_BIG_ENDIAN, 4, 2,
|
||||
+ 4+4+1024+4, 8, 1, -1, cowGetBackingStore
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_DMG] = {
|
||||
+ NULL, /* XXX QEMU says there's no magic for dmg, but we should check... */
|
||||
+ ".dmg",
|
||||
+ 0, -1, 0,
|
||||
+ -1, 0, 0, -1, NULL
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_ISO] = {
|
||||
+ NULL, /* XXX there's probably some magic for iso we can validate too... */
|
||||
+ ".iso",
|
||||
+ 0, -1, 0,
|
||||
+ -1, 0, 0, -1, NULL
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_QCOW] = {
|
||||
+ "QFI", NULL,
|
||||
+ LV_BIG_ENDIAN, 4, 1,
|
||||
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW1_HDR_CRYPT, qcow1GetBackingStore,
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_QCOW2] = {
|
||||
+ "QFI", NULL,
|
||||
+ LV_BIG_ENDIAN, 4, 2,
|
||||
+ QCOWX_HDR_IMAGE_SIZE, 8, 1, QCOW2_HDR_CRYPT, qcow2GetBackingStore,
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_VMDK] = {
|
||||
+ "KDMV", NULL,
|
||||
+ LV_LITTLE_ENDIAN, 4, 1,
|
||||
+ 4+4+4, 8, 512, -1, vmdk4GetBackingStore
|
||||
+ },
|
||||
+ [VIR_STORAGE_FILE_VPC] = {
|
||||
+ "conectix", NULL,
|
||||
+ LV_BIG_ENDIAN, 12, 0x10000,
|
||||
+ 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, -1, NULL
|
||||
+ },
|
||||
};
|
||||
+verify(ARRAY_CARDINALITY(fileTypeInfo) == VIR_STORAGE_FILE_LAST);
|
||||
|
||||
static int
|
||||
cowGetBackingStore(char **res,
|
||||
@@ -506,7 +506,7 @@ virStorageFileGetMetadataFromFD(const char *path,
|
||||
}
|
||||
|
||||
/* Validation passed, we know the file format now */
|
||||
- meta->format = fileTypeInfo[i].type;
|
||||
+ meta->format = i;
|
||||
if (fileTypeInfo[i].getBackingStore != NULL) {
|
||||
char *backing;
|
||||
int backingFormat;
|
||||
@@ -546,7 +546,7 @@ virStorageFileGetMetadataFromFD(const char *path,
|
||||
if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
|
||||
continue;
|
||||
|
||||
- meta->format = fileTypeInfo[i].type;
|
||||
+ meta->format = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,585 +0,0 @@
|
||||
From 57482ca0be29e9e92e242c9acb577e0b770c01d1 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Tue, 15 Jun 2010 14:58:10 +0100
|
||||
Subject: [PATCH 03/11] Refactor virStorageFileGetMetadataFromFD to separate functionality
|
||||
|
||||
The virStorageFileGetMetadataFromFD did two jobs in one. First
|
||||
it probed for storage type, then it extracted metadata for the
|
||||
type. It is desirable to be able to separate these jobs, allowing
|
||||
probing without querying metadata, and querying metadata without
|
||||
probing.
|
||||
|
||||
To prepare for this, split out probing code into a new pair of
|
||||
methods
|
||||
|
||||
virStorageFileProbeFormatFromFD
|
||||
virStorageFileProbeFormat
|
||||
|
||||
* src/util/storage_file.c, src/util/storage_file.h,
|
||||
src/libvirt_private.syms: Introduce virStorageFileProbeFormat
|
||||
and virStorageFileProbeFormatFromFD
|
||||
---
|
||||
src/libvirt_private.syms | 2 +
|
||||
src/util/storage_file.c | 460 +++++++++++++++++++++++++++++++++-------------
|
||||
src/util/storage_file.h | 4 +
|
||||
3 files changed, 335 insertions(+), 131 deletions(-)
|
||||
|
||||
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
||||
index 778ceb1..4607f49 100644
|
||||
--- a/src/libvirt_private.syms
|
||||
+++ b/src/libvirt_private.syms
|
||||
@@ -628,6 +628,8 @@ virStorageGenerateQcowPassphrase;
|
||||
# storage_file.h
|
||||
virStorageFileFormatTypeToString;
|
||||
virStorageFileFormatTypeFromString;
|
||||
+virStorageFileProbeFormat;
|
||||
+virStorageFileProbeFormatFromFD;
|
||||
virStorageFileGetMetadata;
|
||||
virStorageFileGetMetadataFromFD;
|
||||
virStorageFileIsSharedFS;
|
||||
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
|
||||
index df0e3a1..221268b 100644
|
||||
--- a/src/util/storage_file.c
|
||||
+++ b/src/util/storage_file.c
|
||||
@@ -104,6 +104,9 @@ static int vmdk4GetBackingStore(char **, int *,
|
||||
#define QCOW2_HDR_EXTENSION_END 0
|
||||
#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA
|
||||
|
||||
+/* VMDK needs at least this to find backing store,
|
||||
+ * other formats are less */
|
||||
+#define STORAGE_MAX_HEAD (20*512)
|
||||
|
||||
|
||||
static struct FileTypeInfo const fileTypeInfo[] = {
|
||||
@@ -349,9 +352,14 @@ vmdk4GetBackingStore(char **res,
|
||||
size_t buf_size)
|
||||
{
|
||||
static const char prefix[] = "parentFileNameHint=\"";
|
||||
-
|
||||
- char desc[20*512 + 1], *start, *end;
|
||||
+ char *desc, *start, *end;
|
||||
size_t len;
|
||||
+ int ret = BACKING_STORE_ERROR;
|
||||
+
|
||||
+ if (VIR_ALLOC_N(desc, STORAGE_MAX_HEAD + 1) < 0) {
|
||||
+ virReportOOMError();
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
*res = NULL;
|
||||
/*
|
||||
@@ -363,29 +371,42 @@ vmdk4GetBackingStore(char **res,
|
||||
*/
|
||||
*format = VIR_STORAGE_FILE_AUTO;
|
||||
|
||||
- if (buf_size <= 0x200)
|
||||
- return BACKING_STORE_INVALID;
|
||||
+ if (buf_size <= 0x200) {
|
||||
+ ret = BACKING_STORE_INVALID;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
len = buf_size - 0x200;
|
||||
- if (len > sizeof(desc) - 1)
|
||||
- len = sizeof(desc) - 1;
|
||||
+ if (len > STORAGE_MAX_HEAD)
|
||||
+ len = STORAGE_MAX_HEAD;
|
||||
memcpy(desc, buf + 0x200, len);
|
||||
desc[len] = '\0';
|
||||
start = strstr(desc, prefix);
|
||||
- if (start == NULL)
|
||||
- return BACKING_STORE_OK;
|
||||
+ if (start == NULL) {
|
||||
+ ret = BACKING_STORE_OK;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
start += strlen(prefix);
|
||||
end = strchr(start, '"');
|
||||
- if (end == NULL)
|
||||
- return BACKING_STORE_INVALID;
|
||||
- if (end == start)
|
||||
- return BACKING_STORE_OK;
|
||||
+ if (end == NULL) {
|
||||
+ ret = BACKING_STORE_INVALID;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ if (end == start) {
|
||||
+ ret = BACKING_STORE_OK;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
*end = '\0';
|
||||
*res = strdup(start);
|
||||
if (*res == NULL) {
|
||||
virReportOOMError();
|
||||
- return BACKING_STORE_ERROR;
|
||||
+ goto cleanup;
|
||||
}
|
||||
- return BACKING_STORE_OK;
|
||||
+
|
||||
+ ret = BACKING_STORE_OK;
|
||||
+
|
||||
+cleanup:
|
||||
+ VIR_FREE(desc);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,148 +432,325 @@ absolutePathFromBaseFile(const char *base_file, const char *path)
|
||||
return res;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * Probe the header of a file to determine what type of disk image
|
||||
- * it is, and info about its capacity if available.
|
||||
- */
|
||||
-int
|
||||
-virStorageFileGetMetadataFromFD(const char *path,
|
||||
- int fd,
|
||||
- virStorageFileMetadata *meta)
|
||||
+
|
||||
+static bool
|
||||
+virStorageFileMatchesMagic(int format,
|
||||
+ unsigned char *buf,
|
||||
+ size_t buflen)
|
||||
{
|
||||
- unsigned char head[20*512]; /* vmdk4GetBackingStore needs this much. */
|
||||
- int len, i;
|
||||
+ int mlen;
|
||||
|
||||
- memset(meta, 0, sizeof (*meta));
|
||||
+ if (fileTypeInfo[format].magic == NULL)
|
||||
+ return false;
|
||||
|
||||
- /* If all else fails, call it a raw file */
|
||||
- meta->format = VIR_STORAGE_FILE_RAW;
|
||||
+ /* Validate magic data */
|
||||
+ mlen = strlen(fileTypeInfo[format].magic);
|
||||
+ if (mlen > buflen)
|
||||
+ return false;
|
||||
|
||||
- if ((len = read(fd, head, sizeof(head))) < 0) {
|
||||
- virReportSystemError(errno, _("cannot read header '%s'"), path);
|
||||
- return -1;
|
||||
+ if (memcmp(buf, fileTypeInfo[format].magic, mlen) != 0)
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool
|
||||
+virStorageFileMatchesExtension(int format,
|
||||
+ const char *path)
|
||||
+{
|
||||
+ if (fileTypeInfo[format].extension == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ if (virFileHasSuffix(path, fileTypeInfo[format].extension))
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static bool
|
||||
+virStorageFileMatchesVersion(int format,
|
||||
+ unsigned char *buf,
|
||||
+ size_t buflen)
|
||||
+{
|
||||
+ int version;
|
||||
+
|
||||
+ /* Validate version number info */
|
||||
+ if (fileTypeInfo[format].versionOffset == -1)
|
||||
+ return false;
|
||||
+
|
||||
+ if ((fileTypeInfo[format].versionOffset + 4) > buflen)
|
||||
+ return false;
|
||||
+
|
||||
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
|
||||
+ version =
|
||||
+ (buf[fileTypeInfo[format].versionOffset+3] << 24) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset+2] << 16) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset+1] << 8) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset]);
|
||||
+ } else {
|
||||
+ version =
|
||||
+ (buf[fileTypeInfo[format].versionOffset] << 24) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset+1] << 16) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset+2] << 8) |
|
||||
+ (buf[fileTypeInfo[format].versionOffset+3]);
|
||||
}
|
||||
+ if (version != fileTypeInfo[format].versionNumber)
|
||||
+ return false;
|
||||
|
||||
- /* First check file magic */
|
||||
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
||||
- int mlen;
|
||||
-
|
||||
- if (fileTypeInfo[i].magic == NULL)
|
||||
- continue;
|
||||
-
|
||||
- /* Validate magic data */
|
||||
- mlen = strlen(fileTypeInfo[i].magic);
|
||||
- if (mlen > len)
|
||||
- continue;
|
||||
- if (memcmp(head, fileTypeInfo[i].magic, mlen) != 0)
|
||||
- continue;
|
||||
-
|
||||
- /* Validate version number info */
|
||||
- if (fileTypeInfo[i].versionNumber != -1) {
|
||||
- int version;
|
||||
-
|
||||
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
|
||||
- version = (head[fileTypeInfo[i].versionOffset+3] << 24) |
|
||||
- (head[fileTypeInfo[i].versionOffset+2] << 16) |
|
||||
- (head[fileTypeInfo[i].versionOffset+1] << 8) |
|
||||
- head[fileTypeInfo[i].versionOffset];
|
||||
- } else {
|
||||
- version = (head[fileTypeInfo[i].versionOffset] << 24) |
|
||||
- (head[fileTypeInfo[i].versionOffset+1] << 16) |
|
||||
- (head[fileTypeInfo[i].versionOffset+2] << 8) |
|
||||
- head[fileTypeInfo[i].versionOffset+3];
|
||||
- }
|
||||
- if (version != fileTypeInfo[i].versionNumber)
|
||||
- continue;
|
||||
- }
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
- /* Optionally extract capacity from file */
|
||||
- if (fileTypeInfo[i].sizeOffset != -1) {
|
||||
- if (fileTypeInfo[i].endian == LV_LITTLE_ENDIAN) {
|
||||
- meta->capacity =
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7] << 56) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 48) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 40) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 32) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 24) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 16) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 8) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset]);
|
||||
- } else {
|
||||
- meta->capacity =
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset] << 56) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+1] << 48) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+2] << 40) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+3] << 32) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+4] << 24) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+5] << 16) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+6] << 8) |
|
||||
- ((unsigned long long)head[fileTypeInfo[i].sizeOffset+7]);
|
||||
- }
|
||||
- /* Avoid unlikely, but theoretically possible overflow */
|
||||
- if (meta->capacity > (ULLONG_MAX / fileTypeInfo[i].sizeMultiplier))
|
||||
- continue;
|
||||
- meta->capacity *= fileTypeInfo[i].sizeMultiplier;
|
||||
- }
|
||||
|
||||
- if (fileTypeInfo[i].qcowCryptOffset != -1) {
|
||||
- int crypt_format;
|
||||
+static int
|
||||
+virStorageFileGetMetadataFromBuf(int format,
|
||||
+ const char *path,
|
||||
+ unsigned char *buf,
|
||||
+ size_t buflen,
|
||||
+ virStorageFileMetadata *meta)
|
||||
+{
|
||||
+ /* XXX we should consider moving virStorageBackendUpdateVolInfo
|
||||
+ * code into this method, for non-magic files
|
||||
+ */
|
||||
+ if (!fileTypeInfo[format].magic) {
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- crypt_format = (head[fileTypeInfo[i].qcowCryptOffset] << 24) |
|
||||
- (head[fileTypeInfo[i].qcowCryptOffset+1] << 16) |
|
||||
- (head[fileTypeInfo[i].qcowCryptOffset+2] << 8) |
|
||||
- head[fileTypeInfo[i].qcowCryptOffset+3];
|
||||
- meta->encrypted = crypt_format != 0;
|
||||
+ /* Optionally extract capacity from file */
|
||||
+ if (fileTypeInfo[format].sizeOffset != -1) {
|
||||
+ if ((fileTypeInfo[format].sizeOffset + 8) > buflen)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (fileTypeInfo[format].endian == LV_LITTLE_ENDIAN) {
|
||||
+ meta->capacity =
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7] << 56) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 48) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 40) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 32) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 24) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 16) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 8) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset]);
|
||||
+ } else {
|
||||
+ meta->capacity =
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset] << 56) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+1] << 48) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+2] << 40) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+3] << 32) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+4] << 24) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+5] << 16) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+6] << 8) |
|
||||
+ ((unsigned long long)buf[fileTypeInfo[format].sizeOffset+7]);
|
||||
}
|
||||
+ /* Avoid unlikely, but theoretically possible overflow */
|
||||
+ if (meta->capacity > (ULLONG_MAX / fileTypeInfo[format].sizeMultiplier))
|
||||
+ return 1;
|
||||
+ meta->capacity *= fileTypeInfo[format].sizeMultiplier;
|
||||
+ }
|
||||
|
||||
- /* Validation passed, we know the file format now */
|
||||
- meta->format = i;
|
||||
- if (fileTypeInfo[i].getBackingStore != NULL) {
|
||||
- char *backing;
|
||||
- int backingFormat;
|
||||
+ if (fileTypeInfo[format].qcowCryptOffset != -1) {
|
||||
+ int crypt_format;
|
||||
|
||||
- switch (fileTypeInfo[i].getBackingStore(&backing,
|
||||
- &backingFormat,
|
||||
- head, len)) {
|
||||
- case BACKING_STORE_OK:
|
||||
- break;
|
||||
+ crypt_format =
|
||||
+ (buf[fileTypeInfo[format].qcowCryptOffset] << 24) |
|
||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+1] << 16) |
|
||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+2] << 8) |
|
||||
+ (buf[fileTypeInfo[format].qcowCryptOffset+3]);
|
||||
+ meta->encrypted = crypt_format != 0;
|
||||
+ }
|
||||
|
||||
- case BACKING_STORE_INVALID:
|
||||
- continue;
|
||||
+ if (fileTypeInfo[format].getBackingStore != NULL) {
|
||||
+ char *backing;
|
||||
+ int backingFormat;
|
||||
+ int ret = fileTypeInfo[format].getBackingStore(&backing,
|
||||
+ &backingFormat,
|
||||
+ buf, buflen);
|
||||
+ if (ret == BACKING_STORE_INVALID)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (ret == BACKING_STORE_ERROR)
|
||||
+ return -1;
|
||||
|
||||
- case BACKING_STORE_ERROR:
|
||||
+ if (backing != NULL) {
|
||||
+ meta->backingStore = absolutePathFromBaseFile(path, backing);
|
||||
+ VIR_FREE(backing);
|
||||
+ if (meta->backingStore == NULL) {
|
||||
+ virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
- if (backing != NULL) {
|
||||
- meta->backingStore = absolutePathFromBaseFile(path, backing);
|
||||
- VIR_FREE(backing);
|
||||
- if (meta->backingStore == NULL) {
|
||||
- virReportOOMError();
|
||||
- return -1;
|
||||
- }
|
||||
- meta->backingStoreFormat = backingFormat;
|
||||
- } else {
|
||||
- meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
||||
- }
|
||||
+ meta->backingStoreFormat = backingFormat;
|
||||
+ } else {
|
||||
+ meta->backingStore = NULL;
|
||||
+ meta->backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+virStorageFileProbeFormatFromBuf(const char *path,
|
||||
+ unsigned char *buf,
|
||||
+ size_t buflen)
|
||||
+{
|
||||
+ int format = VIR_STORAGE_FILE_RAW;
|
||||
+ int i;
|
||||
+
|
||||
+ /* First check file magic */
|
||||
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
|
||||
+ if (virStorageFileMatchesMagic(i, buf, buflen) &&
|
||||
+ virStorageFileMatchesVersion(i, buf, buflen)) {
|
||||
+ format = i;
|
||||
+ goto cleanup;
|
||||
}
|
||||
- return 0;
|
||||
}
|
||||
|
||||
/* No magic, so check file extension */
|
||||
- for (i = 0 ; i < ARRAY_CARDINALITY(fileTypeInfo) ; i++) {
|
||||
- if (fileTypeInfo[i].extension == NULL)
|
||||
- continue;
|
||||
+ for (i = 0 ; i < VIR_STORAGE_FILE_LAST ; i++) {
|
||||
+ if (virStorageFileMatchesExtension(i, path)) {
|
||||
+ format = i;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (!virFileHasSuffix(path, fileTypeInfo[i].extension))
|
||||
- continue;
|
||||
+cleanup:
|
||||
+ return format;
|
||||
+}
|
||||
|
||||
- meta->format = i;
|
||||
- return 0;
|
||||
+
|
||||
+/**
|
||||
+ * virStorageFileProbeFormatFromFD:
|
||||
+ *
|
||||
+ * Probe for the format of 'fd' (which is an open file descriptor
|
||||
+ * pointing to 'path'), returning the detected disk format.
|
||||
+ *
|
||||
+ * Callers are advised never to trust the returned 'format'
|
||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
+ * malicious guest can turn a file into any other non-raw
|
||||
+ * format at will.
|
||||
+ *
|
||||
+ * Best option: Don't use this function
|
||||
+ */
|
||||
+int
|
||||
+virStorageFileProbeFormatFromFD(const char *path, int fd)
|
||||
+{
|
||||
+ unsigned char *head;
|
||||
+ ssize_t len = STORAGE_MAX_HEAD;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (VIR_ALLOC_N(head, len) < 0) {
|
||||
+ virReportOOMError();
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
||||
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ if ((len = read(fd, head, len)) < 0) {
|
||||
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = virStorageFileProbeFormatFromBuf(path, head, len);
|
||||
+
|
||||
+cleanup:
|
||||
+ VIR_FREE(head);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/**
|
||||
+ * virStorageFileProbeFormat:
|
||||
+ *
|
||||
+ * Probe for the format of 'path', returning the detected
|
||||
+ * disk format.
|
||||
+ *
|
||||
+ * Callers are advised never to trust the returned 'format'
|
||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
+ * malicious guest can turn a raw file into any other non-raw
|
||||
+ * format at will.
|
||||
+ *
|
||||
+ * Best option: Don't use this function
|
||||
+ */
|
||||
+int
|
||||
+virStorageFileProbeFormat(const char *path)
|
||||
+{
|
||||
+ int fd, ret;
|
||||
+
|
||||
+ if ((fd = open(path, O_RDONLY)) < 0) {
|
||||
+ virReportSystemError(errno, _("cannot open file '%s'"), path);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ret = virStorageFileProbeFormatFromFD(path, fd);
|
||||
+
|
||||
+ close(fd);
|
||||
+
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * virStorageFileGetMetadataFromFD:
|
||||
+ *
|
||||
+ * Probe for the format of 'fd' (which is an open file descriptor
|
||||
+ * for the file 'path'), filling 'meta' with the detected
|
||||
+ * format and other associated metadata.
|
||||
+ *
|
||||
+ * Callers are advised never to trust the returned 'meta->format'
|
||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
+ * malicious guest can turn a raw file into any other non-raw
|
||||
+ * format at will.
|
||||
+ */
|
||||
+int
|
||||
+virStorageFileGetMetadataFromFD(const char *path,
|
||||
+ int fd,
|
||||
+ virStorageFileMetadata *meta)
|
||||
+{
|
||||
+ unsigned char *head;
|
||||
+ ssize_t len = STORAGE_MAX_HEAD;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (VIR_ALLOC_N(head, len) < 0) {
|
||||
+ virReportOOMError();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ memset(meta, 0, sizeof (*meta));
|
||||
+
|
||||
+ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
||||
+ virReportSystemError(errno, _("cannot set to start of '%s'"), path);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ if ((len = read(fd, head, len)) < 0) {
|
||||
+ virReportSystemError(errno, _("cannot read header '%s'"), path);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
|
||||
+
|
||||
+ ret = virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
|
||||
+
|
||||
+cleanup:
|
||||
+ VIR_FREE(head);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * virStorageFileGetMetadata:
|
||||
+ *
|
||||
+ * Probe for the format of 'path', filling 'meta' with the detected
|
||||
+ * format and other associated metadata.
|
||||
+ *
|
||||
+ * Callers are advised never to trust the returned 'meta->format'
|
||||
+ * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
+ * malicious guest can turn a raw file into any other non-raw
|
||||
+ * format at will.
|
||||
+ */
|
||||
int
|
||||
virStorageFileGetMetadata(const char *path,
|
||||
virStorageFileMetadata *meta)
|
||||
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
|
||||
index 6328ba7..3420d44 100644
|
||||
--- a/src/util/storage_file.h
|
||||
+++ b/src/util/storage_file.h
|
||||
@@ -57,6 +57,10 @@ typedef struct _virStorageFileMetadata {
|
||||
# define DEV_BSIZE 512
|
||||
# endif
|
||||
|
||||
+int virStorageFileProbeFormat(const char *path);
|
||||
+int virStorageFileProbeFormatFromFD(const char *path,
|
||||
+ int fd);
|
||||
+
|
||||
int virStorageFileGetMetadata(const char *path,
|
||||
virStorageFileMetadata *meta);
|
||||
int virStorageFileGetMetadataFromFD(const char *path,
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,285 +0,0 @@
|
||||
From 726a63a437efd96510ce316bf30d16f213d4db27 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Tue, 15 Jun 2010 16:15:51 +0100
|
||||
Subject: [PATCH 04/11] Require format to be passed into virStorageFileGetMetadata
|
||||
|
||||
Require the disk image to be passed into virStorageFileGetMetadata.
|
||||
If this is set to VIR_STORAGE_FILE_AUTO, then the format will be
|
||||
resolved using probing. This makes it easier to control when
|
||||
probing will be used
|
||||
|
||||
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
|
||||
src/security/security_selinux.c, src/security/virt-aa-helper.c:
|
||||
Set VIR_STORAGE_FILE_AUTO when calling virStorageFileGetMetadata.
|
||||
* src/storage/storage_backend_fs.c: Probe for disk format before
|
||||
calling virStorageFileGetMetadata.
|
||||
* src/util/storage_file.h, src/util/storage_file.c: Remove format
|
||||
from virStorageFileMeta struct & require it to be passed into
|
||||
method.
|
||||
---
|
||||
src/qemu/qemu_driver.c | 27 +++++++++++++++++---
|
||||
src/qemu/qemu_security_dac.c | 4 ++-
|
||||
src/security/security_selinux.c | 4 ++-
|
||||
src/security/virt-aa-helper.c | 4 ++-
|
||||
src/storage/storage_backend_fs.c | 11 ++++++--
|
||||
src/util/storage_file.c | 50 +++++++++++++++++++++++++------------
|
||||
src/util/storage_file.h | 3 +-
|
||||
7 files changed, 76 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 487bfa3..97f2990 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -3069,7 +3069,9 @@ static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
|
||||
}
|
||||
}
|
||||
|
||||
- rc = virStorageFileGetMetadata(path, &meta);
|
||||
+ rc = virStorageFileGetMetadata(path,
|
||||
+ VIR_STORAGE_FILE_AUTO,
|
||||
+ &meta);
|
||||
if (rc < 0)
|
||||
VIR_WARN("Unable to lookup parent image for %s", path);
|
||||
|
||||
@@ -3119,7 +3121,9 @@ static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
|
||||
}
|
||||
}
|
||||
|
||||
- rc = virStorageFileGetMetadata(path, &meta);
|
||||
+ rc = virStorageFileGetMetadata(path,
|
||||
+ VIR_STORAGE_FILE_AUTO,
|
||||
+ &meta);
|
||||
if (rc < 0)
|
||||
VIR_WARN("Unable to lookup parent image for %s", path);
|
||||
|
||||
@@ -9614,6 +9618,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
virDomainDiskDefPtr disk = NULL;
|
||||
struct stat sb;
|
||||
int i;
|
||||
+ int format;
|
||||
|
||||
virCheckFlags(0, -1);
|
||||
|
||||
@@ -9658,7 +9663,21 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
}
|
||||
|
||||
/* Probe for magic formats */
|
||||
- if (virStorageFileGetMetadataFromFD(path, fd, &meta) < 0)
|
||||
+ if (disk->driverType) {
|
||||
+ if ((format = virStorageFileFormatTypeFromString(disk->driverType)) < 0) {
|
||||
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("unknown disk format %s for %s"),
|
||||
+ disk->driverType, disk->src);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ if (virStorageFileGetMetadataFromFD(path, fd,
|
||||
+ format,
|
||||
+ &meta) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Get info for normal formats */
|
||||
@@ -9706,7 +9725,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
highest allocated extent from QEMU */
|
||||
if (virDomainObjIsActive(vm) &&
|
||||
disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
|
||||
- meta.format != VIR_STORAGE_FILE_RAW &&
|
||||
+ format != VIR_STORAGE_FILE_RAW &&
|
||||
S_ISBLK(sb.st_mode)) {
|
||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||
if (qemuDomainObjBeginJob(vm) < 0)
|
||||
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
|
||||
index 95015b0..acfe48e 100644
|
||||
--- a/src/qemu/qemu_security_dac.c
|
||||
+++ b/src/qemu/qemu_security_dac.c
|
||||
@@ -115,7 +115,9 @@ qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
||||
virStorageFileMetadata meta;
|
||||
int ret;
|
||||
|
||||
- ret = virStorageFileGetMetadata(path, &meta);
|
||||
+ ret = virStorageFileGetMetadata(path,
|
||||
+ VIR_STORAGE_FILE_AUTO,
|
||||
+ &meta);
|
||||
|
||||
if (path != disk->src)
|
||||
VIR_FREE(path);
|
||||
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
|
||||
index e5eef19..5c0f002 100644
|
||||
--- a/src/security/security_selinux.c
|
||||
+++ b/src/security/security_selinux.c
|
||||
@@ -457,7 +457,9 @@ SELinuxSetSecurityImageLabel(virDomainObjPtr vm,
|
||||
virStorageFileMetadata meta;
|
||||
int ret;
|
||||
|
||||
- ret = virStorageFileGetMetadata(path, &meta);
|
||||
+ ret = virStorageFileGetMetadata(path,
|
||||
+ VIR_STORAGE_FILE_AUTO,
|
||||
+ &meta);
|
||||
|
||||
if (path != disk->src)
|
||||
VIR_FREE(path);
|
||||
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
|
||||
index c66f107..2c045e6 100644
|
||||
--- a/src/security/virt-aa-helper.c
|
||||
+++ b/src/security/virt-aa-helper.c
|
||||
@@ -830,7 +830,9 @@ get_files(vahControl * ctl)
|
||||
do {
|
||||
virStorageFileMetadata meta;
|
||||
|
||||
- ret = virStorageFileGetMetadata(path, &meta);
|
||||
+ ret = virStorageFileGetMetadata(path,
|
||||
+ VIR_STORAGE_FILE_AUTO,
|
||||
+ &meta);
|
||||
|
||||
if (path != ctl->def->disks[i]->src)
|
||||
VIR_FREE(path);
|
||||
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
|
||||
index f0cd770..d3ac0fe 100644
|
||||
--- a/src/storage/storage_backend_fs.c
|
||||
+++ b/src/storage/storage_backend_fs.c
|
||||
@@ -75,14 +75,19 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
||||
|
||||
memset(&meta, 0, sizeof(meta));
|
||||
|
||||
- if (virStorageFileGetMetadataFromFD(target->path, fd, &meta) < 0) {
|
||||
+ if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
- close(fd);
|
||||
+ if (virStorageFileGetMetadataFromFD(target->path, fd,
|
||||
+ target->format,
|
||||
+ &meta) < 0) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- target->format = meta.format;
|
||||
+ close(fd);
|
||||
|
||||
if (backingStore) {
|
||||
*backingStore = meta.backingStore;
|
||||
diff --git a/src/util/storage_file.c b/src/util/storage_file.c
|
||||
index 221268b..9712d92 100644
|
||||
--- a/src/util/storage_file.c
|
||||
+++ b/src/util/storage_file.c
|
||||
@@ -696,18 +696,23 @@ virStorageFileProbeFormat(const char *path)
|
||||
/**
|
||||
* virStorageFileGetMetadataFromFD:
|
||||
*
|
||||
- * Probe for the format of 'fd' (which is an open file descriptor
|
||||
- * for the file 'path'), filling 'meta' with the detected
|
||||
- * format and other associated metadata.
|
||||
+ * Extract metadata about the storage volume with the specified
|
||||
+ * image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
||||
+ * will probe to automatically identify the format.
|
||||
*
|
||||
- * Callers are advised never to trust the returned 'meta->format'
|
||||
- * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
- * malicious guest can turn a raw file into any other non-raw
|
||||
- * format at will.
|
||||
+ * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
||||
+ * format, since a malicious guest can turn a raw file into any
|
||||
+ * other non-raw format at will.
|
||||
+ *
|
||||
+ * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
||||
+ * it indicates the image didn't specify an explicit format for its
|
||||
+ * backing store. Callers are advised against probing for the
|
||||
+ * backing store format in this case.
|
||||
*/
|
||||
int
|
||||
virStorageFileGetMetadataFromFD(const char *path,
|
||||
int fd,
|
||||
+ int format,
|
||||
virStorageFileMetadata *meta)
|
||||
{
|
||||
unsigned char *head;
|
||||
@@ -731,9 +736,16 @@ virStorageFileGetMetadataFromFD(const char *path,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- meta->format = virStorageFileProbeFormatFromBuf(path, head, len);
|
||||
+ if (format == VIR_STORAGE_FILE_AUTO)
|
||||
+ format = virStorageFileProbeFormatFromBuf(path, head, len);
|
||||
+
|
||||
+ if (format < 0 ||
|
||||
+ format >= VIR_STORAGE_FILE_LAST) {
|
||||
+ virReportSystemError(EINVAL, _("unknown storage file format %d"), format);
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
- ret = virStorageFileGetMetadataFromBuf(meta->format, path, head, len, meta);
|
||||
+ ret = virStorageFileGetMetadataFromBuf(format, path, head, len, meta);
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(head);
|
||||
@@ -743,16 +755,22 @@ cleanup:
|
||||
/**
|
||||
* virStorageFileGetMetadata:
|
||||
*
|
||||
- * Probe for the format of 'path', filling 'meta' with the detected
|
||||
- * format and other associated metadata.
|
||||
+ * Extract metadata about the storage volume with the specified
|
||||
+ * image format. If image format is VIR_STORAGE_FILE_AUTO, it
|
||||
+ * will probe to automatically identify the format.
|
||||
*
|
||||
- * Callers are advised never to trust the returned 'meta->format'
|
||||
- * unless it is listed as VIR_STORAGE_FILE_RAW, since a
|
||||
- * malicious guest can turn a raw file into any other non-raw
|
||||
- * format at will.
|
||||
+ * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
|
||||
+ * format, since a malicious guest can turn a raw file into any
|
||||
+ * other non-raw format at will.
|
||||
+ *
|
||||
+ * If the returned meta.backingStoreFormat is VIR_STORAGE_FILE_AUTO
|
||||
+ * it indicates the image didn't specify an explicit format for its
|
||||
+ * backing store. Callers are advised against probing for the
|
||||
+ * backing store format in this case.
|
||||
*/
|
||||
int
|
||||
virStorageFileGetMetadata(const char *path,
|
||||
+ int format,
|
||||
virStorageFileMetadata *meta)
|
||||
{
|
||||
int fd, ret;
|
||||
@@ -762,7 +780,7 @@ virStorageFileGetMetadata(const char *path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
- ret = virStorageFileGetMetadataFromFD(path, fd, meta);
|
||||
+ ret = virStorageFileGetMetadataFromFD(path, fd, format, meta);
|
||||
|
||||
close(fd);
|
||||
|
||||
diff --git a/src/util/storage_file.h b/src/util/storage_file.h
|
||||
index 3420d44..6853182 100644
|
||||
--- a/src/util/storage_file.h
|
||||
+++ b/src/util/storage_file.h
|
||||
@@ -46,7 +46,6 @@ enum virStorageFileFormat {
|
||||
VIR_ENUM_DECL(virStorageFileFormat);
|
||||
|
||||
typedef struct _virStorageFileMetadata {
|
||||
- int format;
|
||||
char *backingStore;
|
||||
int backingStoreFormat;
|
||||
unsigned long long capacity;
|
||||
@@ -62,9 +61,11 @@ int virStorageFileProbeFormatFromFD(const char *path,
|
||||
int fd);
|
||||
|
||||
int virStorageFileGetMetadata(const char *path,
|
||||
+ int format,
|
||||
virStorageFileMetadata *meta);
|
||||
int virStorageFileGetMetadataFromFD(const char *path,
|
||||
int fd,
|
||||
+ int format,
|
||||
virStorageFileMetadata *meta);
|
||||
|
||||
int virStorageFileIsSharedFS(const char *path);
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
From ac5067f1e2e98181ee0e9230f756697f50d853eb Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 18:09:15 +0100
|
||||
Subject: [PATCH 05/11] Add an API for iterating over disk paths
|
||||
|
||||
There is duplicated code which iterates over disk backing stores
|
||||
performing some action. Provide a convenient helper for doing
|
||||
this to eliminate duplication & risk of mistakes with disk format
|
||||
probing
|
||||
|
||||
* src/conf/domain_conf.c, src/conf/domain_conf.h,
|
||||
src/libvirt_private.syms: Add virDomainDiskDefForeachPath()
|
||||
---
|
||||
src/conf/domain_conf.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
src/conf/domain_conf.h | 11 +++++
|
||||
src/libvirt_private.syms | 1 +
|
||||
3 files changed, 111 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index 378c06e..b20ca97 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "macvtap.h"
|
||||
#include "nwfilter_conf.h"
|
||||
#include "ignore-value.h"
|
||||
+#include "storage_file.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||
|
||||
@@ -7273,4 +7274,102 @@ done:
|
||||
}
|
||||
|
||||
|
||||
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
||||
+ bool allowProbing,
|
||||
+ bool ignoreOpenFailure,
|
||||
+ virDomainDiskDefPathIterator iter,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ virHashTablePtr paths;
|
||||
+ int format;
|
||||
+ int ret = -1;
|
||||
+ size_t depth = 0;
|
||||
+ char *nextpath = NULL;
|
||||
+
|
||||
+ if (!disk->src)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (disk->driverType) {
|
||||
+ const char *formatStr = disk->driverType;
|
||||
+ if (STREQ(formatStr, "aio"))
|
||||
+ formatStr = "raw"; /* Xen compat */
|
||||
+
|
||||
+ if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) {
|
||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("unknown disk format '%s' for %s"),
|
||||
+ disk->driverType, disk->src);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (allowProbing) {
|
||||
+ format = VIR_STORAGE_FILE_AUTO;
|
||||
+ } else {
|
||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("no disk format for %s and probing is disabled"),
|
||||
+ disk->src);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ paths = virHashCreate(5);
|
||||
+
|
||||
+ do {
|
||||
+ virStorageFileMetadata meta;
|
||||
+ const char *path = nextpath ? nextpath : disk->src;
|
||||
+ int fd;
|
||||
+
|
||||
+ if (iter(disk, path, depth, opaque) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if (virHashLookup(paths, path)) {
|
||||
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("backing store for %s is self-referential"),
|
||||
+ disk->src);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ if ((fd = open(path, O_RDONLY)) < 0) {
|
||||
+ if (ignoreOpenFailure) {
|
||||
+ char ebuf[1024];
|
||||
+ VIR_WARN("Ignoring open failure on %s: %s", path,
|
||||
+ virStrerror(errno, ebuf, sizeof(ebuf)));
|
||||
+ break;
|
||||
+ } else {
|
||||
+ virReportSystemError(errno,
|
||||
+ _("unable to open disk path %s"),
|
||||
+ path);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
|
||||
+ close(fd);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ close(fd);
|
||||
+
|
||||
+ if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
|
||||
+ virReportOOMError();
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ depth++;
|
||||
+ nextpath = meta.backingStore;
|
||||
+
|
||||
+ format = meta.backingStoreFormat;
|
||||
+
|
||||
+ if (format == VIR_STORAGE_FILE_AUTO &&
|
||||
+ !allowProbing)
|
||||
+ format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */
|
||||
+ } while (nextpath);
|
||||
+
|
||||
+ ret = 0;
|
||||
+
|
||||
+cleanup:
|
||||
+ virHashFree(paths, NULL);
|
||||
+ VIR_FREE(nextpath);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#endif /* ! PROXY */
|
||||
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
||||
index 01da17e..d46869e 100644
|
||||
--- a/src/conf/domain_conf.h
|
||||
+++ b/src/conf/domain_conf.h
|
||||
@@ -1079,6 +1079,17 @@ int virDomainChrDefForeach(virDomainDefPtr def,
|
||||
void *opaque);
|
||||
|
||||
|
||||
+typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk,
|
||||
+ const char *path,
|
||||
+ size_t depth,
|
||||
+ void *opaque);
|
||||
+
|
||||
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
|
||||
+ bool allowProbing,
|
||||
+ bool ignoreOpenFailure,
|
||||
+ virDomainDiskDefPathIterator iter,
|
||||
+ void *opaque);
|
||||
+
|
||||
VIR_ENUM_DECL(virDomainVirt)
|
||||
VIR_ENUM_DECL(virDomainBoot)
|
||||
VIR_ENUM_DECL(virDomainFeature)
|
||||
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
||||
index 4607f49..b5f3695 100644
|
||||
--- a/src/libvirt_private.syms
|
||||
+++ b/src/libvirt_private.syms
|
||||
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
|
||||
virDomainSnapshotAssignDef;
|
||||
virDomainObjAssignDef;
|
||||
virDomainChrDefForeach;
|
||||
+virDomainDiskDefForeachPath;
|
||||
|
||||
|
||||
# domain_event.h
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
From 54c1bb731d2b19a46a594cf9682c022f1e1114d2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Tue, 15 Jun 2010 16:40:47 +0100
|
||||
Subject: [PATCH 06/11] Convert all disk backing store loops to shared helper API
|
||||
|
||||
Update the QEMU cgroups code, QEMU DAC security driver, SELinux
|
||||
and AppArmour security drivers over to use the shared helper API
|
||||
virDomainDiskDefForeachPath().
|
||||
|
||||
* src/qemu/qemu_driver.c, src/qemu/qemu_security_dac.c,
|
||||
src/security/security_selinux.c, src/security/virt-aa-helper.c:
|
||||
Convert over to use virDomainDiskDefForeachPath()
|
||||
---
|
||||
src/qemu/qemu_driver.c | 161 ++++++++++++++++----------------------
|
||||
src/qemu/qemu_security_dac.c | 47 ++++--------
|
||||
src/security/security_selinux.c | 67 +++++++----------
|
||||
src/security/virt-aa-helper.c | 71 ++++++++----------
|
||||
4 files changed, 142 insertions(+), 204 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 97f2990..99aeffa 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -3040,107 +3040,82 @@ static const char *const defaultDeviceACL[] = {
|
||||
#define DEVICE_PTY_MAJOR 136
|
||||
#define DEVICE_SND_MAJOR 116
|
||||
|
||||
-static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
|
||||
- virDomainObjPtr vm,
|
||||
- virDomainDiskDefPtr disk)
|
||||
-{
|
||||
- char *path = disk->src;
|
||||
- int ret = -1;
|
||||
|
||||
- while (path != NULL) {
|
||||
- virStorageFileMetadata meta;
|
||||
- int rc;
|
||||
+static int qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
||||
+ const char *path,
|
||||
+ size_t depth ATTRIBUTE_UNUSED,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ virCgroupPtr cgroup = opaque;
|
||||
+ int rc;
|
||||
|
||||
- VIR_DEBUG("Process path '%s' for disk", path);
|
||||
- rc = virCgroupAllowDevicePath(cgroup, path);
|
||||
- if (rc != 0) {
|
||||
- /* Get this for non-block devices */
|
||||
- if (rc == -EINVAL) {
|
||||
- VIR_DEBUG("Ignoring EINVAL for %s", path);
|
||||
- } else if (rc == -EACCES) { /* Get this for root squash NFS */
|
||||
- VIR_DEBUG("Ignoring EACCES for %s", path);
|
||||
- } else {
|
||||
- virReportSystemError(-rc,
|
||||
- _("Unable to allow device %s for %s"),
|
||||
- path, vm->def->name);
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ VIR_DEBUG("Process path %s for disk", path);
|
||||
+ /* XXX RO vs RW */
|
||||
+ rc = virCgroupAllowDevicePath(cgroup, path);
|
||||
+ if (rc != 0) {
|
||||
+ /* Get this for non-block devices */
|
||||
+ if (rc == -EINVAL) {
|
||||
+ VIR_DEBUG("Ignoring EINVAL for %s", path);
|
||||
+ } else if (rc == -EACCES) { /* Get this for root squash NFS */
|
||||
+ VIR_DEBUG("Ignoring EACCES for %s", path);
|
||||
+ } else {
|
||||
+ virReportSystemError(-rc,
|
||||
+ _("Unable to allow access for disk path %s"),
|
||||
+ path);
|
||||
+ return -1;
|
||||
}
|
||||
-
|
||||
- rc = virStorageFileGetMetadata(path,
|
||||
- VIR_STORAGE_FILE_AUTO,
|
||||
- &meta);
|
||||
- if (rc < 0)
|
||||
- VIR_WARN("Unable to lookup parent image for %s", path);
|
||||
-
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- path = NULL;
|
||||
-
|
||||
- if (rc < 0)
|
||||
- break; /* Treating as non fatal */
|
||||
-
|
||||
- path = meta.backingStore;
|
||||
}
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
- ret = 0;
|
||||
|
||||
-cleanup:
|
||||
- return ret;
|
||||
+static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
|
||||
+ virDomainDiskDefPtr disk)
|
||||
+{
|
||||
+ return virDomainDiskDefForeachPath(disk,
|
||||
+ true,
|
||||
+ true,
|
||||
+ qemuSetupDiskPathAllow,
|
||||
+ cgroup);
|
||||
}
|
||||
|
||||
|
||||
-static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
|
||||
- virDomainObjPtr vm,
|
||||
- virDomainDiskDefPtr disk)
|
||||
+static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
||||
+ const char *path,
|
||||
+ size_t depth ATTRIBUTE_UNUSED,
|
||||
+ void *opaque)
|
||||
{
|
||||
- char *path = disk->src;
|
||||
- int ret = -1;
|
||||
-
|
||||
- while (path != NULL) {
|
||||
- virStorageFileMetadata meta;
|
||||
- int rc;
|
||||
+ virCgroupPtr cgroup = opaque;
|
||||
+ int rc;
|
||||
|
||||
- VIR_DEBUG("Process path '%s' for disk", path);
|
||||
- rc = virCgroupDenyDevicePath(cgroup, path);
|
||||
- if (rc != 0) {
|
||||
- /* Get this for non-block devices */
|
||||
- if (rc == -EINVAL) {
|
||||
- VIR_DEBUG("Ignoring EINVAL for %s", path);
|
||||
- } else if (rc == -EACCES) { /* Get this for root squash NFS */
|
||||
- VIR_DEBUG("Ignoring EACCES for %s", path);
|
||||
- } else {
|
||||
- virReportSystemError(-rc,
|
||||
- _("Unable to deny device %s for %s"),
|
||||
- path, vm->def->name);
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ VIR_DEBUG("Process path %s for disk", path);
|
||||
+ /* XXX RO vs RW */
|
||||
+ rc = virCgroupDenyDevicePath(cgroup, path);
|
||||
+ if (rc != 0) {
|
||||
+ /* Get this for non-block devices */
|
||||
+ if (rc == -EINVAL) {
|
||||
+ VIR_DEBUG("Ignoring EINVAL for %s", path);
|
||||
+ } else if (rc == -EACCES) { /* Get this for root squash NFS */
|
||||
+ VIR_DEBUG("Ignoring EACCES for %s", path);
|
||||
+ } else {
|
||||
+ virReportSystemError(-rc,
|
||||
+ _("Unable to allow access for disk path %s"),
|
||||
+ path);
|
||||
+ return -1;
|
||||
}
|
||||
-
|
||||
- rc = virStorageFileGetMetadata(path,
|
||||
- VIR_STORAGE_FILE_AUTO,
|
||||
- &meta);
|
||||
- if (rc < 0)
|
||||
- VIR_WARN("Unable to lookup parent image for %s", path);
|
||||
-
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- path = NULL;
|
||||
-
|
||||
- if (rc < 0)
|
||||
- break; /* Treating as non fatal */
|
||||
-
|
||||
- path = meta.backingStore;
|
||||
}
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
- ret = 0;
|
||||
|
||||
-cleanup:
|
||||
- return ret;
|
||||
+static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
|
||||
+ virDomainDiskDefPtr disk)
|
||||
+{
|
||||
+ return virDomainDiskDefForeachPath(disk,
|
||||
+ true,
|
||||
+ true,
|
||||
+ qemuTeardownDiskPathDeny,
|
||||
+ cgroup);
|
||||
}
|
||||
|
||||
|
||||
@@ -3204,7 +3179,7 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
|
||||
}
|
||||
|
||||
for (i = 0; i < vm->def->ndisks ; i++) {
|
||||
- if (qemuSetupDiskCgroup(cgroup, vm, vm->def->disks[i]) < 0)
|
||||
+ if (qemuSetupDiskCgroup(cgroup, vm->def->disks[i]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -8035,7 +8010,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
- if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
@@ -8080,7 +8055,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
/* Fallthrough */
|
||||
}
|
||||
if (ret != 0 && cgroup) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8280,7 +8255,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
|
||||
vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
- if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
@@ -8303,7 +8278,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
|
||||
}
|
||||
|
||||
if (ret != 0 && cgroup) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8430,7 +8405,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
|
||||
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
|
||||
|
||||
if (cgroup != NULL) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8493,7 +8468,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
|
||||
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
|
||||
|
||||
if (cgroup != NULL) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
|
||||
index acfe48e..770010d 100644
|
||||
--- a/src/qemu/qemu_security_dac.c
|
||||
+++ b/src/qemu/qemu_security_dac.c
|
||||
@@ -98,45 +98,28 @@ err:
|
||||
|
||||
|
||||
static int
|
||||
+qemuSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
||||
+ const char *path,
|
||||
+ size_t depth ATTRIBUTE_UNUSED,
|
||||
+ void *opaque ATTRIBUTE_UNUSED)
|
||||
+{
|
||||
+ return qemuSecurityDACSetOwnership(path, driver->user, driver->group);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
qemuSecurityDACSetSecurityImageLabel(virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
||||
virDomainDiskDefPtr disk)
|
||||
|
||||
{
|
||||
- const char *path;
|
||||
-
|
||||
if (!driver->privileged || !driver->dynamicOwnership)
|
||||
return 0;
|
||||
|
||||
- if (!disk->src)
|
||||
- return 0;
|
||||
-
|
||||
- path = disk->src;
|
||||
- do {
|
||||
- virStorageFileMetadata meta;
|
||||
- int ret;
|
||||
-
|
||||
- ret = virStorageFileGetMetadata(path,
|
||||
- VIR_STORAGE_FILE_AUTO,
|
||||
- &meta);
|
||||
-
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- path = NULL;
|
||||
-
|
||||
- if (ret < 0)
|
||||
- return -1;
|
||||
-
|
||||
- if (meta.backingStore != NULL &&
|
||||
- qemuSecurityDACSetOwnership(meta.backingStore,
|
||||
- driver->user, driver->group) < 0) {
|
||||
- VIR_FREE(meta.backingStore);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- path = meta.backingStore;
|
||||
- } while (path != NULL);
|
||||
-
|
||||
- return qemuSecurityDACSetOwnership(disk->src, driver->user, driver->group);
|
||||
+ return virDomainDiskDefForeachPath(disk,
|
||||
+ true,
|
||||
+ false,
|
||||
+ qemuSecurityDACSetSecurityFileLabel,
|
||||
+ NULL);
|
||||
}
|
||||
|
||||
|
||||
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
|
||||
index 5c0f002..d191118 100644
|
||||
--- a/src/security/security_selinux.c
|
||||
+++ b/src/security/security_selinux.c
|
||||
@@ -439,54 +439,43 @@ SELinuxRestoreSecurityImageLabel(virDomainObjPtr vm,
|
||||
|
||||
|
||||
static int
|
||||
+SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
|
||||
+ const char *path,
|
||||
+ size_t depth,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ const virSecurityLabelDefPtr secdef = opaque;
|
||||
+
|
||||
+ if (depth == 0) {
|
||||
+ if (disk->shared) {
|
||||
+ return SELinuxSetFilecon(path, default_image_context);
|
||||
+ } else if (disk->readonly) {
|
||||
+ return SELinuxSetFilecon(path, default_content_context);
|
||||
+ } else if (secdef->imagelabel) {
|
||||
+ return SELinuxSetFilecon(path, secdef->imagelabel);
|
||||
+ } else {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return SELinuxSetFilecon(path, default_content_context);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
SELinuxSetSecurityImageLabel(virDomainObjPtr vm,
|
||||
virDomainDiskDefPtr disk)
|
||||
|
||||
{
|
||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||
- const char *path;
|
||||
|
||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||
return 0;
|
||||
|
||||
- if (!disk->src)
|
||||
- return 0;
|
||||
-
|
||||
- path = disk->src;
|
||||
- do {
|
||||
- virStorageFileMetadata meta;
|
||||
- int ret;
|
||||
-
|
||||
- ret = virStorageFileGetMetadata(path,
|
||||
- VIR_STORAGE_FILE_AUTO,
|
||||
- &meta);
|
||||
-
|
||||
- if (path != disk->src)
|
||||
- VIR_FREE(path);
|
||||
- path = NULL;
|
||||
-
|
||||
- if (ret < 0)
|
||||
- break;
|
||||
-
|
||||
- if (meta.backingStore != NULL &&
|
||||
- SELinuxSetFilecon(meta.backingStore,
|
||||
- default_content_context) < 0) {
|
||||
- VIR_FREE(meta.backingStore);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- path = meta.backingStore;
|
||||
- } while (path != NULL);
|
||||
-
|
||||
- if (disk->shared) {
|
||||
- return SELinuxSetFilecon(disk->src, default_image_context);
|
||||
- } else if (disk->readonly) {
|
||||
- return SELinuxSetFilecon(disk->src, default_content_context);
|
||||
- } else if (secdef->imagelabel) {
|
||||
- return SELinuxSetFilecon(disk->src, secdef->imagelabel);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ return virDomainDiskDefForeachPath(disk,
|
||||
+ true,
|
||||
+ false,
|
||||
+ SELinuxSetSecurityFileLabel,
|
||||
+ secdef);
|
||||
}
|
||||
|
||||
|
||||
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
|
||||
index 2c045e6..9ed0cd3 100644
|
||||
--- a/src/security/virt-aa-helper.c
|
||||
+++ b/src/security/virt-aa-helper.c
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "uuid.h"
|
||||
#include "hostusb.h"
|
||||
#include "pci.h"
|
||||
-#include "storage_file.h"
|
||||
|
||||
static char *progname;
|
||||
|
||||
@@ -801,6 +800,28 @@ file_iterate_pci_cb(pciDevice *dev ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
static int
|
||||
+add_file_path(virDomainDiskDefPtr disk,
|
||||
+ const char *path,
|
||||
+ size_t depth,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ virBufferPtr buf = opaque;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (depth == 0) {
|
||||
+ if (disk->readonly)
|
||||
+ ret = vah_add_file(buf, path, "r");
|
||||
+ else
|
||||
+ ret = vah_add_file(buf, path, "rw");
|
||||
+ } else {
|
||||
+ ret = vah_add_file(buf, path, "r");
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
get_files(vahControl * ctl)
|
||||
{
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
@@ -821,45 +842,15 @@ get_files(vahControl * ctl)
|
||||
goto clean;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ctl->def->ndisks; i++)
|
||||
- if (ctl->def->disks[i] && ctl->def->disks[i]->src) {
|
||||
- int ret;
|
||||
- const char *path;
|
||||
-
|
||||
- path = ctl->def->disks[i]->src;
|
||||
- do {
|
||||
- virStorageFileMetadata meta;
|
||||
-
|
||||
- ret = virStorageFileGetMetadata(path,
|
||||
- VIR_STORAGE_FILE_AUTO,
|
||||
- &meta);
|
||||
-
|
||||
- if (path != ctl->def->disks[i]->src)
|
||||
- VIR_FREE(path);
|
||||
- path = NULL;
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- vah_warning("could not open path, skipping");
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (meta.backingStore != NULL &&
|
||||
- (ret = vah_add_file(&buf, meta.backingStore, "rw")) != 0) {
|
||||
- VIR_FREE(meta.backingStore);
|
||||
- goto clean;
|
||||
- }
|
||||
-
|
||||
- path = meta.backingStore;
|
||||
- } while (path != NULL);
|
||||
-
|
||||
- if (ctl->def->disks[i]->readonly)
|
||||
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "r");
|
||||
- else
|
||||
- ret = vah_add_file(&buf, ctl->def->disks[i]->src, "rw");
|
||||
-
|
||||
- if (ret != 0)
|
||||
- goto clean;
|
||||
- }
|
||||
+ for (i = 0; i < ctl->def->ndisks; i++) {
|
||||
+ int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
|
||||
+ true,
|
||||
+ false,
|
||||
+ add_file_path,
|
||||
+ &buf);
|
||||
+ if (ret != 0)
|
||||
+ goto clean;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < ctl->def->nserials; i++)
|
||||
if (ctl->def->serials[i] && ctl->def->serials[i]->data.file.path)
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,468 +0,0 @@
|
||||
From dac2b936e77f6c76c11f162e4b175492e4803acb Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Tue, 15 Jun 2010 17:58:58 +0100
|
||||
Subject: [PATCH 08/11] Disable all disk probing in QEMU driver & add config option to re-enable
|
||||
|
||||
Disk format probing is now disabled by default. A new config
|
||||
option in /etc/qemu/qemu.conf will re-enable it for existing
|
||||
deployments where this causes trouble
|
||||
---
|
||||
src/qemu/libvirtd_qemu.aug | 1 +
|
||||
src/qemu/qemu.conf | 12 ++++++++++++
|
||||
src/qemu/qemu_conf.c | 4 ++++
|
||||
src/qemu/qemu_conf.h | 1 +
|
||||
src/qemu/qemu_driver.c | 36 +++++++++++++++++++++++-------------
|
||||
src/qemu/qemu_security_dac.c | 2 +-
|
||||
src/qemu/test_libvirtd_qemu.aug | 4 ++++
|
||||
src/security/security_apparmor.c | 12 ++++++++----
|
||||
src/security/security_driver.c | 16 ++++++++++++++--
|
||||
src/security/security_driver.h | 10 ++++++++--
|
||||
src/security/security_selinux.c | 9 ++++++---
|
||||
src/security/virt-aa-helper.c | 10 +++++++++-
|
||||
tests/seclabeltest.c | 2 +-
|
||||
13 files changed, 92 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
|
||||
index 7c9f271..47d0525 100644
|
||||
--- a/src/qemu/libvirtd_qemu.aug
|
||||
+++ b/src/qemu/libvirtd_qemu.aug
|
||||
@@ -40,6 +40,7 @@ module Libvirtd_qemu =
|
||||
| bool_entry "relaxed_acs_check"
|
||||
| bool_entry "vnc_allow_host_audio"
|
||||
| bool_entry "clear_emulator_capabilities"
|
||||
+ | bool_entry "allow_disk_format_probing"
|
||||
|
||||
(* Each enty in the config is one of the following three ... *)
|
||||
let entry = vnc_entry
|
||||
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
|
||||
index 93934f3..dc8eb83 100644
|
||||
--- a/src/qemu/qemu.conf
|
||||
+++ b/src/qemu/qemu.conf
|
||||
@@ -187,3 +187,15 @@
|
||||
# exploit the privileges and possibly do damage to the host.
|
||||
#
|
||||
# clear_emulator_capabilities = 1
|
||||
+
|
||||
+
|
||||
+
|
||||
+# If allow_disk_format_probing is enabled, libvirt will probe disk
|
||||
+# images to attempt to identify their format, when not otherwise
|
||||
+# specified in the XML. This is disabled by default.
|
||||
+#
|
||||
+# WARNING: Enabling probing is a security hole in almost all
|
||||
+# deployments. It is strongly recommended that users update their
|
||||
+# guest XML <disk> elements to include <driver type='XXXX'/>
|
||||
+# elements instead of enabling this option.
|
||||
+# allow_disk_format_probing = 1
|
||||
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
|
||||
index 988220b..3ba48bf 100644
|
||||
--- a/src/qemu/qemu_conf.c
|
||||
+++ b/src/qemu/qemu_conf.c
|
||||
@@ -365,6 +365,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
|
||||
CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
|
||||
if (p) driver->clearEmulatorCapabilities = p->l;
|
||||
|
||||
+ p = virConfGetValue (conf, "allow_disk_format_probing");
|
||||
+ CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG);
|
||||
+ if (p) driver->allowDiskFormatProbing = p->l;
|
||||
+
|
||||
virConfFree (conf);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
|
||||
index ab5f158..30e9f20 100644
|
||||
--- a/src/qemu/qemu_conf.h
|
||||
+++ b/src/qemu/qemu_conf.h
|
||||
@@ -141,6 +141,7 @@ struct qemud_driver {
|
||||
unsigned int relaxedACS : 1;
|
||||
unsigned int vncAllowHostAudio : 1;
|
||||
unsigned int clearEmulatorCapabilities : 1;
|
||||
+ unsigned int allowDiskFormatProbing : 1;
|
||||
|
||||
virCapsPtr caps;
|
||||
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 616547c..3c479c5 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -1322,7 +1322,8 @@ qemudSecurityInit(struct qemud_driver *qemud_drv)
|
||||
qemuSecurityDACSetDriver(qemud_drv);
|
||||
|
||||
ret = virSecurityDriverStartup(&security_drv,
|
||||
- qemud_drv->securityDriverName);
|
||||
+ qemud_drv->securityDriverName,
|
||||
+ qemud_drv->allowDiskFormatProbing);
|
||||
if (ret == -1) {
|
||||
VIR_ERROR0(_("Failed to start security driver"));
|
||||
return -1;
|
||||
@@ -3070,11 +3071,12 @@ static int qemuSetupDiskPathAllow(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
-static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
|
||||
+static int qemuSetupDiskCgroup(struct qemud_driver *driver,
|
||||
+ virCgroupPtr cgroup,
|
||||
virDomainDiskDefPtr disk)
|
||||
{
|
||||
return virDomainDiskDefForeachPath(disk,
|
||||
- true,
|
||||
+ driver->allowDiskFormatProbing,
|
||||
true,
|
||||
qemuSetupDiskPathAllow,
|
||||
cgroup);
|
||||
@@ -3109,11 +3111,12 @@ static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
-static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
|
||||
+static int qemuTeardownDiskCgroup(struct qemud_driver *driver,
|
||||
+ virCgroupPtr cgroup,
|
||||
virDomainDiskDefPtr disk)
|
||||
{
|
||||
return virDomainDiskDefForeachPath(disk,
|
||||
- true,
|
||||
+ driver->allowDiskFormatProbing,
|
||||
true,
|
||||
qemuTeardownDiskPathDeny,
|
||||
cgroup);
|
||||
@@ -3180,7 +3183,7 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
|
||||
}
|
||||
|
||||
for (i = 0; i < vm->def->ndisks ; i++) {
|
||||
- if (qemuSetupDiskCgroup(cgroup, vm->def->disks[i]) < 0)
|
||||
+ if (qemuSetupDiskCgroup(driver, cgroup, vm->def->disks[i]) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -8033,7 +8036,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
- if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuSetupDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
@@ -8078,7 +8081,7 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
|
||||
/* Fallthrough */
|
||||
}
|
||||
if (ret != 0 && cgroup) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8278,7 +8281,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
|
||||
vm->def->name);
|
||||
goto endjob;
|
||||
}
|
||||
- if (qemuSetupDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuSetupDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
@@ -8301,7 +8304,7 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
|
||||
}
|
||||
|
||||
if (ret != 0 && cgroup) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8429,7 +8432,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
|
||||
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
|
||||
|
||||
if (cgroup != NULL) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -8493,7 +8496,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
|
||||
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
|
||||
|
||||
if (cgroup != NULL) {
|
||||
- if (qemuTeardownDiskCgroup(cgroup, dev->data.disk) < 0)
|
||||
+ if (qemuTeardownDiskCgroup(driver, cgroup, dev->data.disk) < 0)
|
||||
VIR_WARN("Failed to teardown cgroup for disk path %s",
|
||||
NULLSTR(dev->data.disk->src));
|
||||
}
|
||||
@@ -9672,8 +9675,15 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
- if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
||||
+ if (driver->allowDiskFormatProbing) {
|
||||
+ if ((format = virStorageFileProbeFormat(disk->src)) < 0)
|
||||
+ goto cleanup;
|
||||
+ } else {
|
||||
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
+ _("no disk format for %s and probing is disabled"),
|
||||
+ disk->src);
|
||||
goto cleanup;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (virStorageFileGetMetadataFromFD(path, fd,
|
||||
diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
|
||||
index 0bbcf69..55dc0c6 100644
|
||||
--- a/src/qemu/qemu_security_dac.c
|
||||
+++ b/src/qemu/qemu_security_dac.c
|
||||
@@ -117,7 +117,7 @@ qemuSecurityDACSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
||||
return 0;
|
||||
|
||||
return virDomainDiskDefForeachPath(disk,
|
||||
- true,
|
||||
+ driver->allowDiskFormatProbing,
|
||||
false,
|
||||
qemuSecurityDACSetSecurityFileLabel,
|
||||
NULL);
|
||||
diff --git a/src/qemu/test_libvirtd_qemu.aug b/src/qemu/test_libvirtd_qemu.aug
|
||||
index 3326cc5..f0c4a0d 100644
|
||||
--- a/src/qemu/test_libvirtd_qemu.aug
|
||||
+++ b/src/qemu/test_libvirtd_qemu.aug
|
||||
@@ -101,6 +101,8 @@ relaxed_acs_check = 1
|
||||
vnc_allow_host_audio = 1
|
||||
|
||||
clear_emulator_capabilities = 0
|
||||
+
|
||||
+allow_disk_format_probing = 1
|
||||
"
|
||||
|
||||
test Libvirtd_qemu.lns get conf =
|
||||
@@ -212,3 +214,5 @@ clear_emulator_capabilities = 0
|
||||
{ "vnc_allow_host_audio" = "1" }
|
||||
{ "#empty" }
|
||||
{ "clear_emulator_capabilities" = "0" }
|
||||
+{ "#empty" }
|
||||
+{ "allow_disk_format_probing" = "1" }
|
||||
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
|
||||
index cb5c739..c5f9829 100644
|
||||
--- a/src/security/security_apparmor.c
|
||||
+++ b/src/security/security_apparmor.c
|
||||
@@ -157,6 +157,8 @@ load_profile(virSecurityDriverPtr drv,
|
||||
char *xml = NULL;
|
||||
int pipefd[2];
|
||||
pid_t child;
|
||||
+ const char *probe = virSecurityDriverGetAllowDiskFormatProbing(drv)
|
||||
+ ? "1" : "0";
|
||||
|
||||
if (pipe(pipefd) < -1) {
|
||||
virReportSystemError(errno, "%s", _("unable to create pipe"));
|
||||
@@ -172,19 +174,19 @@ load_profile(virSecurityDriverPtr drv,
|
||||
|
||||
if (create) {
|
||||
const char *const argv[] = {
|
||||
- VIRT_AA_HELPER, "-c", "-u", profile, NULL
|
||||
+ VIRT_AA_HELPER, "-p", probe, "-c", "-u", profile, NULL
|
||||
};
|
||||
ret = virExec(argv, NULL, NULL, &child,
|
||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
||||
} else if (fn) {
|
||||
const char *const argv[] = {
|
||||
- VIRT_AA_HELPER, "-r", "-u", profile, "-f", fn, NULL
|
||||
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, "-f", fn, NULL
|
||||
};
|
||||
ret = virExec(argv, NULL, NULL, &child,
|
||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
||||
} else {
|
||||
const char *const argv[] = {
|
||||
- VIRT_AA_HELPER, "-r", "-u", profile, NULL
|
||||
+ VIRT_AA_HELPER, "-p", probe, "-r", "-u", profile, NULL
|
||||
};
|
||||
ret = virExec(argv, NULL, NULL, &child,
|
||||
pipefd[0], NULL, NULL, VIR_EXEC_NONE);
|
||||
@@ -347,9 +349,11 @@ AppArmorSecurityDriverProbe(void)
|
||||
* currently not used.
|
||||
*/
|
||||
static int
|
||||
-AppArmorSecurityDriverOpen(virSecurityDriverPtr drv)
|
||||
+AppArmorSecurityDriverOpen(virSecurityDriverPtr drv,
|
||||
+ bool allowDiskFormatProbing)
|
||||
{
|
||||
virSecurityDriverSetDOI(drv, SECURITY_APPARMOR_VOID_DOI);
|
||||
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/security/security_driver.c b/src/security/security_driver.c
|
||||
index aac9f78..9e32fa4 100644
|
||||
--- a/src/security/security_driver.c
|
||||
+++ b/src/security/security_driver.c
|
||||
@@ -56,7 +56,8 @@ virSecurityDriverVerify(virDomainDefPtr def)
|
||||
|
||||
int
|
||||
virSecurityDriverStartup(virSecurityDriverPtr *drv,
|
||||
- const char *name)
|
||||
+ const char *name,
|
||||
+ bool allowDiskFormatProbing)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -72,7 +73,7 @@ virSecurityDriverStartup(virSecurityDriverPtr *drv,
|
||||
switch (tmp->probe()) {
|
||||
case SECURITY_DRIVER_ENABLE:
|
||||
virSecurityDriverInit(tmp);
|
||||
- if (tmp->open(tmp) == -1) {
|
||||
+ if (tmp->open(tmp, allowDiskFormatProbing) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
*drv = tmp;
|
||||
@@ -125,3 +126,14 @@ virSecurityDriverGetModel(virSecurityDriverPtr drv)
|
||||
{
|
||||
return drv->name;
|
||||
}
|
||||
+
|
||||
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
|
||||
+ bool allowDiskFormatProbing)
|
||||
+{
|
||||
+ drv->_private.allowDiskFormatProbing = allowDiskFormatProbing;
|
||||
+}
|
||||
+
|
||||
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv)
|
||||
+{
|
||||
+ return drv->_private.allowDiskFormatProbing;
|
||||
+}
|
||||
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
|
||||
index 61c9eb0..d768f32 100644
|
||||
--- a/src/security/security_driver.h
|
||||
+++ b/src/security/security_driver.h
|
||||
@@ -33,7 +33,8 @@ typedef struct _virSecurityDriverState virSecurityDriverState;
|
||||
typedef virSecurityDriverState *virSecurityDriverStatePtr;
|
||||
|
||||
typedef virSecurityDriverStatus (*virSecurityDriverProbe) (void);
|
||||
-typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv);
|
||||
+typedef int (*virSecurityDriverOpen) (virSecurityDriverPtr drv,
|
||||
+ bool allowDiskFormatProbing);
|
||||
typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityDriverPtr drv,
|
||||
virDomainObjPtr vm,
|
||||
virDomainDiskDefPtr disk);
|
||||
@@ -102,12 +103,14 @@ struct _virSecurityDriver {
|
||||
*/
|
||||
struct {
|
||||
char doi[VIR_SECURITY_DOI_BUFLEN];
|
||||
+ bool allowDiskFormatProbing;
|
||||
} _private;
|
||||
};
|
||||
|
||||
/* Global methods */
|
||||
int virSecurityDriverStartup(virSecurityDriverPtr *drv,
|
||||
- const char *name);
|
||||
+ const char *name,
|
||||
+ bool allowDiskFormatProbing);
|
||||
|
||||
int
|
||||
virSecurityDriverVerify(virDomainDefPtr def);
|
||||
@@ -120,7 +123,10 @@ virSecurityDriverVerify(virDomainDefPtr def);
|
||||
void virSecurityDriverInit(virSecurityDriverPtr drv);
|
||||
int virSecurityDriverSetDOI(virSecurityDriverPtr drv,
|
||||
const char *doi);
|
||||
+void virSecurityDriverSetAllowDiskFormatProbing(virSecurityDriverPtr drv,
|
||||
+ bool allowDiskFormatProbing);
|
||||
const char *virSecurityDriverGetDOI(virSecurityDriverPtr drv);
|
||||
const char *virSecurityDriverGetModel(virSecurityDriverPtr drv);
|
||||
+bool virSecurityDriverGetAllowDiskFormatProbing(virSecurityDriverPtr drv);
|
||||
|
||||
#endif /* __VIR_SECURITY_H__ */
|
||||
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
|
||||
index cc3812b..a9dd836 100644
|
||||
--- a/src/security/security_selinux.c
|
||||
+++ b/src/security/security_selinux.c
|
||||
@@ -266,13 +266,15 @@ SELinuxSecurityDriverProbe(void)
|
||||
}
|
||||
|
||||
static int
|
||||
-SELinuxSecurityDriverOpen(virSecurityDriverPtr drv)
|
||||
+SELinuxSecurityDriverOpen(virSecurityDriverPtr drv,
|
||||
+ bool allowDiskFormatProbing)
|
||||
{
|
||||
/*
|
||||
* Where will the DOI come from? SELinux configuration, or qemu
|
||||
* configuration? For the moment, we'll just set it to "0".
|
||||
*/
|
||||
virSecurityDriverSetDOI(drv, SECURITY_SELINUX_VOID_DOI);
|
||||
+ virSecurityDriverSetAllowDiskFormatProbing(drv, allowDiskFormatProbing);
|
||||
return SELinuxInitialize();
|
||||
}
|
||||
|
||||
@@ -467,18 +469,19 @@ SELinuxSetSecurityFileLabel(virDomainDiskDefPtr disk,
|
||||
}
|
||||
|
||||
static int
|
||||
-SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
|
||||
+SELinuxSetSecurityImageLabel(virSecurityDriverPtr drv,
|
||||
virDomainObjPtr vm,
|
||||
virDomainDiskDefPtr disk)
|
||||
|
||||
{
|
||||
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
|
||||
+ bool allowDiskFormatProbing = virSecurityDriverGetAllowDiskFormatProbing(drv);
|
||||
|
||||
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
|
||||
return 0;
|
||||
|
||||
return virDomainDiskDefForeachPath(disk,
|
||||
- true,
|
||||
+ allowDiskFormatProbing,
|
||||
false,
|
||||
SELinuxSetSecurityFileLabel,
|
||||
secdef);
|
||||
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
|
||||
index 9ed0cd3..521545d 100644
|
||||
--- a/src/security/virt-aa-helper.c
|
||||
+++ b/src/security/virt-aa-helper.c
|
||||
@@ -40,6 +40,7 @@
|
||||
static char *progname;
|
||||
|
||||
typedef struct {
|
||||
+ bool allowDiskFormatProbing;
|
||||
char uuid[PROFILE_NAME_SIZE]; /* UUID of vm */
|
||||
bool dryrun; /* dry run */
|
||||
char cmd; /* 'c' create
|
||||
@@ -844,7 +845,7 @@ get_files(vahControl * ctl)
|
||||
|
||||
for (i = 0; i < ctl->def->ndisks; i++) {
|
||||
int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
|
||||
- true,
|
||||
+ ctl->allowDiskFormatProbing,
|
||||
false,
|
||||
add_file_path,
|
||||
&buf);
|
||||
@@ -943,6 +944,7 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
||||
{
|
||||
int arg, idx = 0;
|
||||
struct option opt[] = {
|
||||
+ {"probing", 1, 0, 'p' },
|
||||
{"add", 0, 0, 'a'},
|
||||
{"create", 0, 0, 'c'},
|
||||
{"dryrun", 0, 0, 'd'},
|
||||
@@ -991,6 +993,12 @@ vahParseArgv(vahControl * ctl, int argc, char **argv)
|
||||
PROFILE_NAME_SIZE) == NULL)
|
||||
vah_error(ctl, 1, "error copying UUID");
|
||||
break;
|
||||
+ case 'p':
|
||||
+ if (STREQ(optarg, "1"))
|
||||
+ ctl->allowDiskFormatProbing = true;
|
||||
+ else
|
||||
+ ctl->allowDiskFormatProbing = false;
|
||||
+ break;
|
||||
default:
|
||||
vah_error(ctl, 1, "unsupported option");
|
||||
break;
|
||||
diff --git a/tests/seclabeltest.c b/tests/seclabeltest.c
|
||||
index 26d1f86..ef3f026 100644
|
||||
--- a/tests/seclabeltest.c
|
||||
+++ b/tests/seclabeltest.c
|
||||
@@ -15,7 +15,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
|
||||
const char *doi, *model;
|
||||
virSecurityDriverPtr security_drv;
|
||||
|
||||
- ret = virSecurityDriverStartup (&security_drv, "selinux");
|
||||
+ ret = virSecurityDriverStartup (&security_drv, "selinux", false);
|
||||
if (ret == -1)
|
||||
{
|
||||
fprintf (stderr, "Failed to start security driver");
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
From 3534cd47a57ee9cf7041472511444784f14d6939 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Mon, 14 Jun 2010 16:08:55 +0100
|
||||
Subject: [PATCH 09/11] Add ability to set a default driver name/type when parsing disks
|
||||
|
||||
Record a default driver name/type in capabilities struct. Use this
|
||||
when parsing disks if value is not set in XML config.
|
||||
|
||||
* src/conf/capabilities.h: Record default driver name/type for disks
|
||||
* src/conf/domain_conf.c: Fallback to default driver name/type
|
||||
when parsing disks
|
||||
* src/qemu/qemu_driver.c: Set default driver name/type to raw
|
||||
---
|
||||
src/conf/capabilities.h | 2 ++
|
||||
src/conf/domain_conf.c | 16 +++++++++++++++-
|
||||
src/qemu/qemu_driver.c | 8 ++++++++
|
||||
3 files changed, 25 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
|
||||
index 9290c82..f676eb8 100644
|
||||
--- a/src/conf/capabilities.h
|
||||
+++ b/src/conf/capabilities.h
|
||||
@@ -123,6 +123,8 @@ struct _virCaps {
|
||||
virCapsGuestPtr *guests;
|
||||
unsigned char macPrefix[VIR_MAC_PREFIX_BUFLEN];
|
||||
unsigned int emulatorRequired : 1;
|
||||
+ const char *defaultDiskDriverName;
|
||||
+ const char *defaultDiskDriverType;
|
||||
void *(*privateDataAllocFunc)(void);
|
||||
void (*privateDataFreeFunc)(void *);
|
||||
int (*privateDataXMLFormat)(virBufferPtr, void *);
|
||||
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
||||
index b20ca97..f3b8cfa 100644
|
||||
--- a/src/conf/domain_conf.c
|
||||
+++ b/src/conf/domain_conf.c
|
||||
@@ -1639,6 +1639,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
||||
def->serial = serial;
|
||||
serial = NULL;
|
||||
|
||||
+ if (!def->driverType &&
|
||||
+ caps->defaultDiskDriverType &&
|
||||
+ !(def->driverType = strdup(caps->defaultDiskDriverType)))
|
||||
+ goto no_memory;
|
||||
+
|
||||
+ if (!def->driverName &&
|
||||
+ caps->defaultDiskDriverName &&
|
||||
+ !(def->driverName = strdup(caps->defaultDiskDriverName)))
|
||||
+ goto no_memory;
|
||||
+
|
||||
if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
|
||||
&& virDomainDiskDefAssignAddress(caps, def) < 0)
|
||||
goto error;
|
||||
@@ -1659,6 +1669,9 @@ cleanup:
|
||||
|
||||
return def;
|
||||
|
||||
+no_memory:
|
||||
+ virReportOOMError();
|
||||
+
|
||||
error:
|
||||
virDomainDiskDefFree(def);
|
||||
def = NULL;
|
||||
@@ -4275,7 +4288,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
||||
if (n && VIR_ALLOC_N(def->disks, n) < 0)
|
||||
goto no_memory;
|
||||
for (i = 0 ; i < n ; i++) {
|
||||
- virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps, nodes[i],
|
||||
+ virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
|
||||
+ nodes[i],
|
||||
flags);
|
||||
if (!disk)
|
||||
goto error;
|
||||
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
||||
index 3c479c5..14b790e 100644
|
||||
--- a/src/qemu/qemu_driver.c
|
||||
+++ b/src/qemu/qemu_driver.c
|
||||
@@ -1357,6 +1357,14 @@ qemuCreateCapabilities(virCapsPtr oldcaps,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if (driver->allowDiskFormatProbing) {
|
||||
+ caps->defaultDiskDriverName = NULL;
|
||||
+ caps->defaultDiskDriverType = NULL;
|
||||
+ } else {
|
||||
+ caps->defaultDiskDriverName = "qemu";
|
||||
+ caps->defaultDiskDriverType = "raw";
|
||||
+ }
|
||||
+
|
||||
/* Domain XML parser hooks */
|
||||
caps->privateDataAllocFunc = qemuDomainObjPrivateAlloc;
|
||||
caps->privateDataFreeFunc = qemuDomainObjPrivateFree;
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,291 +0,0 @@
|
||||
From 2ba8625d6d148fa489586efabdfaf2ef20903762 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Wed, 16 Jun 2010 14:14:05 +0100
|
||||
Subject: [PATCH 10/11] Rewrite qemu-img backing store format handling
|
||||
|
||||
When creating qcow2 files with a backing store, it is important
|
||||
to set an explicit format to prevent QEMU probing. The storage
|
||||
backend was only doing this if it found a 'kvm-img' binary. This
|
||||
is wrong because plenty of kvm-img binaries don't support an
|
||||
explicit format, and plenty of 'qemu-img' binaries do support
|
||||
a format. The result was that most qcow2 files were not getting
|
||||
a backing store format.
|
||||
|
||||
This patch runs 'qemu-img -h' to check for the two support
|
||||
argument formats
|
||||
|
||||
'-o backing_format=raw'
|
||||
'-F raw'
|
||||
|
||||
and use whichever option it finds
|
||||
|
||||
* src/storage/storage_backend.c: Query binary to determine
|
||||
how to set the backing store format
|
||||
---
|
||||
src/storage/storage_backend.c | 214 +++++++++++++++++++++++++++++------------
|
||||
1 files changed, 152 insertions(+), 62 deletions(-)
|
||||
|
||||
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
|
||||
index aba8937..c185693 100644
|
||||
--- a/src/storage/storage_backend.c
|
||||
+++ b/src/storage/storage_backend.c
|
||||
@@ -561,6 +561,69 @@ static int virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+enum {
|
||||
+ QEMU_IMG_BACKING_FORMAT_NONE = 0,
|
||||
+ QEMU_IMG_BACKING_FORMAT_FLAG,
|
||||
+ QEMU_IMG_BACKING_FORMAT_OPTIONS,
|
||||
+};
|
||||
+
|
||||
+static int virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
|
||||
+{
|
||||
+ const char *const qemuarg[] = { qemuimg, "-h", NULL };
|
||||
+ const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
||||
+ pid_t child = 0;
|
||||
+ int status;
|
||||
+ int newstdout = -1;
|
||||
+ char *help = NULL;
|
||||
+ enum { MAX_HELP_OUTPUT_SIZE = 1024*8 };
|
||||
+ int len;
|
||||
+ char *start;
|
||||
+ char *end;
|
||||
+ char *tmp;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (virExec(qemuarg, qemuenv, NULL,
|
||||
+ &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ if ((len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help)) < 0) {
|
||||
+ virReportSystemError(errno,
|
||||
+ _("Unable to read '%s -h' output"),
|
||||
+ qemuimg);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ start = strstr(help, " create ");
|
||||
+ end = strstr(start, "\n");
|
||||
+ if ((tmp = strstr(start, "-F fmt")) && tmp < end)
|
||||
+ ret = QEMU_IMG_BACKING_FORMAT_FLAG;
|
||||
+ else if ((tmp = strstr(start, "[-o options]")) && tmp < end)
|
||||
+ ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
|
||||
+ else
|
||||
+ ret = QEMU_IMG_BACKING_FORMAT_NONE;
|
||||
+
|
||||
+cleanup:
|
||||
+ VIR_FREE(help);
|
||||
+ close(newstdout);
|
||||
+rewait:
|
||||
+ if (child) {
|
||||
+ if (waitpid(child, &status, 0) != child) {
|
||||
+ if (errno == EINTR)
|
||||
+ goto rewait;
|
||||
+
|
||||
+ VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
||||
+ WEXITSTATUS(status), (unsigned long)child);
|
||||
+ }
|
||||
+ if (WEXITSTATUS(status) != 0) {
|
||||
+ VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
||||
+ WEXITSTATUS(status));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int
|
||||
virStorageBackendCreateQemuImg(virConnectPtr conn,
|
||||
virStoragePoolObjPtr pool,
|
||||
@@ -568,10 +631,9 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
||||
virStorageVolDefPtr inputvol,
|
||||
unsigned int flags ATTRIBUTE_UNUSED)
|
||||
{
|
||||
- int ret;
|
||||
+ int ret = -1;
|
||||
char size[100];
|
||||
char *create_tool;
|
||||
- short use_kvmimg;
|
||||
|
||||
const char *type = virStorageFileFormatTypeToString(vol->target.format);
|
||||
const char *backingType = vol->backingStore.path ?
|
||||
@@ -582,41 +644,10 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
||||
const char *inputPath = inputvol ? inputvol->target.path : NULL;
|
||||
/* Treat input block devices as 'raw' format */
|
||||
const char *inputType = inputPath ?
|
||||
- virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_FILE_RAW : inputvol->target.format) :
|
||||
- NULL;
|
||||
-
|
||||
- const char **imgargv;
|
||||
- /* The extra NULL field is for indicating encryption (-e). */
|
||||
- const char *imgargvnormal[] = {
|
||||
- NULL, "create",
|
||||
- "-f", type,
|
||||
- vol->target.path,
|
||||
- size,
|
||||
- NULL,
|
||||
- NULL
|
||||
- };
|
||||
- /* Extra NULL fields are for including "backingType" when using
|
||||
- * kvm-img (-F backingType), and for indicating encryption (-e).
|
||||
- */
|
||||
- const char *imgargvbacking[] = {
|
||||
- NULL, "create",
|
||||
- "-f", type,
|
||||
- "-b", vol->backingStore.path,
|
||||
- vol->target.path,
|
||||
- size,
|
||||
- NULL,
|
||||
- NULL,
|
||||
- NULL,
|
||||
- NULL
|
||||
- };
|
||||
- const char *convargv[] = {
|
||||
- NULL, "convert",
|
||||
- "-f", inputType,
|
||||
- "-O", type,
|
||||
- inputPath,
|
||||
- vol->target.path,
|
||||
- NULL,
|
||||
- };
|
||||
+ virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
|
||||
+ VIR_STORAGE_FILE_RAW :
|
||||
+ inputvol->target.format) :
|
||||
+ NULL;
|
||||
|
||||
if (type == NULL) {
|
||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
@@ -690,44 +721,103 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
||||
}
|
||||
}
|
||||
|
||||
- if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
|
||||
- use_kvmimg = 1;
|
||||
- else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
|
||||
- use_kvmimg = 0;
|
||||
- else {
|
||||
+ /* Size in KB */
|
||||
+ snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
|
||||
+
|
||||
+ /* KVM is usually ahead of qemu on features, so try that first */
|
||||
+ create_tool = virFindFileInPath("kvm-img");
|
||||
+ if (!create_tool)
|
||||
+ create_tool = virFindFileInPath("qemu-img");
|
||||
+
|
||||
+ if (!create_tool) {
|
||||
virStorageReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("unable to find kvm-img or qemu-img"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inputvol) {
|
||||
- convargv[0] = create_tool;
|
||||
- imgargv = convargv;
|
||||
+ const char *imgargv[] = {
|
||||
+ create_tool,
|
||||
+ "convert",
|
||||
+ "-f", inputType,
|
||||
+ "-O", type,
|
||||
+ inputPath,
|
||||
+ vol->target.path,
|
||||
+ NULL,
|
||||
+ };
|
||||
+
|
||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
||||
} else if (vol->backingStore.path) {
|
||||
- imgargvbacking[0] = create_tool;
|
||||
- if (use_kvmimg) {
|
||||
- imgargvbacking[6] = "-F";
|
||||
- imgargvbacking[7] = backingType;
|
||||
- imgargvbacking[8] = vol->target.path;
|
||||
- imgargvbacking[9] = size;
|
||||
+ const char *imgargv[] = {
|
||||
+ create_tool,
|
||||
+ "create",
|
||||
+ "-f", type,
|
||||
+ "-b", vol->backingStore.path,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ NULL
|
||||
+ };
|
||||
+ int imgformat = virStorageBackendQEMUImgBackingFormat(create_tool);
|
||||
+ char *optflag = NULL;
|
||||
+ if (imgformat < 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ switch (imgformat) {
|
||||
+ case QEMU_IMG_BACKING_FORMAT_FLAG:
|
||||
+ imgargv[6] = "-F";
|
||||
+ imgargv[7] = backingType;
|
||||
+ imgargv[8] = vol->target.path;
|
||||
+ imgargv[9] = size;
|
||||
+ if (vol->target.encryption != NULL)
|
||||
+ imgargv[10] = "-e";
|
||||
+ break;
|
||||
+
|
||||
+ case QEMU_IMG_BACKING_FORMAT_OPTIONS:
|
||||
+ if (virAsprintf(&optflag, "backing_fmt=%s", backingType) < 0) {
|
||||
+ virReportOOMError();
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ imgargv[6] = "-o";
|
||||
+ imgargv[7] = optflag;
|
||||
+ imgargv[8] = vol->target.path;
|
||||
+ imgargv[9] = size;
|
||||
if (vol->target.encryption != NULL)
|
||||
- imgargvbacking[10] = "-e";
|
||||
- } else if (vol->target.encryption != NULL)
|
||||
- imgargvbacking[8] = "-e";
|
||||
- imgargv = imgargvbacking;
|
||||
+ imgargv[10] = "-e";
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ VIR_INFO("Unable to set backing store format for %s with %s",
|
||||
+ vol->target.path, create_tool);
|
||||
+ imgargv[6] = vol->target.path;
|
||||
+ imgargv[7] = size;
|
||||
+ if (vol->target.encryption != NULL)
|
||||
+ imgargv[8] = "-e";
|
||||
+ }
|
||||
+
|
||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
||||
+ VIR_FREE(optflag);
|
||||
} else {
|
||||
- imgargvnormal[0] = create_tool;
|
||||
- imgargv = imgargvnormal;
|
||||
+ /* The extra NULL field is for indicating encryption (-e). */
|
||||
+ const char *imgargv[] = {
|
||||
+ create_tool,
|
||||
+ "create",
|
||||
+ "-f", type,
|
||||
+ vol->target.path,
|
||||
+ size,
|
||||
+ NULL,
|
||||
+ NULL
|
||||
+ };
|
||||
if (vol->target.encryption != NULL)
|
||||
imgargv[6] = "-e";
|
||||
- }
|
||||
|
||||
+ ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
||||
+ }
|
||||
|
||||
- /* Size in KB */
|
||||
- snprintf(size, sizeof(size), "%lluK", vol->capacity/1024);
|
||||
-
|
||||
- ret = virStorageBackendCreateExecCommand(pool, vol, imgargv);
|
||||
- VIR_FREE(imgargv[0]);
|
||||
+ cleanup:
|
||||
+ VIR_FREE(create_tool);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
From d33f44c2e74de28c89b64cdc2c0a6564662e075c Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Fri, 9 Jul 2010 11:28:40 +0100
|
||||
Subject: [PATCH 11/11] Use the extract backing store format in storage volume lookup
|
||||
|
||||
The storage volume lookup code was probing for the backing store
|
||||
format, instead of using the format extracted from the file
|
||||
itself. This meant it could report in accurate information. If
|
||||
a format is included in the file, then use that in preference,
|
||||
with probing as a fallback.
|
||||
|
||||
* src/storage/storage_backend_fs.c: Use extracted backing store
|
||||
format
|
||||
---
|
||||
src/storage/storage_backend_fs.c | 80 +++++++++++++++++---------------------
|
||||
1 files changed, 36 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
|
||||
index d3ac0fe..ffb0071 100644
|
||||
--- a/src/storage/storage_backend_fs.c
|
||||
+++ b/src/storage/storage_backend_fs.c
|
||||
@@ -51,6 +51,7 @@
|
||||
static int
|
||||
virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
||||
char **backingStore,
|
||||
+ int *backingStoreFormat,
|
||||
unsigned long long *allocation,
|
||||
unsigned long long *capacity,
|
||||
virStorageEncryptionPtr *encryption)
|
||||
@@ -58,6 +59,10 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
||||
int fd, ret;
|
||||
virStorageFileMetadata meta;
|
||||
|
||||
+ if (backingStore)
|
||||
+ *backingStore = NULL;
|
||||
+ if (backingStoreFormat)
|
||||
+ *backingStoreFormat = VIR_STORAGE_FILE_AUTO;
|
||||
if (encryption)
|
||||
*encryption = NULL;
|
||||
|
||||
@@ -89,22 +94,30 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
||||
|
||||
close(fd);
|
||||
|
||||
- if (backingStore) {
|
||||
- *backingStore = meta.backingStore;
|
||||
- meta.backingStore = NULL;
|
||||
+ if (meta.backingStore) {
|
||||
+ if (backingStore) {
|
||||
+ *backingStore = meta.backingStore;
|
||||
+ meta.backingStore = NULL;
|
||||
+ if (meta.backingStoreFormat == VIR_STORAGE_FILE_AUTO) {
|
||||
+ if ((*backingStoreFormat = virStorageFileProbeFormat(*backingStore)) < 0) {
|
||||
+ close(fd);
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+ } else {
|
||||
+ *backingStoreFormat = meta.backingStoreFormat;
|
||||
+ }
|
||||
+ } else {
|
||||
+ VIR_FREE(meta.backingStore);
|
||||
+ }
|
||||
}
|
||||
|
||||
- VIR_FREE(meta.backingStore);
|
||||
-
|
||||
if (capacity && meta.capacity)
|
||||
*capacity = meta.capacity;
|
||||
|
||||
if (encryption != NULL && meta.encrypted) {
|
||||
if (VIR_ALLOC(*encryption) < 0) {
|
||||
virReportOOMError();
|
||||
- if (backingStore)
|
||||
- VIR_FREE(*backingStore);
|
||||
- return -1;
|
||||
+ goto cleanup;
|
||||
}
|
||||
|
||||
switch (target->format) {
|
||||
@@ -124,6 +137,11 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target,
|
||||
}
|
||||
|
||||
return 0;
|
||||
+
|
||||
+cleanup:
|
||||
+ if (backingStore)
|
||||
+ VIR_FREE(*backingStore);
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
#if WITH_STORAGE_FS
|
||||
@@ -585,6 +603,7 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
int ret;
|
||||
char *backingStore;
|
||||
+ int backingStoreFormat;
|
||||
|
||||
if (VIR_ALLOC(vol) < 0)
|
||||
goto no_memory;
|
||||
@@ -604,6 +623,7 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
|
||||
if ((ret = virStorageBackendProbeTarget(&vol->target,
|
||||
&backingStore,
|
||||
+ &backingStoreFormat,
|
||||
&vol->allocation,
|
||||
&vol->capacity,
|
||||
&vol->target.encryption)) < 0) {
|
||||
@@ -619,46 +639,18 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
if (backingStore != NULL) {
|
||||
- if (vol->target.format == VIR_STORAGE_FILE_QCOW2 &&
|
||||
- STRPREFIX("fmt:", backingStore)) {
|
||||
- char *fmtstr = backingStore + 4;
|
||||
- char *path = strchr(fmtstr, ':');
|
||||
- if (!path) {
|
||||
- VIR_FREE(backingStore);
|
||||
- } else {
|
||||
- *path = '\0';
|
||||
- if ((vol->backingStore.format =
|
||||
- virStorageFileFormatTypeFromString(fmtstr)) < 0) {
|
||||
- VIR_FREE(backingStore);
|
||||
- } else {
|
||||
- memmove(backingStore, path, strlen(path) + 1);
|
||||
- vol->backingStore.path = backingStore;
|
||||
-
|
||||
- if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
|
||||
- NULL,
|
||||
- NULL) < 0)
|
||||
- VIR_FREE(vol->backingStore);
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
- vol->backingStore.path = backingStore;
|
||||
-
|
||||
- if ((ret = virStorageBackendProbeTarget(&vol->backingStore,
|
||||
- NULL, NULL, NULL,
|
||||
- NULL)) < 0) {
|
||||
- if (ret == -1)
|
||||
- goto cleanup;
|
||||
- else {
|
||||
- /* Silently ignore non-regular files,
|
||||
- * eg '.' '..', 'lost+found' */
|
||||
- VIR_FREE(vol->backingStore);
|
||||
- }
|
||||
- }
|
||||
+ vol->backingStore.path = backingStore;
|
||||
+ vol->backingStore.format = backingStoreFormat;
|
||||
+
|
||||
+ if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
|
||||
+ NULL,
|
||||
+ NULL) < 0) {
|
||||
+ VIR_FREE(vol->backingStore.path);
|
||||
+ goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-
|
||||
if (VIR_REALLOC_N(pool->volumes.objs,
|
||||
pool->volumes.count+1) < 0)
|
||||
goto no_memory;
|
||||
--
|
||||
1.7.1.1
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
From 112a309bc7839e95c558b535143f855ce89cca8c Mon Sep 17 00:00:00 2001
|
||||
From: Daniel P. Berrange <berrange@redhat.com>
|
||||
Date: Thu, 10 Jun 2010 12:50:38 -0400
|
||||
Subject: [PATCH] CVE-2010-2242 Apply a source port mapping to virtual network masquerading
|
||||
|
||||
IPtables will seek to preserve the source port unchanged when
|
||||
doing masquerading, if possible. NFS has a pseudo-security
|
||||
option where it checks for the source port <= 1023 before
|
||||
allowing a mount request. If an admin has used this to make the
|
||||
host OS trusted for mounts, the default iptables behaviour will
|
||||
potentially allow NAT'd guests access too. This needs to be
|
||||
stopped.
|
||||
|
||||
With this change, the iptables -t nat -L -n -v rules for the
|
||||
default network will be
|
||||
|
||||
Chain POSTROUTING (policy ACCEPT 95 packets, 9163 bytes)
|
||||
pkts bytes target prot opt in out source destination
|
||||
14 840 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
|
||||
75 5752 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
|
||||
0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
|
||||
|
||||
* src/network/bridge_driver.c: Add masquerade rules for TCP
|
||||
and UDP protocols
|
||||
* src/util/iptables.c, src/util/iptables.c: Add source port
|
||||
mappings for TCP & UDP protocols when masquerading.
|
||||
---
|
||||
src/network/bridge_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++--
|
||||
src/util/iptables.c | 70 +++++++++++++++++++++++++++++------------
|
||||
src/util/iptables.h | 6 ++-
|
||||
3 files changed, 122 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
|
||||
index 72255c1..80ed57a 100644
|
||||
--- a/src/network/bridge_driver.c
|
||||
+++ b/src/network/bridge_driver.c
|
||||
@@ -638,18 +638,74 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
|
||||
goto masqerr2;
|
||||
}
|
||||
|
||||
- /* enable masquerading */
|
||||
+ /*
|
||||
+ * Enable masquerading.
|
||||
+ *
|
||||
+ * We need to end up with 3 rules in the table in this order
|
||||
+ *
|
||||
+ * 1. protocol=tcp with sport mapping restricton
|
||||
+ * 2. protocol=udp with sport mapping restricton
|
||||
+ * 3. generic any protocol
|
||||
+ *
|
||||
+ * The sport mappings are required, because default IPtables
|
||||
+ * MASQUERADE is maintain port number unchanged where possible.
|
||||
+ *
|
||||
+ * NFS can be configured to only "trust" port numbers < 1023.
|
||||
+ *
|
||||
+ * Guests using NAT thus need to be prevented from having port
|
||||
+ * numbers < 1023, otherwise they can bypass the NFS "security"
|
||||
+ * check on the source port number.
|
||||
+ *
|
||||
+ * Since we use '--insert' to add rules to the header of the
|
||||
+ * chain, we actually need to add them in the reverse of the
|
||||
+ * order just mentioned !
|
||||
+ */
|
||||
+
|
||||
+ /* First the generic masquerade rule for other protocols */
|
||||
if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
||||
network->def->network,
|
||||
- network->def->forwardDev))) {
|
||||
+ network->def->forwardDev,
|
||||
+ NULL))) {
|
||||
virReportSystemError(err,
|
||||
_("failed to add iptables rule to enable masquerading to '%s'"),
|
||||
network->def->forwardDev ? network->def->forwardDev : NULL);
|
||||
goto masqerr3;
|
||||
}
|
||||
|
||||
+ /* UDP with a source port restriction */
|
||||
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ "udp"))) {
|
||||
+ virReportSystemError(err,
|
||||
+ _("failed to add iptables rule to enable UDP masquerading to '%s'"),
|
||||
+ network->def->forwardDev ? network->def->forwardDev : NULL);
|
||||
+ goto masqerr4;
|
||||
+ }
|
||||
+
|
||||
+ /* TCP with a source port restriction */
|
||||
+ if ((err = iptablesAddForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ "tcp"))) {
|
||||
+ virReportSystemError(err,
|
||||
+ _("failed to add iptables rule to enable TCP masquerading to '%s'"),
|
||||
+ network->def->forwardDev ? network->def->forwardDev : NULL);
|
||||
+ goto masqerr5;
|
||||
+ }
|
||||
+
|
||||
return 1;
|
||||
|
||||
+ masqerr5:
|
||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ "udp");
|
||||
+ masqerr4:
|
||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ NULL);
|
||||
masqerr3:
|
||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
||||
network->def->network,
|
||||
@@ -814,8 +870,17 @@ networkRemoveIptablesRules(struct network_driver *driver,
|
||||
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
||||
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
|
||||
iptablesRemoveForwardMasquerade(driver->iptables,
|
||||
- network->def->network,
|
||||
- network->def->forwardDev);
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ "tcp");
|
||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ "udp");
|
||||
+ iptablesRemoveForwardMasquerade(driver->iptables,
|
||||
+ network->def->network,
|
||||
+ network->def->forwardDev,
|
||||
+ NULL);
|
||||
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
|
||||
network->def->network,
|
||||
network->def->bridge,
|
||||
diff --git a/src/util/iptables.c b/src/util/iptables.c
|
||||
index d06b857..f63e8c6 100644
|
||||
--- a/src/util/iptables.c
|
||||
+++ b/src/util/iptables.c
|
||||
@@ -692,25 +692,49 @@ iptablesRemoveForwardRejectIn(iptablesContext *ctx,
|
||||
*/
|
||||
static int
|
||||
iptablesForwardMasquerade(iptablesContext *ctx,
|
||||
- const char *network,
|
||||
- const char *physdev,
|
||||
- int action)
|
||||
+ const char *network,
|
||||
+ const char *physdev,
|
||||
+ const char *protocol,
|
||||
+ int action)
|
||||
{
|
||||
- if (physdev && physdev[0]) {
|
||||
- return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
- action,
|
||||
- "--source", network,
|
||||
- "!", "--destination", network,
|
||||
- "--out-interface", physdev,
|
||||
- "--jump", "MASQUERADE",
|
||||
- NULL);
|
||||
+ if (protocol && protocol[0]) {
|
||||
+ if (physdev && physdev[0]) {
|
||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
+ action,
|
||||
+ "--source", network,
|
||||
+ "-p", protocol,
|
||||
+ "!", "--destination", network,
|
||||
+ "--out-interface", physdev,
|
||||
+ "--jump", "MASQUERADE",
|
||||
+ "--to-ports", "1024-65535",
|
||||
+ NULL);
|
||||
+ } else {
|
||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
+ action,
|
||||
+ "--source", network,
|
||||
+ "-p", protocol,
|
||||
+ "!", "--destination", network,
|
||||
+ "--jump", "MASQUERADE",
|
||||
+ "--to-ports", "1024-65535",
|
||||
+ NULL);
|
||||
+ }
|
||||
} else {
|
||||
- return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
- action,
|
||||
- "--source", network,
|
||||
- "!", "--destination", network,
|
||||
- "--jump", "MASQUERADE",
|
||||
- NULL);
|
||||
+ if (physdev && physdev[0]) {
|
||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
+ action,
|
||||
+ "--source", network,
|
||||
+ "!", "--destination", network,
|
||||
+ "--out-interface", physdev,
|
||||
+ "--jump", "MASQUERADE",
|
||||
+ NULL);
|
||||
+ } else {
|
||||
+ return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||
+ action,
|
||||
+ "--source", network,
|
||||
+ "!", "--destination", network,
|
||||
+ "--jump", "MASQUERADE",
|
||||
+ NULL);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,6 +743,7 @@ iptablesForwardMasquerade(iptablesContext *ctx,
|
||||
* @ctx: pointer to the IP table context
|
||||
* @network: the source network name
|
||||
* @physdev: the physical input device or NULL
|
||||
+ * @protocol: the network protocol or NULL
|
||||
*
|
||||
* Add rules to the IP table context to allow masquerading
|
||||
* network @network on @physdev. This allow the bridge to
|
||||
@@ -729,9 +754,10 @@ iptablesForwardMasquerade(iptablesContext *ctx,
|
||||
int
|
||||
iptablesAddForwardMasquerade(iptablesContext *ctx,
|
||||
const char *network,
|
||||
- const char *physdev)
|
||||
+ const char *physdev,
|
||||
+ const char *protocol)
|
||||
{
|
||||
- return iptablesForwardMasquerade(ctx, network, physdev, ADD);
|
||||
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, ADD);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,6 +765,7 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
|
||||
* @ctx: pointer to the IP table context
|
||||
* @network: the source network name
|
||||
* @physdev: the physical input device or NULL
|
||||
+ * @protocol: the network protocol or NULL
|
||||
*
|
||||
* Remove rules from the IP table context to stop masquerading
|
||||
* network @network on @physdev. This stops the bridge from
|
||||
@@ -749,7 +776,8 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
|
||||
int
|
||||
iptablesRemoveForwardMasquerade(iptablesContext *ctx,
|
||||
const char *network,
|
||||
- const char *physdev)
|
||||
+ const char *physdev,
|
||||
+ const char *protocol)
|
||||
{
|
||||
- return iptablesForwardMasquerade(ctx, network, physdev, REMOVE);
|
||||
+ return iptablesForwardMasquerade(ctx, network, physdev, protocol, REMOVE);
|
||||
}
|
||||
diff --git a/src/util/iptables.h b/src/util/iptables.h
|
||||
index 7d55a6d..b47d854 100644
|
||||
--- a/src/util/iptables.h
|
||||
+++ b/src/util/iptables.h
|
||||
@@ -85,9 +85,11 @@ int iptablesRemoveForwardRejectIn (iptablesContext *ctx,
|
||||
|
||||
int iptablesAddForwardMasquerade (iptablesContext *ctx,
|
||||
const char *network,
|
||||
- const char *physdev);
|
||||
+ const char *physdev,
|
||||
+ const char *protocol);
|
||||
int iptablesRemoveForwardMasquerade (iptablesContext *ctx,
|
||||
const char *network,
|
||||
- const char *physdev);
|
||||
+ const char *physdev,
|
||||
+ const char *protocol);
|
||||
|
||||
#endif /* __QEMUD_IPTABLES_H__ */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
+1832
-1154
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user