]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
add permissions checks xenfv2
authorPaul Durrant <pdurrant@amazon.com>
Tue, 24 Jan 2023 13:17:22 +0000 (13:17 +0000)
committerPaul Durrant <pdurrant@amazon.com>
Tue, 24 Jan 2023 13:17:22 +0000 (13:17 +0000)
Signed-off-by: Paul Durrant <pdurrant@amazon.com>
hw/i386/kvm/xenstore_impl.c

index 5e8ea12ae56d1330eab7dd5d90d15c56412ea1d1..cecf3839d47f70ebf909d9b2f5a8520d841b0440 100644 (file)
@@ -405,6 +405,49 @@ static int xs_node_set_perms(XsNode **n, struct walk_op *op)
     return 0;
 }
 
+static void parse_perm(const char *perm, char *letter, unsigned int *dom_id)
+{
+    unsigned int n = sscanf(perm, "%c%u", letter, dom_id);
+
+    assert(n == 2);
+}
+
+static bool can_access(unsigned int dom_id, GList *perms, const char *letters)
+{
+    unsigned int i, n;
+    char perm_letter;
+    unsigned int perm_dom_id;
+    bool access;
+
+    if (dom_id == 0)
+        return true;
+
+    n = g_list_length(perms);
+    assert(n >= 1);
+
+    /*
+     * The dom_id of the first perm is the owner, and the owner always has
+     * read-write access.
+     */
+    parse_perm(g_list_nth_data(perms, 0), &perm_letter, &perm_dom_id);
+    if (dom_id == perm_dom_id)
+        return true;
+
+    /*
+     * The letter of the first perm specified the default access for all other
+     * domains.
+     */
+    access = !!strchr(letters, perm_letter);
+    for (i = 1; i < n; i++) {
+        parse_perm(g_list_nth_data(perms, i), &perm_letter, &perm_dom_id);
+        if (dom_id != perm_dom_id)
+            continue;
+        access = !!strchr(letters, perm_letter);
+    }
+        
+    return access;
+}
+
 /*
  * Passed a full reference in *n which it may free if it needs to COW.
  *
@@ -446,6 +489,11 @@ static int xs_node_walk(XsNode **n, struct walk_op *op)
     }
 
     if (!child_name) {
+        const char *letters = op->mutating ? "wb" : "rb";
+
+        if (!can_access(op->dom_id, old->perms, letters))
+            return EACCES;
+        
         /* This is the actual node on which the operation shall be performed */
         err = op->op_fn(n, op);
         if (!err) {
@@ -479,6 +527,11 @@ static int xs_node_walk(XsNode **n, struct walk_op *op)
             stole_child = true;
         }
     } else if (op->create_dirs) {
+        assert(op->mutating);
+
+        if (!can_access(op->dom_id, old->perms, "wb"))
+            return EACCES;
+        
         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. */