aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/xen-blkback
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2013-03-07 12:32:01 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-03-11 13:54:28 -0400
commit0e367ae46503cfe7791460c8ba8434a5d60b2bd5 (patch)
treef3056dc8de11ab4431cb227f4417af810c7f31e9 /drivers/block/xen-blkback
parenta72d9002f80bffd7e4c7d60e5a9caa0cddffe894 (diff)
xen/blkback: correctly respond to unknown, non-native requests
If the frontend is using a non-native protocol (e.g., a 64-bit frontend with a 32-bit backend) and it sent an unrecognized request, the request was not translated and the response would have the incorrect ID. This may cause the frontend driver to behave incorrectly or crash. Since the ID field in the request is always in the same place, regardless of the request type we can get the correct ID and make a valid response (which will report BLKIF_RSP_EOPNOTSUPP). This bug affected 64-bit SLES 11 guests when using a 32-bit backend. This guest does a BLKIF_OP_RESERVED_1 (BLKIF_OP_PACKET in the SLES source) and would crash in blkif_int() as the ID in the response would be invalid. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: stable@vger.kernel.org Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkback')
-rw-r--r--drivers/block/xen-blkback/blkback.c31
-rw-r--r--drivers/block/xen-blkback/common.h25
2 files changed, 52 insertions, 4 deletions
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 6d1cc3df2ac6..1a0faf6370ca 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -679,6 +679,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
679 return err; 679 return err;
680} 680}
681 681
682static int dispatch_other_io(struct xen_blkif *blkif,
683 struct blkif_request *req,
684 struct pending_req *pending_req)
685{
686 free_req(pending_req);
687 make_response(blkif, req->u.other.id, req->operation,
688 BLKIF_RSP_EOPNOTSUPP);
689 return -EIO;
690}
691
682static void xen_blk_drain_io(struct xen_blkif *blkif) 692static void xen_blk_drain_io(struct xen_blkif *blkif)
683{ 693{
684 atomic_set(&blkif->drain, 1); 694 atomic_set(&blkif->drain, 1);
@@ -800,17 +810,30 @@ __do_block_io_op(struct xen_blkif *blkif)
800 810
801 /* Apply all sanity checks to /private copy/ of request. */ 811 /* Apply all sanity checks to /private copy/ of request. */
802 barrier(); 812 barrier();
803 if (unlikely(req.operation == BLKIF_OP_DISCARD)) { 813
814 switch (req.operation) {
815 case BLKIF_OP_READ:
816 case BLKIF_OP_WRITE:
817 case BLKIF_OP_WRITE_BARRIER:
818 case BLKIF_OP_FLUSH_DISKCACHE:
819 if (dispatch_rw_block_io(blkif, &req, pending_req))
820 goto done;
821 break;
822 case BLKIF_OP_DISCARD:
804 free_req(pending_req); 823 free_req(pending_req);
805 if (dispatch_discard_io(blkif, &req)) 824 if (dispatch_discard_io(blkif, &req))
806 break; 825 goto done;
807 } else if (dispatch_rw_block_io(blkif, &req, pending_req)) 826 break;
827 default:
828 if (dispatch_other_io(blkif, &req, pending_req))
829 goto done;
808 break; 830 break;
831 }
809 832
810 /* Yield point for this unbounded loop. */ 833 /* Yield point for this unbounded loop. */
811 cond_resched(); 834 cond_resched();
812 } 835 }
813 836done:
814 return more_to_do; 837 return more_to_do;
815} 838}
816 839
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index 6072390c7f57..195278ae993d 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -77,11 +77,18 @@ struct blkif_x86_32_request_discard {
77 uint64_t nr_sectors; 77 uint64_t nr_sectors;
78} __attribute__((__packed__)); 78} __attribute__((__packed__));
79 79
80struct blkif_x86_32_request_other {
81 uint8_t _pad1;
82 blkif_vdev_t _pad2;
83 uint64_t id; /* private guest value, echoed in resp */
84} __attribute__((__packed__));
85
80struct blkif_x86_32_request { 86struct blkif_x86_32_request {
81 uint8_t operation; /* BLKIF_OP_??? */ 87 uint8_t operation; /* BLKIF_OP_??? */
82 union { 88 union {
83 struct blkif_x86_32_request_rw rw; 89 struct blkif_x86_32_request_rw rw;
84 struct blkif_x86_32_request_discard discard; 90 struct blkif_x86_32_request_discard discard;
91 struct blkif_x86_32_request_other other;
85 } u; 92 } u;
86} __attribute__((__packed__)); 93} __attribute__((__packed__));
87 94
@@ -113,11 +120,19 @@ struct blkif_x86_64_request_discard {
113 uint64_t nr_sectors; 120 uint64_t nr_sectors;
114} __attribute__((__packed__)); 121} __attribute__((__packed__));
115 122
123struct blkif_x86_64_request_other {
124 uint8_t _pad1;
125 blkif_vdev_t _pad2;
126 uint32_t _pad3; /* offsetof(blkif_..,u.discard.id)==8 */
127 uint64_t id; /* private guest value, echoed in resp */
128} __attribute__((__packed__));
129
116struct blkif_x86_64_request { 130struct blkif_x86_64_request {
117 uint8_t operation; /* BLKIF_OP_??? */ 131 uint8_t operation; /* BLKIF_OP_??? */
118 union { 132 union {
119 struct blkif_x86_64_request_rw rw; 133 struct blkif_x86_64_request_rw rw;
120 struct blkif_x86_64_request_discard discard; 134 struct blkif_x86_64_request_discard discard;
135 struct blkif_x86_64_request_other other;
121 } u; 136 } u;
122} __attribute__((__packed__)); 137} __attribute__((__packed__));
123 138
@@ -278,6 +293,11 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
278 dst->u.discard.nr_sectors = src->u.discard.nr_sectors; 293 dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
279 break; 294 break;
280 default: 295 default:
296 /*
297 * Don't know how to translate this op. Only get the
298 * ID so failure can be reported to the frontend.
299 */
300 dst->u.other.id = src->u.other.id;
281 break; 301 break;
282 } 302 }
283} 303}
@@ -309,6 +329,11 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
309 dst->u.discard.nr_sectors = src->u.discard.nr_sectors; 329 dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
310 break; 330 break;
311 default: 331 default:
332 /*
333 * Don't know how to translate this op. Only get the
334 * ID so failure can be reported to the frontend.
335 */
336 dst->u.other.id = src->u.other.id;
312 break; 337 break;
313 } 338 }
314} 339}