|
|
edecca |
From 0b90fc0c5d4bd3eecbf8b51ff996116bc137d199 Mon Sep 17 00:00:00 2001
|
|
|
edecca |
Message-Id: <0b90fc0c5d4bd3eecbf8b51ff996116bc137d199@dist-git>
|
|
|
edecca |
From: Erik Skultety <eskultet@redhat.com>
|
|
|
edecca |
Date: Fri, 1 Feb 2019 17:21:58 +0100
|
|
|
edecca |
Subject: [PATCH] qemu: caps: Use CAP_DAC_OVERRIDE for probing to avoid
|
|
|
edecca |
permission issues
|
|
|
edecca |
MIME-Version: 1.0
|
|
|
edecca |
Content-Type: text/plain; charset=UTF-8
|
|
|
edecca |
Content-Transfer-Encoding: 8bit
|
|
|
edecca |
|
|
|
edecca |
This is mainly about /dev/sev and its default permissions 0600. Of
|
|
|
edecca |
course, rule of 'tinfoil' would be that we can't trust anything, but the
|
|
|
edecca |
probing code in QEMU is considered safe from security's perspective + we
|
|
|
edecca |
can't create an udev rule for this at the moment, because ioctls and
|
|
|
edecca |
file system permissions aren't cross-checked in kernel and therefore a
|
|
|
edecca |
user with read permissions could issue a 'privileged' operation on SEV
|
|
|
edecca |
which is currently only limited to root.
|
|
|
edecca |
|
|
|
edecca |
https://bugzilla.redhat.com/show_bug.cgi?id=1665400
|
|
|
edecca |
|
|
|
edecca |
Signed-off-by: Erik Skultety <eskultet@redhat.com>
|
|
|
edecca |
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
|
edecca |
(cherry picked from commit a2d3dea9d41dba313d9566120a8ec9d358567bd0)
|
|
|
edecca |
|
|
|
edecca |
Signed-off-by: Erik Skultety <eskultet@redhat.com>
|
|
|
edecca |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
edecca |
---
|
|
|
edecca |
src/qemu/qemu_capabilities.c | 11 +++++++++++
|
|
|
edecca |
src/util/virutil.c | 31 +++++++++++++++++++++++++++++--
|
|
|
edecca |
2 files changed, 40 insertions(+), 2 deletions(-)
|
|
|
edecca |
|
|
|
edecca |
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
|
|
|
edecca |
index ba8c717e22..f71cd08f4d 100644
|
|
|
edecca |
--- a/src/qemu/qemu_capabilities.c
|
|
|
edecca |
+++ b/src/qemu/qemu_capabilities.c
|
|
|
edecca |
@@ -55,6 +55,10 @@
|
|
|
edecca |
#include <stdarg.h>
|
|
|
edecca |
#include <sys/utsname.h>
|
|
|
edecca |
|
|
|
edecca |
+#if WITH_CAPNG
|
|
|
edecca |
+# include <cap-ng.h>
|
|
|
edecca |
+#endif
|
|
|
edecca |
+
|
|
|
edecca |
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
edecca |
|
|
|
edecca |
VIR_LOG_INIT("qemu.qemu_capabilities");
|
|
|
edecca |
@@ -4474,6 +4478,13 @@ virQEMUCapsInitQMPCommandRun(virQEMUCapsInitQMPCommandPtr cmd,
|
|
|
edecca |
NULL);
|
|
|
edecca |
virCommandAddEnvPassCommon(cmd->cmd);
|
|
|
edecca |
virCommandClearCaps(cmd->cmd);
|
|
|
edecca |
+
|
|
|
edecca |
+#if WITH_CAPNG
|
|
|
edecca |
+ /* QEMU might run into permission issues, e.g. /dev/sev (0600), override
|
|
|
edecca |
+ * them just for the purpose of probing */
|
|
|
edecca |
+ virCommandAllowCap(cmd->cmd, CAP_DAC_OVERRIDE);
|
|
|
edecca |
+#endif
|
|
|
edecca |
+
|
|
|
edecca |
virCommandSetGID(cmd->cmd, cmd->runGid);
|
|
|
edecca |
virCommandSetUID(cmd->cmd, cmd->runUid);
|
|
|
edecca |
|
|
|
edecca |
diff --git a/src/util/virutil.c b/src/util/virutil.c
|
|
|
edecca |
index a908422feb..88e17e2c0f 100644
|
|
|
edecca |
--- a/src/util/virutil.c
|
|
|
edecca |
+++ b/src/util/virutil.c
|
|
|
edecca |
@@ -1474,8 +1474,10 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
|
|
|
edecca |
{
|
|
|
edecca |
size_t i;
|
|
|
edecca |
int capng_ret, ret = -1;
|
|
|
edecca |
- bool need_setgid = false, need_setuid = false;
|
|
|
edecca |
+ bool need_setgid = false;
|
|
|
edecca |
+ bool need_setuid = false;
|
|
|
edecca |
bool need_setpcap = false;
|
|
|
edecca |
+ const char *capstr = NULL;
|
|
|
edecca |
|
|
|
edecca |
/* First drop all caps (unless the requested uid is "unchanged" or
|
|
|
edecca |
* root and clearExistingCaps wasn't requested), then add back
|
|
|
edecca |
@@ -1484,14 +1486,18 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
|
|
|
edecca |
*/
|
|
|
edecca |
|
|
|
edecca |
if (clearExistingCaps || (uid != (uid_t)-1 && uid != 0))
|
|
|
edecca |
- capng_clear(CAPNG_SELECT_BOTH);
|
|
|
edecca |
+ capng_clear(CAPNG_SELECT_BOTH);
|
|
|
edecca |
|
|
|
edecca |
for (i = 0; i <= CAP_LAST_CAP; i++) {
|
|
|
edecca |
+ capstr = capng_capability_to_name(i);
|
|
|
edecca |
+
|
|
|
edecca |
if (capBits & (1ULL << i)) {
|
|
|
edecca |
capng_update(CAPNG_ADD,
|
|
|
edecca |
CAPNG_EFFECTIVE|CAPNG_INHERITABLE|
|
|
|
edecca |
CAPNG_PERMITTED|CAPNG_BOUNDING_SET,
|
|
|
edecca |
i);
|
|
|
edecca |
+
|
|
|
edecca |
+ VIR_DEBUG("Added '%s' to child capabilities' set", capstr);
|
|
|
edecca |
}
|
|
|
edecca |
}
|
|
|
edecca |
|
|
|
edecca |
@@ -1551,6 +1557,27 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
|
|
|
edecca |
goto cleanup;
|
|
|
edecca |
}
|
|
|
edecca |
|
|
|
edecca |
+# ifdef PR_CAP_AMBIENT
|
|
|
edecca |
+ /* we couldn't do this in the loop earlier above, because the capabilities
|
|
|
edecca |
+ * were not applied yet, since in order to add a capability into the AMBIENT
|
|
|
edecca |
+ * set, it has to be present in both the PERMITTED and INHERITABLE sets
|
|
|
edecca |
+ * (capabilities(7))
|
|
|
edecca |
+ */
|
|
|
edecca |
+ for (i = 0; i <= CAP_LAST_CAP; i++) {
|
|
|
edecca |
+ capstr = capng_capability_to_name(i);
|
|
|
edecca |
+
|
|
|
edecca |
+ if (capBits & (1ULL << i)) {
|
|
|
edecca |
+ if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0) {
|
|
|
edecca |
+ virReportSystemError(errno,
|
|
|
edecca |
+ _("prctl failed to enable '%s' in the "
|
|
|
edecca |
+ "AMBIENT set"),
|
|
|
edecca |
+ capstr);
|
|
|
edecca |
+ goto cleanup;
|
|
|
edecca |
+ }
|
|
|
edecca |
+ }
|
|
|
edecca |
+ }
|
|
|
edecca |
+# endif
|
|
|
edecca |
+
|
|
|
edecca |
/* Set bounding set while we have CAP_SETPCAP. Unfortunately we cannot
|
|
|
edecca |
* do this if we failed to get the capability above, so ignore the
|
|
|
edecca |
* return value.
|
|
|
edecca |
--
|
|
|
edecca |
2.20.1
|
|
|
edecca |
|