Now that we are able to store security labels for devices, next step is to flush them into a file. For more convenience I've chosen JSON format (as we have all the APIs needed for processing the format). Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- po/POTFILES.in | 1 + src/libvirt_private.syms | 2 + src/util/virudev.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virudev.h | 5 ++ 4 files changed, 165 insertions(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 1469240..dabc612 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -248,6 +248,7 @@ src/util/virthreadpool.c src/util/virtime.c src/util/virtpm.c src/util/virtypedparam.c +src/util/virudev.c src/util/viruri.c src/util/virusb.c src/util/virutil.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 073b00f..ca64c80 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2579,6 +2579,8 @@ virTypedParamsValidate; # util/virudev.h virUdevMgrAddLabel; +virUdevMgrDumpFile; +virUdevMgrDumpStr; virUdevMgrNew; virUdevMgrRemoveAllLabels; diff --git a/src/util/virudev.c b/src/util/virudev.c index f4799e7..7f52149 100644 --- a/src/util/virudev.c +++ b/src/util/virudev.c @@ -24,7 +24,9 @@ #include "internal.h" #include "viralloc.h" +#include "virfile.h" #include "virhash.h" +#include "virjson.h" #include "virobject.h" #include "virudev.h" @@ -112,6 +114,68 @@ udevSeclabelUpdate(udevSeclabelPtr list, } +static virJSONValuePtr +udevSeclabelDump(const virSecurityDeviceLabelDef *seclabel) +{ + virJSONValuePtr object; + + if (!(object = virJSONValueNewObject()) || + virJSONValueObjectAppendString(object, "model", seclabel->model) < 0 || + virJSONValueObjectAppendString(object, "label", seclabel->label) < 0) + goto error; + + return object; + + error: + virJSONValueFree(object); + return NULL; +} + + +static int +udevSeclabelsDump(void *payload, + const void *name, + void *opaque) +{ + udevSeclabelPtr list = payload; + const char *device = name; + virJSONValuePtr seclabels = opaque; + virJSONValuePtr deviceLabels = NULL; + virJSONValuePtr deviceJSON = NULL; + size_t i; + int ret = -1; + + if (!(deviceLabels = virJSONValueNewArray())) + return ret; + + for (i = 0; i < list->nseclabels; i++) { + virJSONValuePtr seclabel = udevSeclabelDump(list->seclabels[i]); + + if (!seclabel || + virJSONValueArrayAppend(deviceLabels, seclabel) < 0) { + virJSONValueFree(seclabel); + goto cleanup; + } + } + + if (!(deviceJSON = virJSONValueNewObject()) || + virJSONValueObjectAppendString(deviceJSON, "device", device) < 0 || + virJSONValueObjectAppend(deviceJSON, "labels", deviceLabels) < 0) + goto cleanup; + deviceLabels = NULL; + + if (virJSONValueArrayAppend(seclabels, deviceJSON) < 0) + goto cleanup; + deviceJSON = NULL; + + ret = 0; + cleanup: + virJSONValueFree(deviceJSON); + virJSONValueFree(deviceLabels); + return ret; +} + + static void virUdevMgrDispose(void *obj) { @@ -202,3 +266,96 @@ virUdevMgrRemoveAllLabels(virUdevMgrPtr mgr, virObjectUnlock(mgr); return ret; } + + +static virJSONValuePtr +virUdevSeclabelDump(virUdevMgrPtr mgr) +{ + virJSONValuePtr seclabels; + + if (!(seclabels = virJSONValueNewArray())) + return NULL; + + if (virHashForEach(mgr->labels, udevSeclabelsDump, seclabels) < 0) { + virJSONValueFree(seclabels); + return NULL; + } + + return seclabels; +} + + +static char * +virUdevMgrDumpInternal(virUdevMgrPtr mgr) +{ + virJSONValuePtr object = NULL; + virJSONValuePtr child = NULL; + char *ret = NULL; + + if (!(object = virJSONValueNewObject())) + goto cleanup; + + if (!(child = virUdevSeclabelDump(mgr))) + goto cleanup; + + if (virJSONValueObjectAppend(object, "labels", child) < 0) { + virJSONValueFree(child); + goto cleanup; + } + + ret = virJSONValueToString(object, true); + cleanup: + virJSONValueFree(object); + return ret; +} + + +char * +virUdevMgrDumpStr(virUdevMgrPtr mgr) +{ + char *ret; + + virObjectLock(mgr); + ret = virUdevMgrDumpInternal(mgr); + virObjectUnlock(mgr); + return ret; +} + + +static int +virUdevMgrRewriter(int fd, void *opaque) +{ + const char *str = opaque; + + return safewrite(fd, str, strlen(str)); +} + + +int +virUdevMgrDumpFile(virUdevMgrPtr mgr, + const char *filename) +{ + int ret = -1; + char *state; + + virObjectLock(mgr); + + if (!(state = virUdevMgrDumpInternal(mgr))) + goto cleanup; + + /* Here we shouldn't use pure virFileWriteStr() as that one is not atomic. + * We can be interrupted in the middle (e.g. due to a context switch) and + * thus leave the file partially written. */ + if (virFileRewrite(filename, 0644, virUdevMgrRewriter, state) < 0) { + virReportSystemError(errno, + _("Unable to save state file %s"), + filename); + goto cleanup; + } + + ret = 0; + cleanup: + virObjectUnlock(mgr); + VIR_FREE(state); + return ret; +} diff --git a/src/util/virudev.h b/src/util/virudev.h index 692b39b..1d5a23e 100644 --- a/src/util/virudev.h +++ b/src/util/virudev.h @@ -36,4 +36,9 @@ int virUdevMgrAddLabel(virUdevMgrPtr mgr, int virUdevMgrRemoveAllLabels(virUdevMgrPtr mgr, const char *device); +char *virUdevMgrDumpStr(virUdevMgrPtr mgr); + +int virUdevMgrDumpFile(virUdevMgrPtr mgr, + const char *filename); + #endif -- 2.8.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list