[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen stable-4.11] tools/ocaml/xenstored: delete watch from trie too when resetting watches

commit 1e870589fac5717761a44d9da52e95decd45c4ae
Author:     Edwin Török <edvin.torok@xxxxxxxxxx>
AuthorDate: Tue Dec 15 14:38:42 2020 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Dec 15 14:38:42 2020 +0100

    tools/ocaml/xenstored: delete watch from trie too when resetting watches
    c/s f8c72b526129 "oxenstored: implement XS_RESET_WATCHES" from Xen 4.6
    introduced reset watches support in oxenstored by mirroring the change
    in cxenstored.
    However the OCaml version has some additional data structures to
    optimize watch firing, and just resetting the watches in one of the data
    structures creates a security bug where a malicious guest kernel can
    exceed its watch quota, driving oxenstored into OOM:
     * create watches
     * reset watches (this still keeps the watches lingering in another data
       structure, using memory)
     * create some more watches
     * loop until oxenstored dies
    The guest kernel doesn't necessarily have to be malicious to trigger
     * if control/platform-feature-xs_reset_watches is set
     * the guest kexecs (e.g. because it crashes)
     * on boot more watches are set up
     * this will slowly "leak" memory for watches in oxenstored, driving it
       towards OOM.
    This is XSA-330.
    Fixes: f8c72b526129 ("oxenstored: implement XS_RESET_WATCHES")
    Signed-off-by: Edwin Török <edvin.torok@xxxxxxxxxx>
    Acked-by: Christian Lindig <christian.lindig@xxxxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
 tools/ocaml/xenstored/connections.ml | 4 ++++
 tools/ocaml/xenstored/process.ml     | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/ocaml/xenstored/connections.ml 
index 020b875dcd..4e69de1d42 100644
--- a/tools/ocaml/xenstored/connections.ml
+++ b/tools/ocaml/xenstored/connections.ml
@@ -134,6 +134,10 @@ let del_watch cons con path token =
                cons.watches <- Trie.set cons.watches key watches;
+let del_watches cons con =
+       Connection.del_watches con;
+       cons.watches <- Trie.map (del_watches_of_con con) cons.watches
 (* path is absolute *)
 let fire_watches ?oldroot root cons path recurse =
        let key = key_of_path path in
diff --git a/tools/ocaml/xenstored/process.ml b/tools/ocaml/xenstored/process.ml
index 6a998f8764..12ad66fce6 100644
--- a/tools/ocaml/xenstored/process.ml
+++ b/tools/ocaml/xenstored/process.ml
@@ -179,8 +179,8 @@ let do_isintroduced con _t domains _cons data =
        if domid = Define.domid_self || Domains.exist domains domid then 
"T\000" else "F\000"
 (* only in xen >= 4.2 *)
-let do_reset_watches con t domains cons data =
-  Connection.del_watches con;
+let do_reset_watches con _t _domains cons _data =
+  Connections.del_watches cons con;
   Connection.del_transactions con
 (* only in >= xen3.3                                                           
generated by git-patchbot for /home/xen/git/xen.git#stable-4.11



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.