0 | |
From 7855c34e1517163aa7a4c58f6c4fff762cef515b Mon Sep 17 00:00:00 2001
|
1 | |
From: Daniel P. Berrange <berrange@redhat.com>
|
2 | |
Date: Wed, 17 Dec 2008 16:55:58 +0000
|
3 | |
Subject: [PATCH] Fix missing read-only access checks (CVE-2008-5086)
|
4 | |
|
5 | |
The following methods in libvirt.c are missing a check against the
|
6 | |
read-only connection flag:
|
7 | |
|
8 | |
virDomainMigrate
|
9 | |
virDomainMigratePrepare
|
10 | |
virDomainMigratePerform
|
11 | |
virDomainMigrateFinish
|
12 | |
virDomainMigratePrepare2
|
13 | |
virDomainMigrateFinish2
|
14 | |
virDomainBlockPeek
|
15 | |
virDomainMemoryPeek
|
16 | |
virDomainSetAutostart
|
17 | |
virNetworkSetAutostart
|
18 | |
virConnectFindStoragePoolSources
|
19 | |
virStoragePoolSetAutostart
|
20 | |
|
21 | |
If using PolicyKit auth, the default policy will allow any local user
|
22 | |
to make a read-only connection to the libvirtd daemon without needing
|
23 | |
authentication.
|
24 | |
|
25 | |
If not using PolicyKit, the default libvirtd.conf configuration settings
|
26 | |
will allow an unprivileged user to make a read-only connection to the
|
27 | |
libvirtd daemon without needing authentication.
|
28 | |
|
29 | |
Thus out of the box unprivileged local users may be able to migrate VMs,
|
30 | |
set or unset the autostart flag for domains, networks & storage pools,
|
31 | |
and access privileged data in the VM memory, or disks.
|
32 | |
|
33 | |
All TCP remote connections are read-write, and default settings require
|
34 | |
full authentication, thus remote access is not impacted by this flaw.
|
35 | |
|
36 | |
Administrators can apply a workaround by editting /etc/libvirt/libvirtd.conf
|
37 | |
to explicitly set 'unix_sock_ro_perms' parameter to '0700'. Restart the
|
38 | |
libvirtd daemon after making this change.
|
39 | |
|
40 | |
The first vulnerable release was 0.3.2, where the virDomainMigrate API
|
41 | |
was added for the Xen driver. Other APIs were added in various subsequent
|
42 | |
releases depending on the hypervisor driver in question.
|
43 | |
|
44 | |
The attached patch has been committed to CVS, and OS distributors are
|
45 | |
recommended to apply this patch to all existing releases shipped. It
|
46 | |
was diff'd against current CVS head, and applies against 0.5.1, and
|
47 | |
is trivially re-diffable for all earlier releases.
|
48 | |
|
49 | |
This flaw has been assigned the identifier CVE-2008-5086
|
50 | |
|
51 | |
Daniel
|
52 | |
---
|
53 | |
src/libvirt.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
54 | |
1 files changed, 55 insertions(+), 0 deletions(-)
|
55 | |
|
56 | |
diff --git a/src/libvirt.c b/src/libvirt.c
|
57 | |
index ed98323..02f67b7 100644
|
58 | |
--- a/src/libvirt.c
|
59 | |
+++ b/src/libvirt.c
|
60 | |
@@ -2180,6 +2180,16 @@ virDomainMigrate (virDomainPtr domain,
|
61 | |
return NULL;
|
62 | |
}
|
63 | |
|
64 | |
+ if (domain->conn->flags & VIR_CONNECT_RO) {
|
65 | |
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
66 | |
+ return NULL;
|
67 | |
+ }
|
68 | |
+ if (dconn->flags & VIR_CONNECT_RO) {
|
69 | |
+ /* NB, delibrately report error against source object, not dest here */
|
70 | |
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
71 | |
+ return NULL;
|
72 | |
+ }
|
73 | |
+
|
74 | |
/* Check that migration is supported by both drivers. */
|
75 | |
if (!VIR_DRV_SUPPORTS_FEATURE (conn->driver, conn,
|
76 | |
VIR_DRV_FEATURE_MIGRATION_V1) ||
|
77 | |
@@ -2257,6 +2267,11 @@ __virDomainMigratePrepare (virConnectPtr dconn,
|
78 | |
return -1;
|
79 | |
}
|
80 | |
|
81 | |
+ if (dconn->flags & VIR_CONNECT_RO) {
|
82 | |
+ virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
83 | |
+ return -1;
|
84 | |
+ }
|
85 | |
+
|
86 | |
if (dconn->driver->domainMigratePrepare)
|
87 | |
return dconn->driver->domainMigratePrepare (dconn, cookie, cookielen,
|
88 | |
uri_in, uri_out,
|
89 | |
@@ -2287,6 +2302,11 @@ __virDomainMigratePerform (virDomainPtr domain,
|
90 | |
}
|
91 | |
conn = domain->conn;
|
92 | |
|
93 | |
+ if (domain->conn->flags & VIR_CONNECT_RO) {
|
94 | |
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
95 | |
+ return -1;
|
96 | |
+ }
|
97 | |
+
|
98 | |
if (conn->driver->domainMigratePerform)
|
99 | |
return conn->driver->domainMigratePerform (domain, cookie, cookielen,
|
100 | |
uri,
|
101 | |
@@ -2314,6 +2334,11 @@ __virDomainMigrateFinish (virConnectPtr dconn,
|
102 | |
return NULL;
|
103 | |
}
|
104 | |
|
105 | |
+ if (dconn->flags & VIR_CONNECT_RO) {
|
106 | |
+ virLibConnError(dconn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
107 | |
+ return NULL;
|
108 | |
+ }
|
109 | |
+
|
110 | |
if (dconn->driver->domainMigrateFinish)
|
111 | |
return dconn->driver->domainMigrateFinish (dconn, dname,
|
112 | |
cookie, cookielen,
|
113 | |
@@ -2671,6 +2696,11 @@ virDomainBlockPeek (virDomainPtr dom,
|
114 | |
}
|
115 | |
conn = dom->conn;
|
116 | |
|
117 | |
+ if (dom->conn->flags & VIR_CONNECT_RO) {
|
118 | |
+ virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
119 | |
+ return (-1);
|
120 | |
+ }
|
121 | |
+
|
122 | |
if (!path) {
|
123 | |
virLibDomainError (dom, VIR_ERR_INVALID_ARG,
|
124 | |
_("path is NULL"));
|
125 | |
@@ -2746,6 +2776,11 @@ virDomainMemoryPeek (virDomainPtr dom,
|
126 | |
}
|
127 | |
conn = dom->conn;
|
128 | |
|
129 | |
+ if (dom->conn->flags & VIR_CONNECT_RO) {
|
130 | |
+ virLibDomainError(dom, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
131 | |
+ return (-1);
|
132 | |
+ }
|
133 | |
+
|
134 | |
/* Flags must be VIR_MEMORY_VIRTUAL at the moment.
|
135 | |
*
|
136 | |
* Note on access to physical memory: A VIR_MEMORY_PHYSICAL flag is
|
137 | |
@@ -3013,6 +3048,11 @@ virDomainSetAutostart(virDomainPtr domain,
|
138 | |
|
139 | |
conn = domain->conn;
|
140 | |
|
141 | |
+ if (domain->conn->flags & VIR_CONNECT_RO) {
|
142 | |
+ virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
143 | |
+ return (-1);
|
144 | |
+ }
|
145 | |
+
|
146 | |
if (conn->driver->domainSetAutostart)
|
147 | |
return conn->driver->domainSetAutostart (domain, autostart);
|
148 | |
|
149 | |
@@ -3963,6 +4003,11 @@ virNetworkSetAutostart(virNetworkPtr network,
|
150 | |
return (-1);
|
151 | |
}
|
152 | |
|
153 | |
+ if (network->conn->flags & VIR_CONNECT_RO) {
|
154 | |
+ virLibNetworkError(network, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
155 | |
+ return (-1);
|
156 | |
+ }
|
157 | |
+
|
158 | |
conn = network->conn;
|
159 | |
|
160 | |
if (conn->networkDriver && conn->networkDriver->networkSetAutostart)
|
161 | |
@@ -4161,6 +4206,11 @@ virConnectFindStoragePoolSources(virConnectPtr conn,
|
162 | |
return NULL;
|
163 | |
}
|
164 | |
|
165 | |
+ if (conn->flags & VIR_CONNECT_RO) {
|
166 | |
+ virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
167 | |
+ return NULL;
|
168 | |
+ }
|
169 | |
+
|
170 | |
if (conn->storageDriver && conn->storageDriver->findPoolSources)
|
171 | |
return conn->storageDriver->findPoolSources(conn, type, srcSpec, flags);
|
172 | |
|
173 | |
@@ -4834,6 +4884,11 @@ virStoragePoolSetAutostart(virStoragePoolPtr pool,
|
174 | |
return (-1);
|
175 | |
}
|
176 | |
|
177 | |
+ if (pool->conn->flags & VIR_CONNECT_RO) {
|
178 | |
+ virLibStoragePoolError(pool, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
179 | |
+ return (-1);
|
180 | |
+ }
|
181 | |
+
|
182 | |
conn = pool->conn;
|
183 | |
|
184 | |
if (conn->storageDriver && conn->storageDriver->poolSetAutostart)
|
185 | |
--
|
186 | |
1.6.0.3
|
187 | |
|