]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
xenstore perms WIP
authorPaul Durrant <pdurrant@amazon.com>
Mon, 23 Jan 2023 16:21:16 +0000 (16:21 +0000)
committerPaul Durrant <pdurrant@amazon.com>
Tue, 24 Jan 2023 11:11:24 +0000 (11:11 +0000)
just store perms as a GList of strings. No actual checks as yet.

Signed-off-by: Paul Durrant <pdurrant@amazon.com>
hw/i386/kvm/xen_xenstore.c
hw/i386/kvm/xenstore_impl.c
hw/i386/kvm/xenstore_impl.h
tests/unit/test-xs-node.c

index 369ca2a021e4ee039918970f8bf37c3e398e0268..57bb5fcbc94790c8254873a066af28f90619c2fe 100644 (file)
@@ -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;
 }
 
index 1d614c8794441a3c7865dd76e5aa49f750de5473..a344821eae35180d109993c09df3bdbb37c39707 100644 (file)
@@ -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 <perm-as-string> 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 <perm-as-string> 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;
 }
 
index ae3da654596081d469ca543db3ef88d4d86eb3d5..92152c2753407abbec3d2db7d5549cd8fccdf5f2 100644 (file)
@@ -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);
 
index ea543c8e1da84b048ae2360907edfdba4dd6d823..879adebc2964117334c1284210552748c7b3bfeb 100644 (file)
@@ -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;