debuggers.hg

view xen/common/compat/grant_table.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 95ea2052b41b
children
line source
1 /******************************************************************************
2 * common/compat/grant_table.c
3 *
4 */
6 #include <compat/grant_table.h>
8 #define xen_grant_entry_v1 grant_entry_v1
9 CHECK_grant_entry_v1;
10 #undef xen_grant_entry_v1
12 #define xen_grant_entry_header grant_entry_header
13 CHECK_grant_entry_header;
14 #undef xen_grant_entry_header
16 #define xen_grant_entry_v2 grant_entry_v2
17 CHECK_grant_entry_v2;
18 #undef xen_grant_entry_v2
20 #define xen_gnttab_map_grant_ref gnttab_map_grant_ref
21 CHECK_gnttab_map_grant_ref;
22 #undef xen_gnttab_map_grant_ref
24 #define xen_gnttab_unmap_grant_ref gnttab_unmap_grant_ref
25 CHECK_gnttab_unmap_grant_ref;
26 #undef xen_gnttab_unmap_grant_ref
28 #define xen_gnttab_unmap_and_replace gnttab_unmap_and_replace
29 CHECK_gnttab_unmap_and_replace;
30 #undef xen_gnttab_unmap_and_replace
32 DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_compat_t);
33 DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_compat_t);
34 DEFINE_XEN_GUEST_HANDLE(gnttab_copy_compat_t);
36 #define xen_gnttab_dump_table gnttab_dump_table
37 CHECK_gnttab_dump_table;
38 #undef xen_gnttab_dump_table
40 #define xen_gnttab_set_version gnttab_set_version
41 CHECK_gnttab_set_version;
42 #undef xen_gnttab_set_version
44 DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_compat_t);
46 #define xen_gnttab_get_version gnttab_get_version
47 CHECK_gnttab_get_version;
48 #undef xen_gnttab_get_version
50 int compat_grant_table_op(unsigned int cmd,
51 XEN_GUEST_HANDLE(void) cmp_uop,
52 unsigned int count)
53 {
54 int rc = 0;
55 unsigned int i;
56 XEN_GUEST_HANDLE(void) cnt_uop;
58 set_xen_guest_handle(cnt_uop, NULL);
59 switch ( cmd )
60 {
61 #define CASE(name) \
62 case GNTTABOP_##name: \
63 if ( unlikely(!guest_handle_okay(guest_handle_cast(cmp_uop, \
64 gnttab_##name##_compat_t), \
65 count)) ) \
66 rc = -EFAULT; \
67 break
69 #ifndef CHECK_gnttab_map_grant_ref
70 CASE(map_grant_ref);
71 #endif
73 #ifndef CHECK_gnttab_unmap_grant_ref
74 CASE(unmap_grant_ref);
75 #endif
77 #ifndef CHECK_gnttab_unmap_and_replace
78 CASE(unmap_and_replace);
79 #endif
81 #ifndef CHECK_gnttab_setup_table
82 CASE(setup_table);
83 #endif
85 #ifndef CHECK_gnttab_transfer
86 CASE(transfer);
87 #endif
89 #ifndef CHECK_gnttab_copy
90 CASE(copy);
91 #endif
93 #ifndef CHECK_gnttab_dump_table
94 CASE(dump_table);
95 #endif
97 #ifndef CHECK_gnttab_get_status_frames
98 CASE(get_status_frames);
99 #endif
101 #undef CASE
102 default:
103 return do_grant_table_op(cmd, cmp_uop, count);
104 }
106 if ( (int)count < 0 )
107 rc = -EINVAL;
109 for ( i = 0; i < count && rc == 0; )
110 {
111 unsigned int n;
112 union {
113 XEN_GUEST_HANDLE(void) uop;
114 struct gnttab_setup_table *setup;
115 struct gnttab_transfer *xfer;
116 struct gnttab_copy *copy;
117 struct gnttab_get_status_frames *get_status;
118 } nat;
119 union {
120 struct compat_gnttab_setup_table setup;
121 struct compat_gnttab_transfer xfer;
122 struct compat_gnttab_copy copy;
123 struct compat_gnttab_get_status_frames get_status;
124 } cmp;
126 set_xen_guest_handle(nat.uop, COMPAT_ARG_XLAT_VIRT_BASE);
127 switch ( cmd )
128 {
129 case GNTTABOP_setup_table:
130 if ( unlikely(count > 1) )
131 rc = -EINVAL;
132 else if ( unlikely(__copy_from_guest(&cmp.setup, cmp_uop, 1)) )
133 rc = -EFAULT;
134 else if ( unlikely(!compat_handle_okay(cmp.setup.frame_list, cmp.setup.nr_frames)) )
135 rc = -EFAULT;
136 else
137 {
138 unsigned int max_frame_list_size_in_page =
139 (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.setup)) /
140 sizeof(*nat.setup->frame_list.p);
141 if ( max_frame_list_size_in_page < max_nr_grant_frames )
142 {
143 gdprintk(XENLOG_WARNING,
144 "max_nr_grant_frames is too large (%u,%u)\n",
145 max_nr_grant_frames, max_frame_list_size_in_page);
146 rc = -EINVAL;
147 }
148 else
149 {
150 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
151 set_xen_guest_handle((_d_)->frame_list, (unsigned long *)(nat.setup + 1))
152 XLAT_gnttab_setup_table(nat.setup, &cmp.setup);
153 #undef XLAT_gnttab_setup_table_HNDL_frame_list
154 rc = gnttab_setup_table(guest_handle_cast(nat.uop, gnttab_setup_table_t), 1);
155 }
156 }
157 ASSERT(rc <= 0);
158 if ( rc == 0 )
159 {
160 #define XLAT_gnttab_setup_table_HNDL_frame_list(_d_, _s_) \
161 do \
162 { \
163 if ( (_s_)->status == GNTST_okay ) \
164 { \
165 for ( i = 0; i < (_s_)->nr_frames; ++i ) \
166 { \
167 unsigned int frame = (_s_)->frame_list.p[i]; \
168 (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
169 } \
170 } \
171 } while (0)
172 XLAT_gnttab_setup_table(&cmp.setup, nat.setup);
173 #undef XLAT_gnttab_setup_table_HNDL_frame_list
174 if ( unlikely(__copy_to_guest(cmp_uop, &cmp.setup, 1)) )
175 rc = -EFAULT;
176 else
177 i = 1;
178 }
179 break;
181 case GNTTABOP_transfer:
182 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.xfer) && i < count && rc == 0; ++i, ++n )
183 {
184 if ( unlikely(__copy_from_guest_offset(&cmp.xfer, cmp_uop, i, 1)) )
185 rc = -EFAULT;
186 else
187 {
188 XLAT_gnttab_transfer(nat.xfer + n, &cmp.xfer);
189 }
190 }
191 if ( rc == 0 )
192 rc = gnttab_transfer(guest_handle_cast(nat.uop, gnttab_transfer_t), n);
193 if ( rc > 0 )
194 {
195 ASSERT(rc < n);
196 i -= n - rc;
197 n = rc;
198 }
199 if ( rc >= 0 )
200 {
201 XEN_GUEST_HANDLE(gnttab_transfer_compat_t) xfer;
203 xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
204 guest_handle_add_offset(xfer, i);
205 cnt_uop = guest_handle_cast(xfer, void);
206 while ( n-- )
207 {
208 guest_handle_add_offset(xfer, -1);
209 if ( __copy_field_to_guest(xfer, nat.xfer + n, status) )
210 rc = -EFAULT;
211 }
212 }
213 break;
215 case GNTTABOP_copy:
216 for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.copy) && i < count && rc == 0; ++i, ++n )
217 {
218 if ( unlikely(__copy_from_guest_offset(&cmp.copy, cmp_uop, i, 1)) )
219 rc = -EFAULT;
220 else
221 {
222 enum XLAT_gnttab_copy_source_u source_u;
223 enum XLAT_gnttab_copy_dest_u dest_u;
225 if ( cmp.copy.flags & GNTCOPY_source_gref )
226 source_u = XLAT_gnttab_copy_source_u_ref;
227 else
228 source_u = XLAT_gnttab_copy_source_u_gmfn;
229 if ( cmp.copy.flags & GNTCOPY_dest_gref )
230 dest_u = XLAT_gnttab_copy_dest_u_ref;
231 else
232 dest_u = XLAT_gnttab_copy_dest_u_gmfn;
233 XLAT_gnttab_copy(nat.copy + n, &cmp.copy);
234 }
235 }
236 if ( rc == 0 )
237 rc = gnttab_copy(guest_handle_cast(nat.uop, gnttab_copy_t), n);
238 if ( rc > 0 )
239 {
240 ASSERT(rc < n);
241 i -= n - rc;
242 n = rc;
243 }
244 if ( rc >= 0 )
245 {
246 XEN_GUEST_HANDLE(gnttab_copy_compat_t) copy;
248 copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
249 guest_handle_add_offset(copy, i);
250 cnt_uop = guest_handle_cast(copy, void);
251 while ( n-- )
252 {
253 guest_handle_add_offset(copy, -1);
254 if ( __copy_field_to_guest(copy, nat.copy + n, status) )
255 rc = -EFAULT;
256 }
257 }
258 break;
260 case GNTTABOP_get_status_frames: {
261 unsigned int max_frame_list_size_in_pages =
262 (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.get_status)) /
263 sizeof(*nat.get_status->frame_list.p);
264 if ( count != 1)
265 {
266 rc = -EINVAL;
267 break;
268 }
269 if ( unlikely(__copy_from_guest(&cmp.get_status, cmp_uop, 1) ||
270 !compat_handle_okay(cmp.get_status.frame_list,
271 cmp.get_status.nr_frames)) )
272 {
273 rc = -EFAULT;
274 break;
275 }
276 if ( max_frame_list_size_in_pages <
277 grant_to_status_frames(max_nr_grant_frames) )
278 {
279 gdprintk(XENLOG_WARNING,
280 "grant_to_status_frames(max_nr_grant_frames) is too large (%u,%u)\n",
281 grant_to_status_frames(max_nr_grant_frames),
282 max_frame_list_size_in_pages);
283 rc = -EINVAL;
284 break;
285 }
287 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
288 set_xen_guest_handle((_d_)->frame_list, (uint64_t *)(nat.get_status + 1))
289 XLAT_gnttab_get_status_frames(nat.get_status, &cmp.get_status);
290 #undef XLAT_gnttab_get_status_frames_HNDL_frame_list
292 rc = gnttab_get_status_frames(
293 guest_handle_cast(nat.uop, gnttab_get_status_frames_t),
294 count);
295 if ( rc >= 0 )
296 {
297 #define XLAT_gnttab_get_status_frames_HNDL_frame_list(_d_, _s_) \
298 do \
299 { \
300 if ( (_s_)->status == GNTST_okay ) \
301 { \
302 for ( i = 0; i < (_s_)->nr_frames; ++i ) \
303 { \
304 uint64_t frame = (_s_)->frame_list.p[i]; \
305 (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \
306 } \
307 } \
308 } while (0)
309 XLAT_gnttab_get_status_frames(&cmp.get_status, nat.get_status);
310 #undef XLAT_gnttab_get_status_frames_HNDL_frame_list
311 if ( unlikely(__copy_to_guest(cmp_uop, &cmp.get_status, 1)) )
312 rc = -EFAULT;
313 }
314 break;
315 }
317 default:
318 domain_crash(current->domain);
319 break;
320 }
321 }
323 if ( rc > 0 )
324 {
325 ASSERT(i < count);
326 ASSERT(!guest_handle_is_null(cnt_uop));
327 rc = hypercall_create_continuation(__HYPERVISOR_grant_table_op,
328 "ihi", cmd, cnt_uop, count - i);
329 }
331 return rc;
332 }
334 /*
335 * Local variables:
336 * mode: C
337 * c-set-style: "BSD"
338 * c-basic-offset: 4
339 * tab-width: 4
340 * indent-tabs-mode: nil
341 * End:
342 */