Whenever a security driver wants to change label of some path, it
should let virUdevMgr module know so that it can update its
internal database too.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 2 ++
src/security/security_dac.c | 36 ++++++++++++++++++++++++++++---
src/security/security_manager.c | 16 ++++++++++++++
src/security/security_manager.h | 5 +++++
src/security/security_selinux.c | 47 ++++++++++++++++++++++++++++++++++++++---
5 files changed, 100 insertions(+), 6 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 037443b..c6d17c4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1147,6 +1147,7 @@ virSecurityManagerGetModel;
virSecurityManagerGetMountOptions;
virSecurityManagerGetNested;
virSecurityManagerGetProcessLabel;
+virSecurityManagerGetUdevManager;
virSecurityManagerNew;
virSecurityManagerNewDAC;
virSecurityManagerNewStack;
@@ -1171,6 +1172,7 @@ virSecurityManagerSetProcessLabel;
virSecurityManagerSetSavedStateLabel;
virSecurityManagerSetSocketLabel;
virSecurityManagerSetTapFDLabel;
+virSecurityManagerSetUdevManager;
virSecurityManagerStackAddNested;
virSecurityManagerVerify;
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 7f17124..54e59c7 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -356,7 +356,11 @@ virSecurityDACSetOwnership(virSecurityManagerPtr mgr,
gid_t gid)
{
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virUdevMgrPtr udevMgr = virSecurityManagerGetUdevManager(mgr);
+ virSecurityDeviceLabelDefPtr seclabel = NULL;
+ char *label = NULL;
struct stat sb;
+ int ret = -1;
if (!path && src && src->path &&
virStorageSourceIsLocalStorage(src))
@@ -365,14 +369,36 @@ virSecurityDACSetOwnership(virSecurityManagerPtr mgr,
if (path) {
if (stat(path, &sb) < 0) {
virReportSystemError(errno, _("unable to stat: %s"), path);
- return -1;
+ return ret;
}
if (virSecurityDACRememberLabel(priv, path, sb.st_uid, sb.st_gid) < 0)
- return -1;
+ return ret;
+
+ if (udevMgr) {
+ if (virAsprintf(&label, "%u %u",
+ (unsigned int) uid,
+ (unsigned int) gid) < 0)
+ goto cleanup;
+
+ if (!(seclabel = virSecurityDeviceLabelDefNewLabel(SECURITY_DAC_NAME,
label)))
+ goto cleanup;
+ VIR_FREE(label);
+ }
}
- return virSecurityDACSetOwnershipInternal(priv, src, path, uid, gid);
+ if (virSecurityDACSetOwnershipInternal(priv, src, path, uid, gid) < 0)
+ goto cleanup;
+
+ if (udevMgr && path &&
+ virUdevMgrAddLabel(udevMgr, path, seclabel) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(label);
+ virSecurityDeviceLabelDefFree(seclabel);
+ return ret;
}
@@ -382,6 +408,7 @@ virSecurityDACRestoreFileLabelInternal(virSecurityManagerPtr mgr,
const char *path)
{
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virUdevMgrPtr udevMgr = virSecurityManagerGetUdevManager(mgr);
int rv;
uid_t uid = 0; /* By default return to root:root */
gid_t gid = 0;
@@ -399,6 +426,9 @@ virSecurityDACRestoreFileLabelInternal(virSecurityManagerPtr mgr,
return -1;
if (rv > 0)
return 0;
+
+ if (udevMgr)
+ virUdevMgrRemoveAllLabels(udevMgr, path);
}
return virSecurityDACSetOwnershipInternal(priv, src, path, uid, gid);
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index ecb4a40..2f07d6a 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -39,6 +39,7 @@ struct _virSecurityManager {
virSecurityDriverPtr drv;
unsigned int flags;
const char *virtDriver;
+ virUdevMgrPtr udevMgr;
void *privateData;
};
@@ -1001,3 +1002,18 @@ virSecurityManagerDomainSetPathLabel(virSecurityManagerPtr mgr,
return 0;
}
+
+
+void
+virSecurityManagerSetUdevManager(virSecurityManagerPtr mgr,
+ virUdevMgrPtr udevMgr)
+{
+ mgr->udevMgr = virObjectRef(udevMgr);
+}
+
+
+virUdevMgrPtr
+virSecurityManagerGetUdevManager(virSecurityManagerPtr mgr)
+{
+ return mgr->udevMgr;
+}
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index 4cbc2d8..8f565f7 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -26,6 +26,7 @@
# include "domain_conf.h"
# include "vircommand.h"
# include "virstoragefile.h"
+# include "virudev.h"
typedef struct _virSecurityManager virSecurityManager;
typedef virSecurityManager *virSecurityManagerPtr;
@@ -164,4 +165,8 @@ int virSecurityManagerDomainSetPathLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
const char *path);
+void virSecurityManagerSetUdevManager(virSecurityManagerPtr mgr,
+ virUdevMgrPtr udevMgr);
+virUdevMgrPtr virSecurityManagerGetUdevManager(virSecurityManagerPtr mgr);
+
#endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 5dad22c..c85f500 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -947,7 +947,24 @@ virSecuritySELinuxSetFileconOptional(virSecurityManagerPtr mgr,
const char *path, char *tcon)
{
bool privileged = virSecurityManagerGetPrivileged(mgr);
- return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged);
+ virUdevMgrPtr udevMgr = virSecurityManagerGetUdevManager(mgr);
+ virSecurityDeviceLabelDefPtr seclabel = NULL;
+ int rc;
+
+ if (udevMgr &&
+ !(seclabel = virSecurityDeviceLabelDefNewLabel(SECURITY_SELINUX_NAME, tcon)))
+ return -1;
+
+ rc = virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged);
+
+ if (udevMgr &&
+ virUdevMgrAddLabel(udevMgr, path, seclabel) < 0) {
+ virSecurityDeviceLabelDefFree(seclabel);
+ return -1;
+ }
+
+ virSecurityDeviceLabelDefFree(seclabel);
+ return rc;
}
static int
@@ -955,7 +972,24 @@ virSecuritySELinuxSetFilecon(virSecurityManagerPtr mgr,
const char *path, char *tcon)
{
bool privileged = virSecurityManagerGetPrivileged(mgr);
- return virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged);
+ virUdevMgrPtr udevMgr = virSecurityManagerGetUdevManager(mgr);
+ virSecurityDeviceLabelDefPtr seclabel = NULL;
+ int rc;
+
+ if (udevMgr &&
+ !(seclabel = virSecurityDeviceLabelDefNewLabel(SECURITY_SELINUX_NAME, tcon)))
+ return -1;
+
+ rc = virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged);
+
+ if (udevMgr &&
+ virUdevMgrAddLabel(udevMgr, path, seclabel) < 0) {
+ virSecurityDeviceLabelDefFree(seclabel);
+ return -1;
+ }
+
+ virSecurityDeviceLabelDefFree(seclabel);
+ return rc;
}
static int
@@ -1018,6 +1052,8 @@ static int
virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr,
const char *path)
{
+ virUdevMgrPtr udevMgr = virSecurityManagerGetUdevManager(mgr);
+ bool privileged = virSecurityManagerGetPrivileged(mgr);
struct stat buf;
security_context_t fcon = NULL;
int rc = -1;
@@ -1038,6 +1074,11 @@ virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr,
goto err;
}
+ if (udevMgr) {
+ virUdevMgrRemoveAllLabels(udevMgr, path);
+ virUdevMgrRemoveAllLabels(udevMgr, newpath);
+ }
+
if (stat(newpath, &buf) != 0) {
VIR_WARN("cannot stat %s: %s", newpath,
virStrerror(errno, ebuf, sizeof(ebuf)));
@@ -1051,7 +1092,7 @@ virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr,
VIR_WARN("cannot lookup default selinux label for %s", newpath);
rc = 0;
} else {
- rc = virSecuritySELinuxSetFilecon(mgr, newpath, fcon);
+ rc = virSecuritySELinuxSetFileconHelper(newpath, fcon, false, privileged);
}
err:
--
2.8.4