[libvirt] [PATCH v2 16/19] virudevtest: Introduce device filtering

Michal Privoznik mprivozn at redhat.com
Thu Nov 3 12:19:06 UTC 2016


In some cases callers might want to filter what devices are
stored in this module (esp. when used in combination with udev
who cares about nothing but "/dev/" prefixed paths).

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/libvirt_private.syms |  1 +
 src/util/virudev.c       | 25 ++++++++++++++++++++++
 src/util/virudev.h       | 13 ++++++++++++
 tests/virudevtest.c      | 54 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c6d17c4..2a1f96e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2588,6 +2588,7 @@ virUdevMgrNew;
 virUdevMgrNewFromFile;
 virUdevMgrNewFromStr;
 virUdevMgrRemoveAllLabels;
+virUdevMgrSetFilter;
 
 
 # util/viruri.h
diff --git a/src/util/virudev.c b/src/util/virudev.c
index 9940f5f..c17682c 100644
--- a/src/util/virudev.c
+++ b/src/util/virudev.c
@@ -36,6 +36,9 @@
 struct _virUdevMgr {
     virObjectLockable parent;
     virHashTablePtr labels;
+
+    virUdevMgrFilter filter;
+    void *opaque;
 };
 
 struct _udevSeclabel {
@@ -274,6 +277,17 @@ virUdevMgrAddLabel(virUdevMgrPtr mgr,
 
     virObjectLock(mgr);
 
+    if (mgr->filter) {
+        int rc = mgr->filter(device, seclabel, mgr->opaque);
+        if (rc < 0)
+            goto cleanup;
+        if (rc == 0) {
+            /* Claim success. */
+            ret = 0;
+            goto cleanup;
+        }
+    }
+
     if ((list = virHashLookup(mgr->labels, device))) {
         virSecurityDeviceLabelDefPtr entry = udevSeclabelFindByModel(list, seclabel->model);
 
@@ -561,3 +575,14 @@ virUdevMgrNewFromFile(const char *filename)
     VIR_FREE(state);
     return NULL;
 }
+
+void
+virUdevMgrSetFilter(virUdevMgrPtr mgr,
+                    virUdevMgrFilter filter,
+                    void *opaque)
+{
+    virObjectLock(mgr);
+    mgr->filter = filter;
+    mgr->opaque = opaque;
+    virObjectUnlock(mgr);
+}
diff --git a/src/util/virudev.h b/src/util/virudev.h
index 4e286bb..2f035e3 100644
--- a/src/util/virudev.h
+++ b/src/util/virudev.h
@@ -28,6 +28,15 @@
 typedef struct _virUdevMgr virUdevMgr;
 typedef virUdevMgr *virUdevMgrPtr;
 
+/* Filter some devices out in virUdevMgrAddLabel.
+ * Return 0 to NOT record label for device,
+ *        1 to record the label for device,
+ *       -1 on error.
+ */
+typedef int (*virUdevMgrFilter)(const char *device,
+                                const virSecurityDeviceLabelDef *seclabel,
+                                void *opaque);
+
 virUdevMgrPtr virUdevMgrNew(void);
 virUdevMgrPtr virUdevMgrNewFromStr(const char *str);
 virUdevMgrPtr virUdevMgrNewFromFile(const char *filename);
@@ -47,4 +56,8 @@ char *virUdevMgrDumpStr(virUdevMgrPtr mgr);
 int virUdevMgrDumpFile(virUdevMgrPtr mgr,
                        const char *filename);
 
+void virUdevMgrSetFilter(virUdevMgrPtr mgr,
+                         virUdevMgrFilter filter,
+                         void *opaque);
+
 #endif
diff --git a/tests/virudevtest.c b/tests/virudevtest.c
index 36a9077..cd5d136 100644
--- a/tests/virudevtest.c
+++ b/tests/virudevtest.c
@@ -29,6 +29,7 @@
 struct testUdevData {
     const char *file;
     const char *const *labels;
+    virUdevMgrFilter filter;
 };
 
 
@@ -49,6 +50,8 @@ testDump(const void *opaque)
     if (!(mgr = virUdevMgrNew()))
         goto cleanup;
 
+    virUdevMgrSetFilter(mgr, data->filter, NULL);
+
     tmp = data->labels;
     while (*tmp) {
         const char *device;
@@ -194,6 +197,25 @@ testLookup(const void *opaque)
 
 
 static int
+filterAll(const char *device ATTRIBUTE_UNUSED,
+          const virSecurityDeviceLabelDef *seclabel ATTRIBUTE_UNUSED,
+          void *opaque ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static int
+filterAllowSda(const char *device,
+               const virSecurityDeviceLabelDef *seclabel ATTRIBUTE_UNUSED,
+               void *opaque ATTRIBUTE_UNUSED)
+{
+    return STRPREFIX(device, "/dev/sda") ? 1 : 0;
+}
+
+
+
+static int
 mymain(void)
 {
     int ret = 0;
@@ -202,7 +224,7 @@ mymain(void)
     do {                                                            \
         const char *labels[] = {__VA_ARGS__, NULL};                 \
         struct testUdevData data = {                                \
-            .file = filename, .labels = labels,                     \
+            .file = filename, .labels = labels, .filter = NULL,     \
         };                                                          \
         if (virTestRun("Dump " filename, testDump, &data) < 0)      \
             ret = -1;                                               \
@@ -227,6 +249,17 @@ mymain(void)
             ret = -1;                                               \
     } while (0)
 
+#define DO_TEST_FILTER(filename, fltr, ...)                         \
+    do {                                                            \
+        const char *labels[] = {__VA_ARGS__, NULL};                 \
+        struct testUdevData data = {                                \
+            .file = filename, .labels = labels, .filter = fltr,     \
+        };                                                          \
+        if (virTestRun("Filter " filename, testDump, &data) < 0)    \
+            ret = -1;                                               \
+    } while (0)
+
+
     DO_TEST_DUMP("empty", NULL);
     DO_TEST_DUMP("simple-selinux",
                  "/dev/sda", "selinux", "someSELinuxLabel");
@@ -254,6 +287,25 @@ mymain(void)
                    "/dev/sdb", "dac",     "otherDACLabel",
                    "/dev/sdb", "selinux", "otherSELinuxLabel");
 
+    DO_TEST_FILTER("empty", filterAll,
+                   "/dev/sda", "dac",     "someDACLabel",
+                   "/dev/sda", "selinux", "someSELinuxLabel",
+                   "/dev/sdb", "dac",     "otherDACLabel",
+                   "/dev/sdb", "selinux", "otherSELinuxLabel");
+    DO_TEST_FILTER("simple-selinux", filterAllowSda,
+                   "/dev/sda", "selinux", "someSELinuxLabel",
+                   "/dev/sdb", "dac",     "otherDACLabel",
+                   "/dev/sdb", "selinux", "otherSELinuxLabel");
+    DO_TEST_FILTER("simple-dac", filterAllowSda,
+                   "/dev/sda", "dac", "someDACLabel",
+                   "/dev/sdb", "dac",     "otherDACLabel",
+                   "/dev/sdb", "selinux", "otherSELinuxLabel");
+    DO_TEST_FILTER("complex", NULL,
+                   "/dev/sda", "dac",     "someDACLabel",
+                   "/dev/sda", "selinux", "someSELinuxLabel",
+                   "/dev/sdb", "dac",     "otherDACLabel",
+                   "/dev/sdb", "selinux", "otherSELinuxLabel");
+
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
-- 
2.8.4




More information about the libvir-list mailing list