This is a small helper intended to be run by udev. On its input
(either as the only command line argument or in DEVNODE
environment vairable) it is given a device and on the output it
will either put nothing (meaning the device is not used by any of
the libvirt domains), or it will print out security labels in the
following form:
UID GID SELABEL
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 2 +
po/POTFILES.in | 1 +
src/Makefile.am | 20 ++++++++
src/util/udevhelper.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 161 insertions(+)
create mode 100644 src/util/udevhelper.c
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 545990c..856c702 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1630,6 +1630,7 @@ exit 0
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/
%attr(0755, root, root) %{_libexecdir}/libvirt_iohelper
+%attr(0755, root, root) %{_libexecdir}/libvirt_udevhelper
%attr(0755, root, root) %{_sbindir}/libvirtd
%attr(0755, root, root) %{_sbindir}/virtlogd
diff --git a/mingw-libvirt.spec.in b/mingw-libvirt.spec.in
index c9bf503..015b06b 100644
--- a/mingw-libvirt.spec.in
+++ b/mingw-libvirt.spec.in
@@ -178,6 +178,8 @@ rm -rf $RPM_BUILD_ROOT%{mingw64_datadir}/gtk-doc/*
rm -rf $RPM_BUILD_ROOT%{mingw32_libexecdir}/libvirt_iohelper.exe
rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_iohelper.exe
+rm -rf $RPM_BUILD_ROOT%{mingw32_libexecdir}/libvirt_udevhelper.exe
+rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt_udevhelper.exe
rm -rf $RPM_BUILD_ROOT%{mingw32_libexecdir}/libvirt-guests.sh
rm -rf $RPM_BUILD_ROOT%{mingw64_libexecdir}/libvirt-guests.sh
diff --git a/po/POTFILES.in b/po/POTFILES.in
index dabc612..7a89cbd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -178,6 +178,7 @@ src/test/test_driver.c
src/uml/uml_conf.c
src/uml/uml_driver.c
src/util/iohelper.c
+src/util/udevhelper.c
src/util/viralloc.c
src/util/viraudit.c
src/util/virauth.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 2ea6f2b..0c97728 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1007,6 +1007,9 @@ STORAGE_HELPER_DISK_SOURCES = \
UTIL_IO_HELPER_SOURCES = \
util/iohelper.c
+UTIL_UDEV_HELPER_SOURCES = \
+ util/udevhelper.c
+
NETWORK_LEASES_HELPER_SOURCES = \
network/leaseshelper.c
@@ -2858,6 +2861,23 @@ libvirt_iohelper_CFLAGS = \
$(PIE_CFLAGS) \
$(NULL)
+libexec_PROGRAMS += libvirt_udevhelper
+libvirt_udevhelper_SOURCES = $(UTIL_UDEV_HELPER_SOURCES)
+libvirt_udevhelper_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(PIE_CFLAGS) \
+ $(NULL)
+libvirt_udevhelper_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ $(PIE_LDFLAGS) \
+ $(NULL)
+libvirt_udevhelper_LDADD = \
+ libvirt_util.la \
+ ../gnulib/lib/libgnu.la
+if WITH_DTRACE_PROBES
+libvirt_udevhelper_LDADD += libvirt_probes.lo
+endif WITH_DTRACE_PROBES
+
if WITH_NETWORK
libexec_PROGRAMS += libvirt_leaseshelper
libvirt_leaseshelper_SOURCES = $(NETWORK_LEASES_HELPER_SOURCES)
diff --git a/src/util/udevhelper.c b/src/util/udevhelper.c
new file mode 100644
index 0000000..e44e6f6
--- /dev/null
+++ b/src/util/udevhelper.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Author: Michal Privoznik <mprivozn(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "configmake.h"
+#include "viralloc.h"
+#include "virgettext.h"
+#include "virobject.h"
+#include "virstring.h"
+#include "virthread.h"
+#include "virudev.h"
+#include "virutil.h"
+
+#define VIR_FROM_THIS VIR_FROM_SECURITY
+
+
+static void
+usage(const char *progname)
+{
+ fprintf(stderr,
+ _("Usage: %s [device]\n"
+ "\n"
+ "This program is intended to be run from udev to\n"
+ "maintain proper security labels on devices used by\n"
+ "domains managed by libvirt.\n"
+ "\n"
+ "For given device (either passed as the only\n"
+ "command line argument or set by DEVNODE environment\n"
+ "variable) all the security labels are printed onto\n"
+ "standard output.\n"), progname);
+}
+
+
+static int
+printLabels(const char *device)
+{
+ char *filename = NULL;
+ virUdevMgrPtr mgr = NULL;
+ int ret = -1;
+ virSecurityDeviceLabelDefPtr *labels = NULL;
+ size_t i, nlabels = 0;
+ const char *dacLabel = NULL;
+ const char *seLabel = NULL;
+
+ if (virAsprintf(&filename,
+ "%s/run/libvirt/qemu/devices.udev", LOCALSTATEDIR) < 0)
+ goto cleanup;
+
+ if (!(mgr = virUdevMgrNewFromFile(filename)))
+ goto cleanup;
+
+ if (virUdevMgrLookupLabels(mgr, device, &labels, &nlabels) < 0)
+ goto cleanup;
+
+ if (!labels) {
+ /* Device not found in our DB. Claim success. */
+ ret = 0;
+ goto cleanup;
+ }
+
+ for (i = 0; i < nlabels; i++) {
+ virSecurityDeviceLabelDefPtr tmp = labels[i];
+
+ if (STREQ(tmp->model, "dac"))
+ dacLabel = tmp->label;
+ else if (STREQ(tmp->model, "selinux"))
+ seLabel = tmp->label;
+ }
+
+ if (dacLabel)
+ printf("%s", dacLabel);
+ if (seLabel)
+ printf(" %s", seLabel);
+ printf("\n");
+
+ ret = 0;
+ cleanup:
+ for (i = 0; i < nlabels; i++)
+ virSecurityDeviceLabelDefFree(labels[i]);
+ VIR_FREE(labels);
+ virObjectUnref(mgr);
+ return ret;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ const char *device = NULL;
+ int ret = EXIT_FAILURE;
+
+ if (virGettextInitialize() < 0 ||
+ virThreadInitialize() < 0 ||
+ virErrorInitialize() < 0) {
+ fprintf(stderr, _("%s: initialization failed\n"), argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (argc > 1)
+ device = argv[1];
+ if (!device)
+ device = virGetEnvBlockSUID("DEVNODE");
+ if (!device || STREQ(device, "-h") || STREQ(device, "--help")) {
+ usage(argv[0]);
+ if (device)
+ ret = EXIT_SUCCESS;
+ goto cleanup;
+ }
+
+ if (printLabels(device) < 0)
+ goto cleanup;
+
+ ret = EXIT_SUCCESS;
+ cleanup:
+ return ret;
+}
--
2.8.4