Fixes for CVE-2010-4247 blkback: Request-processing loop is unbounded and hence requires a yield point. Also, bad request type is a good cause to sleep for a short while as the frontend has probably gone mad. Patch by Steven Smith Signed-off-by: Keir Fraser blkback/blktap: Check for kthread_should_stop() in inner loop, mdelaay() should be msleep(), and these changes belong in blktap as well as blkback. Based on comments and patches from Jan Beulich and Steven Smith. Signed-off-by: Keir Fraser Signed-off-by: Stefan Bader diff -Nurp custom-source-xen.orig/drivers/xen/blkback/blkback.c custom-source-xen/drivers/xen/blkback/blkback.c --- custom-source-xen.orig/drivers/xen/blkback/blkback.c 2011-06-01 09:35:13.180006000 +0000 +++ custom-source-xen/drivers/xen/blkback/blkback.c 2011-06-01 09:46:55.470006001 +0000 @@ -309,7 +309,7 @@ static int do_block_io_op(blkif_t *blkif rp = blk_rings->common.sring->req_prod; rmb(); /* Ensure we see queued requests up to 'rp'. */ - while ((rc != rp)) { + while (rc != rp) { if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) break; @@ -321,6 +321,11 @@ static int do_block_io_op(blkif_t *blkif break; } + if (kthread_should_stop()) { + more_to_do = 1; + break; + } + switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req)); @@ -349,6 +354,9 @@ static int do_block_io_op(blkif_t *blkif dispatch_rw_block_io(blkif, &req, pending_req); break; default: + /* A good sign something is wrong: sleep for a while to + * avoid excessive CPU consumption by a bad guest. */ + msleep(1); DPRINTK("error: unknown block io operation [%d]\n", req.operation); make_response(blkif, req.id, req.operation, @@ -356,7 +364,11 @@ static int do_block_io_op(blkif_t *blkif free_req(pending_req); break; } + + /* Yield point for this unbounded loop. */ + cond_resched(); } + return more_to_do; } @@ -507,7 +519,8 @@ static void dispatch_rw_block_io(blkif_t fail_response: make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); free_req(pending_req); -} + msleep(1); /* back off a bit */ +} diff -Nurp custom-source-xen.orig/drivers/xen/blktap/blktap.c custom-source-xen/drivers/xen/blktap/blktap.c --- custom-source-xen.orig/drivers/xen/blktap/blktap.c 2011-06-01 09:35:13.190006000 +0000 +++ custom-source-xen/drivers/xen/blktap/blktap.c 2011-06-01 09:45:50.870006001 +0000 @@ -53,6 +53,7 @@ #include #include #include +#include #include #define MAX_TAP_DEV 256 /*the maximum number of tapdisk ring devices */ @@ -1243,6 +1244,11 @@ static int do_block_io_op(blkif_t *blkif break; } + if (kthread_should_stop()) { + more_to_do = 1; + break; + } + switch (blkif->blk_protocol) { case BLKIF_PROTOCOL_NATIVE: memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), @@ -1271,6 +1277,9 @@ static int do_block_io_op(blkif_t *blkif break; default: + /* A good sign something is wrong: sleep for a while to + * avoid excessive CPU consumption by a bad guest. */ + msleep(1); WPRINTK("unknown operation [%d]\n", req.operation); make_response(blkif, req.id, req.operation, @@ -1278,6 +1287,9 @@ static int do_block_io_op(blkif_t *blkif free_req(pending_req); break; } + + /* Yield point for this unbounded loop. */ + cond_resched(); } blktap_kick_user(blkif->dev_num); @@ -1504,7 +1516,8 @@ static void dispatch_rw_block_io(blkif_t fail_response: make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); free_req(pending_req); -} + msleep(1); /* back off a bit */ +}