]> xenbits.xensource.com Git - xen.git/commitdiff
tools/ocaml/xenstored: introduce permissions for special watches
authorEdwin Török <edvin.torok@citrix.com>
Tue, 15 Dec 2020 13:29:14 +0000 (14:29 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 15 Dec 2020 13:29:14 +0000 (14:29 +0100)
The special watches "@introduceDomain" and "@releaseDomain" should be
allowed for privileged callers only, as they allow to gain information
about presence of other guests on the host. So send watch events for
those watches via privileged connections only.

Start to address this by treating the special watches as regular nodes
in the tree, which gives them normal semantics for permissions.  A later
change will restrict the handling, so that they can't be listed, etc.

This is part of XSA-115.

Signed-off-by: Edwin Török <edvin.torok@citrix.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
tools/ocaml/xenstored/process.ml
tools/ocaml/xenstored/store.ml
tools/ocaml/xenstored/utils.ml
tools/ocaml/xenstored/xenstored.ml

index 56aea4ce30c8ffe8ceeed01c84236470f8b5dcda..e42460f60a58bcddafd8ad3d41511eed078bec9b 100644 (file)
@@ -414,7 +414,7 @@ let do_introduce con _t domains cons data =
                else try
                        let ndom = Domains.create domains domid mfn port in
                        Connections.add_domain cons ndom;
-                       Connections.fire_spec_watches cons "@introduceDomain";
+                       Connections.fire_spec_watches cons Store.Path.introduce_domain;
                        ndom
                with _ -> raise Invalid_Cmd_Args
        in
@@ -433,7 +433,7 @@ let do_release con _t domains cons data =
        Domains.del domains domid;
        Connections.del_domain cons domid;
        if fire_spec_watches
-       then Connections.fire_spec_watches cons "@releaseDomain"
+       then Connections.fire_spec_watches cons Store.Path.release_domain
        else raise Invalid_Cmd_Args
 
 let do_resume con _t domains _cons data =
index 92b6289b5ec57e22821a449cf36ae4cf1d4da9ee..52b88b3ee1a971795e57a45b3129f61ce230f6f1 100644 (file)
@@ -214,6 +214,11 @@ let rec lookup node path fct =
 
 let apply rnode path fct =
        lookup rnode path fct
+
+let introduce_domain = "@introduceDomain"
+let release_domain = "@releaseDomain"
+let specials = List.map of_string [ introduce_domain; release_domain ]
+
 end
 
 (* The Store.t type *)
index b252db799b8f0e94199e1408e26d3345877dea3f..e8c9fe4e94c608fd1122b6621c58a9c18e2a7102 100644 (file)
@@ -88,19 +88,17 @@ let read_file_single_integer filename =
        Unix.close fd;
        int_of_string (Bytes.sub_string buf 0 sz)
 
-let path_complete path connection_path =
-       if String.get path 0 <> '/' then
-               connection_path ^ path
-       else
-               path
-
+(* @path may be guest data and needs its length validating.  @connection_path
+ * is generated locally in xenstored and always of the form "/local/domain/$N/" *)
 let path_validate path connection_path =
-       if String.length path = 0 || String.length path > 1024 then
-               raise Define.Invalid_path
-       else
-               let cpath = path_complete path connection_path in
-               if String.get cpath 0 <> '/' then
-                       raise Define.Invalid_path
-               else
-                       cpath
+       let len = String.length path in
+
+       if len = 0 || len > 1024 then raise Define.Invalid_path;
+
+       let abs_path =
+               match String.get path 0 with
+               | '/' | '@' -> path
+               | _   -> connection_path ^ path
+       in
 
+       abs_path
index a4466c5b5ca9d955564e29128ec6c62367a1476a..894e5a709d5b4a2f1f1c3a6923ca71d59bcd9b3f 100644 (file)
@@ -287,6 +287,8 @@ let _ =
        let quit = ref false in
 
        Logging.init_xenstored_log();
+       List.iter (fun path ->
+               Store.write store Perms.Connection.full_rights path "") Store.Path.specials;
 
        let filename = Paths.xen_run_stored ^ "/db" in
        if cf.restart && Sys.file_exists filename then (
@@ -339,7 +341,7 @@ let _ =
                                        let (notify, deaddom) = Domains.cleanup domains in
                                        List.iter (Connections.del_domain cons) deaddom;
                                        if deaddom <> [] || notify then
-                                               Connections.fire_spec_watches cons "@releaseDomain"
+                                               Connections.fire_spec_watches cons Store.Path.release_domain
                                )
                                else
                                        let c = Connections.find_domain_by_port cons port in