From e6e9aa1b51ad96544f5cd6aa898ff5012c4975a8 Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Mon, 23 Jan 2023 16:21:16 +0000 Subject: [PATCH] xenstore perms WIP just store perms as a GList of strings. No actual checks as yet. Signed-off-by: Paul Durrant --- hw/i386/kvm/xen_xenstore.c | 2 +- hw/i386/kvm/xenstore_impl.c | 156 +++++++++++++++++++++++++++++++----- hw/i386/kvm/xenstore_impl.h | 2 +- tests/unit/test-xs-node.c | 8 +- 4 files changed, 143 insertions(+), 25 deletions(-) diff --git a/hw/i386/kvm/xen_xenstore.c b/hw/i386/kvm/xen_xenstore.c index 369ca2a021..57bb5fcbc9 100644 --- a/hw/i386/kvm/xen_xenstore.c +++ b/hw/i386/kvm/xen_xenstore.c @@ -101,7 +101,7 @@ static void xen_xenstore_realize(DeviceState *dev, Error **errp) aio_set_fd_handler(qemu_get_aio_context(), xen_be_evtchn_fd(s->eh), true, xen_xenstore_event, NULL, NULL, NULL, s); - s->impl = xs_impl_create(); + s->impl = xs_impl_create(xen_domid); xen_xenstore_ops = &emu_xenstore_backend_ops; } diff --git a/hw/i386/kvm/xenstore_impl.c b/hw/i386/kvm/xenstore_impl.c index 1d614c8794..a344821eae 100644 --- a/hw/i386/kvm/xenstore_impl.c +++ b/hw/i386/kvm/xenstore_impl.c @@ -12,6 +12,8 @@ #include "qemu/osdep.h" #include "qom/object.h" +#include "hw/xen/xen.h" + #include "xen_xenstore.h" #include "xenstore_impl.h" #include "include/hw/xen/xen_backend_ops.h" @@ -24,6 +26,7 @@ OBJECT_DECLARE_TYPE(XsNode, XsNodeClass, XS_NODE) typedef struct XsNode { Object obj; GByteArray *content; + GList *perms; GHashTable *children; bool deleted_in_tx; bool modified_in_tx; @@ -71,6 +74,9 @@ static void xs_node_finalize(Object *obj) if (n->content) { g_byte_array_unref(n->content); } + if (n->perms) { + g_list_free_full(n->perms, g_free); + } if (n->children) { g_hash_table_unref(n->children); } @@ -111,8 +117,27 @@ static inline void xs_node_unref(XsNode *n) object_unref(OBJECT(n)); } -/* For copying from one hash table to another using g_hash_table_foreach() */ -static void do_insert(gpointer key, gpointer value, gpointer user_data) +static gpointer do_perm_copy(gconstpointer src, gpointer user_data) +{ + return g_strdup(src); +} + +static XsNode *xs_node_create(const char *name, GList *perms) +{ + XsNode *n = xs_node_new(); + +#ifdef XS_NODE_UNIT_TEST + if (name) + n->name = g_strdup(name); +#endif + + n->perms = g_list_copy_deep(perms, do_perm_copy, NULL); + + return n; +} + +/* For copying a child from one hash table to another using g_hash_table_foreach() */ +static void do_child_insert(gpointer key, gpointer value, gpointer user_data) { g_hash_table_insert(user_data, g_strdup(key), object_ref(value)); } @@ -127,12 +152,16 @@ static XsNode *xs_node_copy(XsNode *old) } #endif + assert(old); if (old->children) { n->children = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, object_unref); - g_hash_table_foreach(old->children, do_insert, n->children); + g_hash_table_foreach(old->children, do_child_insert, n->children); } - if (old && old->content) { + if (old->perms) { + n->perms = g_list_copy_deep(old->perms, do_perm_copy, NULL); + } + if (old->content) { n->content = g_byte_array_ref(old->content); } return n; @@ -311,6 +340,9 @@ static XsNode *xs_node_copy_deleted(XsNode *old) object_unref); g_hash_table_foreach(old->children, copy_deleted_recurse, n->children); } + if (old->perms) { + n->perms = g_list_copy_deep(old->perms, do_perm_copy, NULL); + } n->deleted_in_tx = true; /* If it gets resurrected we only fire a watch if it lost its content */ if (old->content) { @@ -341,6 +373,38 @@ static int xs_node_rm(XsNode **n, struct walk_op *op) return 0; } +static int xs_node_get_perms(XsNode **n, struct walk_op *op) +{ + GList **perms = op->op_opaque; + + assert(op->inplace); + assert(*n); + + *perms = g_list_copy_deep((*n)->perms, do_perm_copy, NULL); + return 0; +} + +static int xs_node_set_perms(XsNode **n, struct walk_op *op) +{ + GList *perms = op->op_opaque; + + /* We *are* the node to be written. Either this or a copy. */ + if (!op->inplace) { + XsNode *old = *n; + *n = xs_node_copy(old); + xs_node_unref(old); + } + + if ((*n)->perms) { + g_list_free_full((*n)->perms, g_free); + } + (*n)->perms = g_list_copy_deep(perms, do_perm_copy, NULL); + if (op->tx_id != XBT_NULL) { + (*n)->modified_in_tx = true; + } + return 0; +} + /* * Passed a full reference in *n which it may free if it needs to COW. * @@ -415,7 +479,7 @@ static int xs_node_walk(XsNode **n, struct walk_op *op) stole_child = true; } } else if (op->create_dirs) { - child = xs_node_new(); + child = xs_node_create(child_name, old->perms); /* If we're creating a new child, we can clearly modify it (and its * children) in place from here on down. */ op->inplace = true; @@ -787,20 +851,72 @@ int xs_impl_rm(XenstoreImplState *s, unsigned int dom_id, unsigned int tx_id, int xs_impl_get_perms(XenstoreImplState *s, unsigned int dom_id, unsigned int tx_id, const char *path, GList **perms) { - /* - * The perms are (char *) in the wire format to be - * freed by the caller. - */ - return ENOSYS; + struct walk_op op; + XsNode **n; + int ret; + + ret = init_walk_op(s, &op, tx_id, dom_id, path, &n); + if (ret) { + return ret; + } + op.op_fn = xs_node_get_perms; + op.op_opaque = perms; + return xs_node_walk(n, &op); +} + +static void is_valid_perm(gpointer data, gpointer user_data) +{ + char *perm = data; + bool *valid = user_data; + char letter; + unsigned int dom_id; + + if (!*valid) + return; + + if (sscanf(perm, "%c%u", &letter, &dom_id) != 2) { + *valid = false; + return; + } + + switch (letter) { + case 'n': + case 'r': + case 'w': + case 'b': + break; + + default: + *valid = false; + break; + } } int xs_impl_set_perms(XenstoreImplState *s, unsigned int dom_id, unsigned int tx_id, const char *path, GList *perms) { - /* - * The perms are (const char *) in the wire format. - */ - return ENOSYS; + struct walk_op op; + XsNode **n; + bool valid = true; + int ret; + + if (!g_list_length(perms)) { + return EINVAL; + } + + g_list_foreach(perms, is_valid_perm, &valid); + if (!valid) { + return EINVAL; + } + + ret = init_walk_op(s, &op, tx_id, dom_id, path, &n); + if (ret) { + return ret; + } + op.op_fn = xs_node_set_perms; + op.op_opaque = perms; + op.mutating = true; + return xs_node_walk(n, &op); } int xs_impl_watch(XenstoreImplState *s, unsigned int dom_id, const char *path, @@ -994,17 +1110,19 @@ static void xs_tx_free(void *_tx) g_free(tx); } -XenstoreImplState *xs_impl_create(void) +XenstoreImplState *xs_impl_create(unsigned int dom_id) { XenstoreImplState *s = g_new0(XenstoreImplState, 1); + GList *perms = NULL; s->watches = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); s->transactions = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, xs_tx_free); - s->root = xs_node_new(); -#ifdef XS_NODE_UNIT_TEST - s->root->name = g_strdup("/"); -#endif + + perms = g_list_append(perms, xs_perm_as_string(XS_PERM_NONE, dom_id)); + s->root = xs_node_create("/", perms); + g_list_free_full(perms, g_free); + return s; } diff --git a/hw/i386/kvm/xenstore_impl.h b/hw/i386/kvm/xenstore_impl.h index ae3da65459..92152c2753 100644 --- a/hw/i386/kvm/xenstore_impl.h +++ b/hw/i386/kvm/xenstore_impl.h @@ -16,7 +16,7 @@ typedef struct XenstoreImplState XenstoreImplState; -XenstoreImplState *xs_impl_create(void); +XenstoreImplState *xs_impl_create(unsigned int dom_id); char *xs_perm_as_string(unsigned int perm, unsigned int domid); diff --git a/tests/unit/test-xs-node.c b/tests/unit/test-xs-node.c index ea543c8e1d..879adebc29 100644 --- a/tests/unit/test-xs-node.c +++ b/tests/unit/test-xs-node.c @@ -61,7 +61,7 @@ static void watch_cb(void *_str, const char *path, const char *token) static void test_xs_node_simple(void) { - XenstoreImplState *s = xs_impl_create(); + XenstoreImplState *s = xs_impl_create(DOMID_GUEST); GString *guest_watches = g_string_new(NULL); GString *qemu_watches = g_string_new(NULL); GList *items = NULL; @@ -222,7 +222,7 @@ static void test_xs_node_simple(void) static void do_test_xs_node_tx(bool fail, bool commit) { - XenstoreImplState *s = xs_impl_create(); + XenstoreImplState *s = xs_impl_create(DOMID_GUEST); GString *watches = g_string_new(NULL); GByteArray *data = g_byte_array_new(); unsigned int tx_id = XBT_NULL; @@ -322,7 +322,7 @@ static void test_xs_node_tx_succeed(void) static void test_xs_node_tx_rm(void) { - XenstoreImplState *s = xs_impl_create(); + XenstoreImplState *s = xs_impl_create(DOMID_GUEST); GString *watches = g_string_new(NULL); GByteArray *data = g_byte_array_new(); unsigned int tx_id = XBT_NULL; @@ -385,7 +385,7 @@ static void test_xs_node_tx_rm(void) static void test_xs_node_tx_resurrect(void) { - XenstoreImplState *s = xs_impl_create(); + XenstoreImplState *s = xs_impl_create(DOMID_GUEST); GString *watches = g_string_new(NULL); GByteArray *data = g_byte_array_new(); unsigned int tx_id = XBT_NULL; -- 2.39.5