From: "Richard W.M. Jones" <rjones(a)redhat.com>
According to Eric Paris this is slightly more efficient because it
only loads the regular expressions in libselinux once.
---
src/security/security_selinux.c | 129 ++++++++++++++++++++++++++--------------
1 file changed, 83 insertions(+), 46 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index a3ef728..d1f80b2 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -63,6 +63,9 @@ struct _virSecuritySELinuxData {
char *content_context;
virHashTablePtr mcs;
bool skipAllLabel;
+#if HAVE_SELINUX_LABEL_H
+ struct selabel_handle *label_handle;
+#endif
};
struct _virSecuritySELinuxCallbackData {
@@ -367,12 +370,21 @@ virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr)
data->skipAllLabel = true;
+#if HAVE_SELINUX_LABEL_H
+ data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (!data->label_handle) {
+ virReportSystemError(errno,
+ _("cannot open SELinux label_handle"));
+ return -1;
+ }
+#endif
+
selinux_conf = virConfReadFile(selinux_lxc_contexts_path(), 0);
if (!selinux_conf) {
virReportSystemError(errno,
_("cannot open SELinux lxc contexts file
'%s'"),
selinux_lxc_contexts_path());
- return -1;
+ goto error;
}
scon = virConfGetValue(selinux_conf, "process");
@@ -418,6 +430,9 @@ virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr)
return 0;
error:
+#if HAVE_SELINUX_LABEL_H
+ selabel_close(data->label_handle);
+#endif
virConfFree(selinux_conf);
VIR_FREE(data->domain_context);
VIR_FREE(data->file_context);
@@ -444,6 +459,15 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
data->skipAllLabel = false;
+#if HAVE_SELINUX_LABEL_H
+ data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (!data->label_handle) {
+ virReportSystemError(errno,
+ _("cannot open SELinux label_handle"));
+ return -1;
+ }
+#endif
+
if (virFileReadAll(selinux_virtual_domain_context_path(), MAX_CONTEXT,
&(data->domain_context)) < 0) {
virReportSystemError(errno,
_("cannot read SELinux virtual domain context file
'%s'"),
@@ -499,6 +523,9 @@ virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
return 0;
error:
+#if HAVE_SELINUX_LABEL_H
+ selabel_close(data->label_handle);
+#endif
VIR_FREE(data->domain_context);
VIR_FREE(data->alt_domain_context);
VIR_FREE(data->file_context);
@@ -763,6 +790,10 @@ virSecuritySELinuxSecurityDriverClose(virSecurityManagerPtr mgr)
if (!data)
return 0;
+#if HAVE_SELINUX_LABEL_H
+ selabel_close(data->label_handle);
+#endif
+
virHashFree(data->mcs);
VIR_FREE(data->domain_context);
@@ -937,18 +968,13 @@ virSecuritySELinuxFSetFilecon(int fd, char *tcon)
/* Set fcon to the appropriate label for path and mode, or return -1. */
static int
-getContext(const char *newpath, mode_t mode, security_context_t *fcon)
+getContext(virSecurityManagerPtr mgr,
+ const char *newpath, mode_t mode, security_context_t *fcon)
{
#if HAVE_SELINUX_LABEL_H
- struct selabel_handle *handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- int ret;
-
- if (handle == NULL)
- return -1;
+ virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
- ret = selabel_lookup_raw(handle, fcon, newpath, mode);
- selabel_close(handle);
- return ret;
+ return selabel_lookup_raw(data->label_handle, fcon, newpath, mode);
#else
return matchpathcon(newpath, mode, fcon);
#endif
@@ -958,7 +984,8 @@ getContext(const char *newpath, mode_t mode, security_context_t
*fcon)
/* This method shouldn't raise errors, since they'll overwrite
* errors that the caller(s) are already dealing with */
static int
-virSecuritySELinuxRestoreSecurityFileLabel(const char *path)
+virSecuritySELinuxRestoreSecurityFileLabel(virSecurityManagerPtr mgr,
+ const char *path)
{
struct stat buf;
security_context_t fcon = NULL;
@@ -980,7 +1007,7 @@ virSecuritySELinuxRestoreSecurityFileLabel(const char *path)
goto err;
}
- if (getContext(newpath, buf.st_mode, &fcon) < 0) {
+ if (getContext(mgr, newpath, buf.st_mode, &fcon) < 0) {
/* Any user created path likely does not have a default label,
* which makes this an expected non error
*/
@@ -997,7 +1024,7 @@ err:
}
static int
-virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr
ATTRIBUTE_UNUSED,
+virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
virDomainDefPtr def,
virDomainDiskDefPtr disk,
int migrated)
@@ -1044,7 +1071,7 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr
mgr ATTRIBU
}
}
- return virSecuritySELinuxRestoreSecurityFileLabel(disk->src);
+ return virSecuritySELinuxRestoreSecurityFileLabel(mgr, disk->src);
}
@@ -1301,22 +1328,27 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr
mgr ATTRIBUTE_UN
static int
virSecuritySELinuxRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
const char *file,
- void *opaque ATTRIBUTE_UNUSED)
+ void *opaque)
{
- return virSecuritySELinuxRestoreSecurityFileLabel(file);
+ virSecurityManagerPtr mgr = opaque;
+
+ return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file);
}
static int
virSecuritySELinuxRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
const char *file,
- void *opaque ATTRIBUTE_UNUSED)
+ void *opaque)
{
- return virSecuritySELinuxRestoreSecurityFileLabel(file);
+ virSecurityManagerPtr mgr = opaque;
+
+ return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file);
}
static int
-virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev,
+virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr,
+ virDomainHostdevDefPtr dev,
const char *vroot)
{
@@ -1335,7 +1367,7 @@
virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev,
if (!usb)
goto done;
- ret = usbDeviceFileIterate(usb, virSecuritySELinuxRestoreSecurityUSBLabel,
NULL);
+ ret = usbDeviceFileIterate(usb, virSecuritySELinuxRestoreSecurityUSBLabel, mgr);
usbFreeDevice(usb);
break;
@@ -1350,7 +1382,7 @@
virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virDomainHostdevDefPtr dev,
if (!pci)
goto done;
- ret = pciDeviceFileIterate(pci, virSecuritySELinuxRestoreSecurityPCILabel,
NULL);
+ ret = pciDeviceFileIterate(pci, virSecuritySELinuxRestoreSecurityPCILabel, mgr);
pciFreeDevice(pci);
break;
@@ -1367,7 +1399,8 @@ done:
static int
-virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev,
+virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virSecurityManagerPtr mgr,
+ virDomainHostdevDefPtr dev,
const char *vroot)
{
int ret = -1;
@@ -1387,7 +1420,7 @@
virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev,
return -1;
}
}
- ret = virSecuritySELinuxRestoreSecurityFileLabel(path);
+ ret = virSecuritySELinuxRestoreSecurityFileLabel(mgr, path);
VIR_FREE(path);
break;
}
@@ -1405,7 +1438,7 @@
virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev,
return -1;
}
}
- ret = virSecuritySELinuxRestoreSecurityFileLabel(path);
+ ret = virSecuritySELinuxRestoreSecurityFileLabel(mgr, path);
VIR_FREE(path);
break;
}
@@ -1420,7 +1453,7 @@
virSecuritySELinuxRestoreSecurityHostdevCapsLabel(virDomainHostdevDefPtr dev,
static int
-virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr
ATTRIBUTE_UNUSED,
+virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
virDomainHostdevDefPtr dev,
const char *vroot)
@@ -1437,10 +1470,10 @@
virSecuritySELinuxRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUT
switch (dev->mode) {
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
- return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(dev, vroot);
+ return virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(mgr, dev, vroot);
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
- return virSecuritySELinuxRestoreSecurityHostdevCapsLabel(dev, vroot);
+ return virSecuritySELinuxRestoreSecurityHostdevCapsLabel(mgr, dev, vroot);
default:
return 0;
@@ -1522,7 +1555,8 @@ done:
}
static int
-virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr def,
+virSecuritySELinuxRestoreSecurityChardevLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
virDomainChrDefPtr dev,
virDomainChrSourceDefPtr dev_source)
@@ -1545,14 +1579,14 @@ virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr
def,
switch (dev_source->type) {
case VIR_DOMAIN_CHR_TYPE_DEV:
case VIR_DOMAIN_CHR_TYPE_FILE:
- if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path)
< 0)
+ if (virSecuritySELinuxRestoreSecurityFileLabel(mgr,
dev_source->data.file.path) < 0)
goto done;
ret = 0;
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
if (!dev_source->data.nix.listen) {
- if (virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path)
< 0)
+ if (virSecuritySELinuxRestoreSecurityFileLabel(mgr,
dev_source->data.file.path) < 0)
goto done;
}
ret = 0;
@@ -1565,11 +1599,11 @@ virSecuritySELinuxRestoreSecurityChardevLabel(virDomainDefPtr
def,
goto done;
}
if (virFileExists(in) && virFileExists(out)) {
- if ((virSecuritySELinuxRestoreSecurityFileLabel(out) < 0) ||
- (virSecuritySELinuxRestoreSecurityFileLabel(in) < 0)) {
+ if ((virSecuritySELinuxRestoreSecurityFileLabel(mgr, out) < 0) ||
+ (virSecuritySELinuxRestoreSecurityFileLabel(mgr, in) < 0)) {
goto done;
}
- } else if
(virSecuritySELinuxRestoreSecurityFileLabel(dev_source->data.file.path) < 0) {
+ } else if (virSecuritySELinuxRestoreSecurityFileLabel(mgr,
dev_source->data.file.path) < 0) {
goto done;
}
ret = 0;
@@ -1590,14 +1624,16 @@ done:
static int
virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDefPtr def,
virDomainChrDefPtr dev,
- void *opaque ATTRIBUTE_UNUSED)
+ void *opaque)
{
+ virSecurityManagerPtr mgr = opaque;
+
/* This is taken care of by processing of def->serials */
if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
return 0;
- return virSecuritySELinuxRestoreSecurityChardevLabel(def, dev,
+ return virSecuritySELinuxRestoreSecurityChardevLabel(mgr, def, dev,
&dev->source);
}
@@ -1605,8 +1641,9 @@ virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDefPtr
def,
static int
virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def,
virDomainSmartcardDefPtr dev,
- void *opaque ATTRIBUTE_UNUSED)
+ void *opaque)
{
+ virSecurityManagerPtr mgr = opaque;
const char *database;
switch (dev->type) {
@@ -1617,10 +1654,10 @@ virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr
def,
database = dev->data.cert.database;
if (!database)
database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
- return virSecuritySELinuxRestoreSecurityFileLabel(database);
+ return virSecuritySELinuxRestoreSecurityFileLabel(mgr, database);
case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
- return virSecuritySELinuxRestoreSecurityChardevLabel(def, NULL,
&dev->data.passthru);
+ return virSecuritySELinuxRestoreSecurityChardevLabel(mgr, def, NULL,
&dev->data.passthru);
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1670,21 +1707,21 @@ virSecuritySELinuxRestoreSecurityAllLabel(virSecurityManagerPtr
mgr,
if (virDomainChrDefForeach(def,
false,
virSecuritySELinuxRestoreSecurityChardevCallback,
- NULL) < 0)
+ mgr) < 0)
rc = -1;
if (virDomainSmartcardDefForeach(def,
false,
virSecuritySELinuxRestoreSecuritySmartcardCallback,
- NULL) < 0)
+ mgr) < 0)
rc = -1;
if (def->os.kernel &&
- virSecuritySELinuxRestoreSecurityFileLabel(def->os.kernel) < 0)
+ virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.kernel) < 0)
rc = -1;
if (def->os.initrd &&
- virSecuritySELinuxRestoreSecurityFileLabel(def->os.initrd) < 0)
+ virSecuritySELinuxRestoreSecurityFileLabel(mgr, def->os.initrd) < 0)
rc = -1;
return rc;
@@ -1737,7 +1774,7 @@ virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr
ATTRIBUTE_UNUSED,
static int
-virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
const char *savefile)
{
@@ -1750,7 +1787,7 @@ virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr
ATTRIBUTE_UNU
if (secdef->norelabel)
return 0;
- return virSecuritySELinuxRestoreSecurityFileLabel(savefile);
+ return virSecuritySELinuxRestoreSecurityFileLabel(mgr, savefile);
}
@@ -2080,7 +2117,7 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr
ATTRIBUTE_UNUSED,
}
static int
-virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd)
{
@@ -2108,7 +2145,7 @@ virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr
ATTRIBUTE_UNUSED,
goto cleanup;
}
- if (getContext("/dev/tap.*", buf.st_mode, &fcon) < 0) {
+ if (getContext(mgr, "/dev/tap.*", buf.st_mode, &fcon) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot lookup default selinux label for tap fd %d"),
fd);
goto cleanup;
--
1.8.1