]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.4.39/xen-blkback-correctly-respond-to-unknown-non-native-requests.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.39 / xen-blkback-correctly-respond-to-unknown-non-native-requests.patch
1 From 0e367ae46503cfe7791460c8ba8434a5d60b2bd5 Mon Sep 17 00:00:00 2001
2 From: David Vrabel <david.vrabel@citrix.com>
3 Date: Thu, 7 Mar 2013 17:32:01 +0000
4 Subject: xen/blkback: correctly respond to unknown, non-native requests
5
6 From: David Vrabel <david.vrabel@citrix.com>
7
8 commit 0e367ae46503cfe7791460c8ba8434a5d60b2bd5 upstream.
9
10 If the frontend is using a non-native protocol (e.g., a 64-bit
11 frontend with a 32-bit backend) and it sent an unrecognized request,
12 the request was not translated and the response would have the
13 incorrect ID. This may cause the frontend driver to behave
14 incorrectly or crash.
15
16 Since the ID field in the request is always in the same place,
17 regardless of the request type we can get the correct ID and make a
18 valid response (which will report BLKIF_RSP_EOPNOTSUPP).
19
20 This bug affected 64-bit SLES 11 guests when using a 32-bit backend.
21 This guest does a BLKIF_OP_RESERVED_1 (BLKIF_OP_PACKET in the SLES
22 source) and would crash in blkif_int() as the ID in the response would
23 be invalid.
24
25 Signed-off-by: David Vrabel <david.vrabel@citrix.com>
26 Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
27 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
28
29 ---
30 drivers/block/xen-blkback/blkback.c | 31 +++++++++++++++++++++++++++----
31 drivers/block/xen-blkback/common.h | 25 +++++++++++++++++++++++++
32 include/xen/interface/io/blkif.h | 10 ++++++++++
33 3 files changed, 62 insertions(+), 4 deletions(-)
34
35 --- a/drivers/block/xen-blkback/blkback.c
36 +++ b/drivers/block/xen-blkback/blkback.c
37 @@ -422,6 +422,16 @@ static int dispatch_discard_io(struct xe
38 return err;
39 }
40
41 +static int dispatch_other_io(struct xen_blkif *blkif,
42 + struct blkif_request *req,
43 + struct pending_req *pending_req)
44 +{
45 + free_req(pending_req);
46 + make_response(blkif, req->u.other.id, req->operation,
47 + BLKIF_RSP_EOPNOTSUPP);
48 + return -EIO;
49 +}
50 +
51 static void xen_blk_drain_io(struct xen_blkif *blkif)
52 {
53 atomic_set(&blkif->drain, 1);
54 @@ -543,17 +553,30 @@ __do_block_io_op(struct xen_blkif *blkif
55
56 /* Apply all sanity checks to /private copy/ of request. */
57 barrier();
58 - if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
59 +
60 + switch (req.operation) {
61 + case BLKIF_OP_READ:
62 + case BLKIF_OP_WRITE:
63 + case BLKIF_OP_WRITE_BARRIER:
64 + case BLKIF_OP_FLUSH_DISKCACHE:
65 + if (dispatch_rw_block_io(blkif, &req, pending_req))
66 + goto done;
67 + break;
68 + case BLKIF_OP_DISCARD:
69 free_req(pending_req);
70 if (dispatch_discard_io(blkif, &req))
71 - break;
72 - } else if (dispatch_rw_block_io(blkif, &req, pending_req))
73 + goto done;
74 break;
75 + default:
76 + if (dispatch_other_io(blkif, &req, pending_req))
77 + goto done;
78 + break;
79 + }
80
81 /* Yield point for this unbounded loop. */
82 cond_resched();
83 }
84 -
85 +done:
86 return more_to_do;
87 }
88
89 --- a/drivers/block/xen-blkback/common.h
90 +++ b/drivers/block/xen-blkback/common.h
91 @@ -76,11 +76,18 @@ struct blkif_x86_32_request_discard {
92 uint64_t nr_sectors;
93 } __attribute__((__packed__));
94
95 +struct blkif_x86_32_request_other {
96 + uint8_t _pad1;
97 + blkif_vdev_t _pad2;
98 + uint64_t id; /* private guest value, echoed in resp */
99 +} __attribute__((__packed__));
100 +
101 struct blkif_x86_32_request {
102 uint8_t operation; /* BLKIF_OP_??? */
103 union {
104 struct blkif_x86_32_request_rw rw;
105 struct blkif_x86_32_request_discard discard;
106 + struct blkif_x86_32_request_other other;
107 } u;
108 } __attribute__((__packed__));
109
110 @@ -112,11 +119,19 @@ struct blkif_x86_64_request_discard {
111 uint64_t nr_sectors;
112 } __attribute__((__packed__));
113
114 +struct blkif_x86_64_request_other {
115 + uint8_t _pad1;
116 + blkif_vdev_t _pad2;
117 + uint32_t _pad3; /* offsetof(blkif_..,u.discard.id)==8 */
118 + uint64_t id; /* private guest value, echoed in resp */
119 +} __attribute__((__packed__));
120 +
121 struct blkif_x86_64_request {
122 uint8_t operation; /* BLKIF_OP_??? */
123 union {
124 struct blkif_x86_64_request_rw rw;
125 struct blkif_x86_64_request_discard discard;
126 + struct blkif_x86_64_request_other other;
127 } u;
128 } __attribute__((__packed__));
129
130 @@ -262,6 +277,11 @@ static inline void blkif_get_x86_32_req(
131 dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
132 break;
133 default:
134 + /*
135 + * Don't know how to translate this op. Only get the
136 + * ID so failure can be reported to the frontend.
137 + */
138 + dst->u.other.id = src->u.other.id;
139 break;
140 }
141 }
142 @@ -293,6 +313,11 @@ static inline void blkif_get_x86_64_req(
143 dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
144 break;
145 default:
146 + /*
147 + * Don't know how to translate this op. Only get the
148 + * ID so failure can be reported to the frontend.
149 + */
150 + dst->u.other.id = src->u.other.id;
151 break;
152 }
153 }
154 --- a/include/xen/interface/io/blkif.h
155 +++ b/include/xen/interface/io/blkif.h
156 @@ -138,11 +138,21 @@ struct blkif_request_discard {
157 uint8_t _pad3;
158 } __attribute__((__packed__));
159
160 +struct blkif_request_other {
161 + uint8_t _pad1;
162 + blkif_vdev_t _pad2; /* only for read/write requests */
163 +#ifdef CONFIG_X86_64
164 + uint32_t _pad3; /* offsetof(blkif_req..,u.other.id)==8*/
165 +#endif
166 + uint64_t id; /* private guest value, echoed in resp */
167 +} __attribute__((__packed__));
168 +
169 struct blkif_request {
170 uint8_t operation; /* BLKIF_OP_??? */
171 union {
172 struct blkif_request_rw rw;
173 struct blkif_request_discard discard;
174 + struct blkif_request_other other;
175 } u;
176 } __attribute__((__packed__));
177