|
|
43fe83 |
From 13572b2c50e079c5618870af7ae64bf3a73154d7 Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <13572b2c50e079c5618870af7ae64bf3a73154d7.1379597659.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: "Daniel P. Berrange" <berrange@redhat.com>
|
|
|
43fe83 |
Date: Wed, 28 Aug 2013 15:25:40 +0100
|
|
|
43fe83 |
Subject: [PATCH] Add support for using 3-arg pkcheck syntax for process
|
|
|
43fe83 |
|
|
|
43fe83 |
CVE-2013-4311
|
|
|
43fe83 |
|
|
|
43fe83 |
With the existing pkcheck (pid, start time) tuple for identifying
|
|
|
43fe83 |
the process, there is a race condition, where a process can make
|
|
|
43fe83 |
a libvirt RPC call and in another thread exec a setuid application,
|
|
|
43fe83 |
causing it to change to effective UID 0. This in turn causes polkit
|
|
|
43fe83 |
to do its permission check based on the wrong UID.
|
|
|
43fe83 |
|
|
|
43fe83 |
To address this, libvirt must get the UID the caller had at time
|
|
|
43fe83 |
of connect() (from SO_PEERCRED) and pass a (pid, start time, uid)
|
|
|
43fe83 |
triple to the pkcheck program.
|
|
|
43fe83 |
|
|
|
43fe83 |
This fix requires that libvirt is re-built against a version of
|
|
|
43fe83 |
polkit that has the fix for its CVE-2013-4288, so that libvirt
|
|
|
43fe83 |
can see 'pkg-config --variable pkcheck_supports_uid polkit-gobject-1'
|
|
|
43fe83 |
|
|
|
43fe83 |
Signed-off-by: Colin Walters <walters@redhat.com>
|
|
|
43fe83 |
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
|
|
|
43fe83 |
(cherry picked from commit 922b7fda77b094dbf022d625238262ea05335666)
|
|
|
43fe83 |
---
|
|
|
43fe83 |
configure.ac | 8 ++++++++
|
|
|
43fe83 |
daemon/remote.c | 22 ++++++++++++++++++---
|
|
|
43fe83 |
libvirt.spec.in | 7 ++++---
|
|
|
43fe83 |
src/access/viraccessdriverpolkit.c | 40 +++++++++++++++++++++++++++++++++-----
|
|
|
43fe83 |
4 files changed, 66 insertions(+), 11 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/configure.ac b/configure.ac
|
|
|
43fe83 |
index 917db6a..7dd6ca3 100644
|
|
|
43fe83 |
--- a/configure.ac
|
|
|
43fe83 |
+++ b/configure.ac
|
|
|
43fe83 |
@@ -1166,6 +1166,14 @@ if test "x$with_polkit" = "xyes" || test "x$with_polkit" = "xcheck"; then
|
|
|
43fe83 |
AC_PATH_PROG([PKCHECK_PATH],[pkcheck], [], [/usr/sbin:$PATH])
|
|
|
43fe83 |
if test "x$PKCHECK_PATH" != "x" ; then
|
|
|
43fe83 |
AC_DEFINE_UNQUOTED([PKCHECK_PATH],["$PKCHECK_PATH"],[Location of pkcheck program])
|
|
|
43fe83 |
+ AC_MSG_CHECKING([whether pkcheck supports uid value])
|
|
|
43fe83 |
+ pkcheck_supports_uid=`$PKG_CONFIG --variable pkcheck_supports_uid polkit-gobject-1`
|
|
|
43fe83 |
+ if test "x$pkcheck_supports_uid" = "xtrue"; then
|
|
|
43fe83 |
+ AC_MSG_RESULT([yes])
|
|
|
43fe83 |
+ AC_DEFINE_UNQUOTED([PKCHECK_SUPPORTS_UID], 1, [Pass uid to pkcheck])
|
|
|
43fe83 |
+ else
|
|
|
43fe83 |
+ AC_MSG_RESULT([no])
|
|
|
43fe83 |
+ fi
|
|
|
43fe83 |
AC_DEFINE_UNQUOTED([WITH_POLKIT], 1,
|
|
|
43fe83 |
[use PolicyKit for UNIX socket access checks])
|
|
|
43fe83 |
AC_DEFINE_UNQUOTED([WITH_POLKIT1], 1,
|
|
|
43fe83 |
diff --git a/daemon/remote.c b/daemon/remote.c
|
|
|
43fe83 |
index 6ace7af..b5395dd 100644
|
|
|
43fe83 |
--- a/daemon/remote.c
|
|
|
43fe83 |
+++ b/daemon/remote.c
|
|
|
43fe83 |
@@ -2738,10 +2738,12 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED,
|
|
|
43fe83 |
int status = -1;
|
|
|
43fe83 |
char *ident = NULL;
|
|
|
43fe83 |
bool authdismissed = 0;
|
|
|
43fe83 |
+ bool supportsuid = false;
|
|
|
43fe83 |
char *pkout = NULL;
|
|
|
43fe83 |
struct daemonClientPrivate *priv =
|
|
|
43fe83 |
virNetServerClientGetPrivateData(client);
|
|
|
43fe83 |
virCommandPtr cmd = NULL;
|
|
|
43fe83 |
+ static bool polkitInsecureWarned;
|
|
|
43fe83 |
|
|
|
43fe83 |
virMutexLock(&priv->lock);
|
|
|
43fe83 |
action = virNetServerClientGetReadonly(client) ?
|
|
|
43fe83 |
@@ -2763,14 +2765,28 @@ remoteDispatchAuthPolkit(virNetServerPtr server ATTRIBUTE_UNUSED,
|
|
|
43fe83 |
goto authfail;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+ if (timestamp == 0) {
|
|
|
43fe83 |
+ VIR_WARN("Failing polkit auth due to missing client (pid=%lld) start time",
|
|
|
43fe83 |
+ (long long)callerPid);
|
|
|
43fe83 |
+ goto authfail;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
VIR_INFO("Checking PID %lld running as %d",
|
|
|
43fe83 |
(long long) callerPid, callerUid);
|
|
|
43fe83 |
|
|
|
43fe83 |
virCommandAddArg(cmd, "--process");
|
|
|
43fe83 |
- if (timestamp != 0) {
|
|
|
43fe83 |
- virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp);
|
|
|
43fe83 |
+# ifdef PKCHECK_SUPPORTS_UID
|
|
|
43fe83 |
+ supportsuid = true;
|
|
|
43fe83 |
+# endif
|
|
|
43fe83 |
+ if (supportsuid) {
|
|
|
43fe83 |
+ virCommandAddArgFormat(cmd, "%lld,%llu,%lu",
|
|
|
43fe83 |
+ (long long) callerPid, timestamp, (unsigned long) callerUid);
|
|
|
43fe83 |
} else {
|
|
|
43fe83 |
- virCommandAddArgFormat(cmd, "%lld", (long long) callerPid);
|
|
|
43fe83 |
+ if (!polkitInsecureWarned) {
|
|
|
43fe83 |
+ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure.");
|
|
|
43fe83 |
+ polkitInsecureWarned = true;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ virCommandAddArgFormat(cmd, "%lld,%llu", (long long) callerPid, timestamp);
|
|
|
43fe83 |
}
|
|
|
43fe83 |
virCommandAddArg(cmd, "--allow-user-interaction");
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c
|
|
|
43fe83 |
index b472bc3..ff82583 100644
|
|
|
43fe83 |
--- a/src/access/viraccessdriverpolkit.c
|
|
|
43fe83 |
+++ b/src/access/viraccessdriverpolkit.c
|
|
|
43fe83 |
@@ -72,8 +72,12 @@ static char *
|
|
|
43fe83 |
virAccessDriverPolkitFormatProcess(const char *actionid)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
virIdentityPtr identity = virIdentityGetCurrent();
|
|
|
43fe83 |
- const char *process = NULL;
|
|
|
43fe83 |
+ const char *callerPid = NULL;
|
|
|
43fe83 |
+ const char *callerTime = NULL;
|
|
|
43fe83 |
+ const char *callerUid = NULL;
|
|
|
43fe83 |
char *ret = NULL;
|
|
|
43fe83 |
+ bool supportsuid = false;
|
|
|
43fe83 |
+ static bool polkitInsecureWarned;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (!identity) {
|
|
|
43fe83 |
virAccessError(VIR_ERR_ACCESS_DENIED,
|
|
|
43fe83 |
@@ -81,17 +85,43 @@ virAccessDriverPolkitFormatProcess(const char *actionid)
|
|
|
43fe83 |
actionid);
|
|
|
43fe83 |
return NULL;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
- if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &process) < 0)
|
|
|
43fe83 |
+ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &callerPid) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_TIME, &callerTime) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_USER_ID, &callerUid) < 0)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
- if (!process) {
|
|
|
43fe83 |
+ if (!callerPid) {
|
|
|
43fe83 |
virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
_("No UNIX process ID available"));
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
-
|
|
|
43fe83 |
- if (VIR_STRDUP(ret, process) < 0)
|
|
|
43fe83 |
+ if (!callerTime) {
|
|
|
43fe83 |
+ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("No UNIX process start time available"));
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ if (!callerUid) {
|
|
|
43fe83 |
+ virAccessError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("No UNIX caller UID available"));
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+
|
|
|
43fe83 |
+#ifdef PKCHECK_SUPPORTS_UID
|
|
|
43fe83 |
+ supportsuid = true;
|
|
|
43fe83 |
+#endif
|
|
|
43fe83 |
+ if (supportsuid) {
|
|
|
43fe83 |
+ if (virAsprintf(&ret, "%s,%s,%s", callerPid, callerTime, callerUid) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ } else {
|
|
|
43fe83 |
+ if (!polkitInsecureWarned) {
|
|
|
43fe83 |
+ VIR_WARN("No support for caller UID with pkcheck. This deployment is known to be insecure.");
|
|
|
43fe83 |
+ polkitInsecureWarned = true;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
+ if (virAsprintf(&ret, "%s,%s", callerPid, callerTime) < 0)
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
|
|
|
43fe83 |
cleanup:
|
|
|
43fe83 |
virObjectUnref(identity);
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.3.2
|
|
|
43fe83 |
|