[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] tools/ocaml: oxenstored: Be more paranoid about ring reading
# HG changeset patch # User Ian Jackson <ian.jackson@xxxxxxxxxxxxx> # Date 1360246904 0 # Node ID 2c0fd406f02cabed45a09f7afd3b09af271adfc3 # Parent 6c1b12c884b4521a940e079c8dfebc5d8e88d2e9 tools/ocaml: oxenstored: Be more paranoid about ring reading oxenstored makes use of the OCaml Xenbus bindings, in which the function xs_ring_read in tools/ocaml/libs/xb/xs_ring_stubs.c is used to read from the shared memory Xenstore ring. This function does not correctly handle all possible (prod, cons) states when MASK_XENSTORE_IDX(prod) > MASK_XENSTORE_IDX(cons). The root cause is the use of the unmasked values of prod and cons to calculate to_read. If prod is set to an out-of-range value, the ring peer can cause to_read to be too large or even negative. This allows the ring peer to force oxenstored to read and write out of range for the buffers leading to a crash or possibly to privilege escalation. Correct this by masking the values of cons and prod at the start, so we only deal with masked values. This makes the logic simpler, as semantically inappropriate values of the upper bits of the ring pointers are simply ignored. The same vulnerability does not exist in the ring writer because the only use made of the unmasked value is the check which prevents the prod pointer overtaking the cons pointer. A ring peer which defeats this check will suffer only lost data. However, additionally, precautions need to be taken to ensure that req_cons and req_prod are only read once in each function. Without the use of volatile or some asm construct, the compiler can "prove" that req_cons and req_prod do not change unexpectedly and is permitted to "amplify" the read of (say) req_cons into two reads at different times, giving two different values for use as cons, and then use the two sources of cons interchangeably. (The use of xen_mb() does not forbid this.) Therefore do the reads of req_cons and req_prod through a volatile pointer in both xs_ring_read and xs_ring_write. This is currently believed to be a theoretical vulnerability as we are not aware of any compilers which amplify reads in this way. This is a security issue, part of XSA-38 / CVE-2013-0215. Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Tested-by: Matthew Daley <mattjd@xxxxxxxxx> Committed-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- diff -r 6c1b12c884b4 -r 2c0fd406f02c tools/ocaml/libs/xb/xs_ring_stubs.c --- a/tools/ocaml/libs/xb/xs_ring_stubs.c Tue Feb 05 15:47:41 2013 +0000 +++ b/tools/ocaml/libs/xb/xs_ring_stubs.c Thu Feb 07 14:21:44 2013 +0000 @@ -39,21 +39,23 @@ static int xs_ring_read(struct mmap_inte char *buffer, int len) { struct xenstore_domain_interface *intf = interface->addr; - XENSTORE_RING_IDX cons, prod; + XENSTORE_RING_IDX cons, prod; /* offsets only */ int to_read; - cons = intf->req_cons; - prod = intf->req_prod; + cons = *(volatile uint32*)&intf->req_cons; + prod = *(volatile uint32*)&intf->req_prod; xen_mb(); + cons = MASK_XENSTORE_IDX(cons); + prod = MASK_XENSTORE_IDX(prod); if (prod == cons) return 0; - if (MASK_XENSTORE_IDX(prod) > MASK_XENSTORE_IDX(cons)) + if (prod > cons) to_read = prod - cons; else - to_read = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); + to_read = XENSTORE_RING_SIZE - cons; if (to_read < len) len = to_read; - memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len); + memcpy(buffer, intf->req + cons, len); xen_mb(); intf->req_cons += len; return len; @@ -66,8 +68,8 @@ static int xs_ring_write(struct mmap_int XENSTORE_RING_IDX cons, prod; int can_write; - cons = intf->rsp_cons; - prod = intf->rsp_prod; + cons = *(volatile uint32*)&intf->rsp_cons; + prod = *(volatile uint32*)&intf->rsp_prod; xen_mb(); if ( (prod - cons) >= XENSTORE_RING_SIZE ) return 0; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |