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@xxxxxxxxxx> --- 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 66df1f7..60dc16b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2584,6 +2584,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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list