[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v8 06/16] xen/memory: Fix mapping grant tables with XENMEM_acquire_resource
On 01/02/2021 12:07, Roger Pau Monné wrote: > On Mon, Feb 01, 2021 at 11:11:37AM +0000, Andrew Cooper wrote: >> On 01/02/2021 10:10, Roger Pau Monné wrote: >>> On Sat, Jan 30, 2021 at 02:58:42AM +0000, Andrew Cooper wrote: >>>> + (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.mar)) / >>>> + sizeof(*xen_frame_list); >>>> + >>>> + if ( start_extent >= cmp.mar.nr_frames ) >>>> + return -EINVAL; >>>> + >>>> + /* >>>> + * Adjust nat to account for work done on previous >>>> + * continuations, leaving cmp pristine. Hide the >>>> continaution >>>> + * from the native code to prevent double accounting. >>>> + */ >>>> + nat.mar->nr_frames -= start_extent; >>>> + nat.mar->frame += start_extent; >>>> + cmd &= MEMOP_CMD_MASK; >>>> + >>>> + /* >>>> + * If there are two many frames to fit within the xlat >>>> buffer, >>>> + * we'll need to loop to marshal them all. >>>> + */ >>>> + nat.mar->nr_frames = min(nat.mar->nr_frames, >>>> xlat_max_frames); >>>> + >>>> /* >>>> * frame_list is an input for translated guests, and an >>>> output >>>> * for untranslated guests. Only copy in for translated >>>> guests. >>>> @@ -444,14 +453,14 @@ int compat_memory_op(unsigned int cmd, >>>> XEN_GUEST_HANDLE_PARAM(void) compat) >>>> cmp.mar.nr_frames) || >>>> __copy_from_compat_offset( >>>> compat_frame_list, cmp.mar.frame_list, >>>> - 0, cmp.mar.nr_frames) ) >>>> + start_extent, nat.mar->nr_frames) ) >>>> return -EFAULT; >>>> >>>> /* >>>> * Iterate backwards over compat_frame_list[] >>>> expanding >>>> * compat_pfn_t to xen_pfn_t in place. >>>> */ >>>> - for ( int x = cmp.mar.nr_frames - 1; x >= 0; --x ) >>>> + for ( int x = nat.mar->nr_frames - 1; x >= 0; --x ) >>>> xen_frame_list[x] = compat_frame_list[x]; >>> Unrelated question, but I don't really see the point of iterating >>> backwards, wouldn't it be easy to use use the existing 'i' loop >>> counter and for a for ( i = 0; i < nat.mar->nr_frames; i++ )? >>> >>> (Not that you need to fix it here, just curious about why we use that >>> construct instead). >> Iterating backwards is totally critical. >> >> xen_frame_list and compat_frame_list are the same numerical pointer. >> We've just filled it 50% full with compat_pfn_t's, and need to turn >> these into xen_pfn_t's which are double the size. >> >> Iterating forwards would clobber every entry but the first. > Oh, I didn't realize they point to the same address. A comment would > help (not that you need to add it now). Well - that's what "expand ... in place" means in the existing comment. Suggestions for how to make it clearer? > >>>> } >>>> } >>>> @@ -600,9 +609,11 @@ int compat_memory_op(unsigned int cmd, >>>> XEN_GUEST_HANDLE_PARAM(void) compat) >>>> case XENMEM_acquire_resource: >>>> { >>>> DEFINE_XEN_GUEST_HANDLE(compat_mem_acquire_resource_t); >>>> + unsigned int done; >>>> >>>> if ( compat_handle_is_null(cmp.mar.frame_list) ) >>>> { >>>> + ASSERT(split == 0 && rc == 0); >>>> if ( __copy_field_to_guest( >>>> guest_handle_cast(compat, >>>> compat_mem_acquire_resource_t), >>>> @@ -611,6 +622,21 @@ int compat_memory_op(unsigned int cmd, >>>> XEN_GUEST_HANDLE_PARAM(void) compat) >>>> break; >>>> } >>>> >>>> + if ( split < 0 ) >>>> + { >>>> + /* Continuation occurred. */ >>>> + ASSERT(rc != XENMEM_acquire_resource); >>>> + done = cmd >> MEMOP_EXTENT_SHIFT; >>>> + } >>>> + else >>>> + { >>>> + /* No continuation. */ >>>> + ASSERT(rc == 0); >>>> + done = nat.mar->nr_frames; >>>> + } >>>> + >>>> + ASSERT(done <= nat.mar->nr_frames); >>>> + >>>> /* >>>> * frame_list is an input for translated guests, and an >>>> output for >>>> * untranslated guests. Only copy out for untranslated >>>> guests. >>>> @@ -626,7 +652,7 @@ int compat_memory_op(unsigned int cmd, >>>> XEN_GUEST_HANDLE_PARAM(void) compat) >>>> */ >>>> BUILD_BUG_ON(sizeof(compat_pfn_t) > sizeof(xen_pfn_t)); >>>> >>>> - for ( i = 0; i < cmp.mar.nr_frames; i++ ) >>>> + for ( i = 0; i < done; i++ ) >>>> { >>>> compat_pfn_t frame = xen_frame_list[i]; >>>> >>>> @@ -636,15 +662,45 @@ int compat_memory_op(unsigned int cmd, >>>> XEN_GUEST_HANDLE_PARAM(void) compat) >>>> compat_frame_list[i] = frame; >>>> } >>>> >>>> - if ( __copy_to_compat_offset(cmp.mar.frame_list, 0, >>>> + if ( __copy_to_compat_offset(cmp.mar.frame_list, >>>> start_extent, >>>> compat_frame_list, >>>> - cmp.mar.nr_frames) ) >>>> + done) ) >>>> return -EFAULT; >>> Is it fine to return with a possibly pending continuation already >>> encoded here? >>> >>> Other places seem to crash the domain when that happens. >> Hmm. This is all a total mess. (Elsewhere the error handling is also >> broken - a caller who receives an error can't figure out how to recover) >> >> But yes - I think you're right - the only thing we can do here is `goto >> crash;` and woe betide any 32bit kernel which passes a pointer to a >> read-only buffer. > With that added: > > Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Thanks. ~Andrew
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |