tools/ocaml/xenstored: Fix quota bypass on domain shutdown

XSA-322 fixed a domid reuse vulnerability by assigning Dom0 as the owner of
any nodes left after a domain is shutdown (e.g. outside its /local/domain/N
tree).

However Dom0 has no quota on purpose, so this opened up another potential
attack vector. Avoid it by deleting these nodes instead of assigning them to
Dom0.

This is part of XSA-419 / CVE-2022-42323.

Fixes: c46eff9212 ("tools/ocaml/xenstored: clean up permissions for dead domains")
Signed-off-by: Edwin Török <edvin.torok@citrix.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
This commit is contained in:
Edwin Török authored and Andrew Cooper committed 2022-11-01 13:05:44 +00:00
1 parent d084d2c6df
commit db471408ed
2 files changed
+22 -10

No files matched your search

+1 -2
View File
@@ -64,8 +64,7 @@ let get_owner perm = perm.owner
* *)
let remove_domid ~domid perm =
let acl = List.filter (fun (acl_domid, _) -> acl_domid <> domid) perm.acl in
let owner = if perm.owner = domid then 0 else perm.owner in
{ perm with acl; owner }
if perm.owner = domid then None else Some { perm with acl; owner = perm.owner }
let default0 = create 0 NONE []
+21 -8
View File
@@ -87,10 +87,21 @@ let check_owner node connection =
let rec recurse fct node = fct node; SymbolMap.iter (fun _ -> recurse fct) node.children
(** [recurse_map f tree] applies [f] on each node in the tree recursively *)
let recurse_map f =
(** [recurse_filter_map f tree] applies [f] on each node in the tree recursively,
possibly removing some nodes.
Note that the nodes removed this way won't generate watch events.
*)
let recurse_filter_map f =
let invalid = -1 in
let is_valid _ node = node.perms.owner <> invalid in
let rec walk node =
f { node with children = SymbolMap.map walk node.children }
(* Map.filter_map is Ocaml 4.11+ only *)
let node =
{ node with children =
SymbolMap.map walk node.children |> SymbolMap.filter is_valid } in
match f node with
| Some keep -> keep
| None -> { node with perms = {node.perms with owner = invalid } }
in
walk
@@ -444,11 +455,13 @@ let setperms store perm path nperms =
let reset_permissions store domid =
Logging.info "store|node" "Cleaning up xenstore ACLs for domid %d" domid;
store.root <- Node.recurse_map (fun node ->
let perms = Perms.Node.remove_domid ~domid node.perms in
if perms <> node.perms then
Logging.debug "store|node" "Changed permissions for node %s" (Node.get_name node);
{ node with perms }
store.root <- Node.recurse_filter_map (fun node ->
match Perms.Node.remove_domid ~domid node.perms with
| None -> None
| Some perms ->
if perms <> node.perms then
Logging.debug "store|node" "Changed permissions for node %s" (Node.get_name node);
Some { node with perms }
) store.root
type ops = {
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.