]> xenbits.xensource.com Git - xen.git/commitdiff
oxenstored: Protect oxenstored from malicious domains.
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 3 Sep 2013 10:55:48 +0000 (11:55 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Tue, 3 Sep 2013 11:03:39 +0000 (12:03 +0100)
add check logic when read from IO ring, and if error happens,
then mark the reading connection as "bad", Unless vm reboot,
oxenstored will not handle message from this connection any more.

xs_ring_stubs.c: add a more strict check on ring reading
connection.ml, domain.ml: add getter and setter for bad flag
process.ml: if exception raised when reading from domain's ring,
            mark this domain as "bad"
xenstored.ml: if a domain is marked as "bad", do not handle it.

Signed-off-by: John Liu <john.liuqiming@huawei.com>
Acked-by: David Scott <dave.scott@eu.citrix.com>
(cherry picked from commit 704302ce9404c73cfb687d31adcf67094ab5bb53)
(cherry picked from commit a978634bee4db6c5e0ceeb66adcc5114f3f9bc48)

Conflicts:
tools/ocaml/xenstored/domain.ml

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
(cherry picked from commit 9f93027afd796a98d7b92898f4ccc772796a4874)

tools/ocaml/libs/xb/xs_ring_stubs.c
tools/ocaml/xenstored/connection.ml
tools/ocaml/xenstored/domain.ml
tools/ocaml/xenstored/process.ml
tools/ocaml/xenstored/xenstored.ml

index 37649df5bf68ef0f36d6a46b52851e0bbff1de07..eddeec35c0ea099bc1e21af5f3608e42421932e1 100644 (file)
@@ -49,6 +49,10 @@ static int xs_ring_read(struct mmap_interface *interface,
        cons = *(volatile uint32*)&intf->req_cons;
        prod = *(volatile uint32*)&intf->req_prod;
        xen_mb();
+
+       if ((prod - cons) > XENSTORE_RING_SIZE)
+           return -1;
+
        if (prod == cons)
                return 0;
        cons = MASK_XENSTORE_IDX(cons);
@@ -98,7 +102,7 @@ CAMLprim value ml_interface_read(value interface, value buffer, value len)
        res = xs_ring_read(GET_C_STRUCT(interface),
                           String_val(buffer), Int_val(len));
        if (res == -1)
-               caml_failwith("huh");
+               caml_failwith("bad connection");
        result = Val_int(res);
        CAMLreturn(result);
 }
index 70cdbbfa9107d3360a8d2330a2f09b5cd5c2826b..c15595b4dae5060e2678cd40e592d63d4beb295f 100644 (file)
@@ -38,6 +38,11 @@ and t = {
        mutable perm: Perms.Connection.t;
 }
 
+let mark_as_bad con =
+       match con.dom with
+       |None -> ()
+       | Some domain -> Domain.mark_as_bad domain
+
 let get_path con =
 Printf.sprintf "/local/domain/%i/" (match con.dom with None -> 0 | Some d -> Domain.get_id d)
 
index 258d172a5fc9e12d822d9ecca11c325807488460..b41b00c658075154599dee14eaa97c9ec1ab1b05 100644 (file)
@@ -26,6 +26,7 @@ type t =
        interface: Mmap.mmap_interface;
        eventchn: Event.t;
        mutable port: int;
+       mutable bad_client: bool;
 }
 
 let get_path dom = "/local/domain/" ^ (sprintf "%u" dom.id)
@@ -34,6 +35,9 @@ let get_interface d = d.interface
 let get_mfn d = d.mfn
 let get_remote_port d = d.remote_port
 
+let is_bad_domain domain = domain.bad_client
+let mark_as_bad domain = domain.bad_client <- true
+
 let dump d chan =
        fprintf chan "dom,%d,%nd,%d\n" d.id d.mfn d.port
 
@@ -56,7 +60,8 @@ let make id mfn remote_port interface eventchn = {
        remote_port = remote_port;
        interface = interface;
        eventchn = eventchn;
-       port = -1
+       port = -1;
+       bad_client = false
 }
 
 let is_dom0 d = d.id = 0
index 1549774d00a3742a289c0114b20e31f0241d9977..bd87646bc630378a969f7890ca0f2404b5ab826f 100644 (file)
@@ -368,7 +368,17 @@ let write_answer_log ~ty ~tid ~con ~data =
        Logging.xb_answer ~ty ~tid ~con:(Connection.get_domstr con) data
 
 let do_input store cons doms con =
-       if Connection.do_input con then (
+       let newpacket =
+               try
+                       Connection.do_input con
+               with Failure exp ->
+                       error "caught exception %s" exp;
+                       error "got a bad client %s" (sprintf "%-8s" (Connection.get_domstr con));
+                       Connection.mark_as_bad con;
+                       false
+       in
+
+       if newpacket then (
                let packet = Connection.pop_in con in
                let tid, rid, ty, data = Xb.Packet.unpack packet in
                (* As we don't log IO, do not call an unnecessary sanitize_data 
index 91cde8deedd448efb01717378058553fef3a730d..d004ad2779b26d5fb0ade72f3736a6fc11a4219d 100644 (file)
@@ -49,9 +49,10 @@ let process_connection_fds store cons domains rset wset =
 
 let process_domains store cons domains =
        let do_io_domain domain =
-               let con = Connections.find_domain cons (Domain.get_id domain) in
-               Process.do_input store cons domains con;
-               Process.do_output store cons domains con in
+               if not (Domain.is_bad_domain domain) then
+                       let con = Connections.find_domain cons (Domain.get_id domain) in
+                               Process.do_input store cons domains con;
+                               Process.do_output store cons domains con in
        Domains.iter domains do_io_domain
 
 let sigusr1_handler store =