[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v5 for-4.9 3/4] hvm/dmop: Implement copy_{to, from}_guest_buf_offset() helpers


  • To: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>, Xen-devel <xen-devel@xxxxxxxxxxxxx>
  • From: Paul Durrant <Paul.Durrant@xxxxxxxxxx>
  • Date: Mon, 10 Apr 2017 10:04:21 +0000
  • Accept-language: en-GB, en-US
  • Cc: Julien Grall <julien.grall@xxxxxxx>, Jan Beulich <JBeulich@xxxxxxxx>
  • Delivery-date: Mon, 10 Apr 2017 10:04:34 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: AQHSr9Yu05HiuvDSkUy00HdpsQDveKG+VEWg///mIACAACO3cP//4mIAgAAhwbA=
  • Thread-topic: [PATCH v5 for-4.9 3/4] hvm/dmop: Implement copy_{to,from}_guest_buf_offset() helpers

> -----Original Message-----
> From: Andrew Cooper
> Sent: 10 April 2017 10:57
> To: Paul Durrant <Paul.Durrant@xxxxxxxxxx>; Xen-devel <xen-
> devel@xxxxxxxxxxxxx>
> Cc: Jan Beulich <JBeulich@xxxxxxxx>; Julien Grall <julien.grall@xxxxxxx>
> Subject: Re: [PATCH v5 for-4.9 3/4] hvm/dmop: Implement
> copy_{to,from}_guest_buf_offset() helpers
> 
> On 10/04/17 10:52, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: Andrew Cooper
> >> Sent: 10 April 2017 10:36
> >> To: Paul Durrant <Paul.Durrant@xxxxxxxxxx>; Xen-devel <xen-
> >> devel@xxxxxxxxxxxxx>
> >> Cc: Jan Beulich <JBeulich@xxxxxxxx>; Julien Grall <julien.grall@xxxxxxx>
> >> Subject: Re: [PATCH v5 for-4.9 3/4] hvm/dmop: Implement
> >> copy_{to,from}_guest_buf_offset() helpers
> >>
> >> On 10/04/17 10:11, Paul Durrant wrote:
> >>>> -----Original Message-----
> >>>> From: Andrew Cooper [mailto:andrew.cooper3@xxxxxxxxxx]
> >>>> Sent: 07 April 2017 20:36
> >>>> To: Xen-devel <xen-devel@xxxxxxxxxxxxx>
> >>>> Cc: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>; Jan Beulich
> >>>> <JBeulich@xxxxxxxx>; Paul Durrant <Paul.Durrant@xxxxxxxxxx>; Julien
> >> Grall
> >>>> <julien.grall@xxxxxxx>
> >>>> Subject: [PATCH v5 for-4.9 3/4] hvm/dmop: Implement
> >>>> copy_{to,from}_guest_buf_offset() helpers
> >>>>
> >>>> copy_{to,from}_guest_buf() are now implemented using an offset of
> 0.
> >>>>
> >>>> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> >>>> ---
> >>>> CC: Jan Beulich <JBeulich@xxxxxxxx>
> >>>> CC: Paul Durrant <paul.durrant@xxxxxxxxxx>
> >>>> CC: Julien Grall <julien.grall@xxxxxxx>
> >>>> ---
> >>>>  xen/arch/x86/hvm/dm.c | 34 ++++++++++++++++++++++++----------
> >>>>  1 file changed, 24 insertions(+), 10 deletions(-)
> >>>>
> >>>> diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
> >>>> index 3d8ae89..d584aba 100644
> >>>> --- a/xen/arch/x86/hvm/dm.c
> >>>> +++ b/xen/arch/x86/hvm/dm.c
> >>>> @@ -37,9 +37,9 @@ struct dmop_bufs {
> >>>>  #undef MAX_NR_BUFS
> >>>>  };
> >>>>
> >>>> -static bool _raw_copy_from_guest_buf(
> >>>> +static bool _raw_copy_from_guest_buf_offset(
> >>>>      const struct dmop_bufs *bufs, unsigned int idx,
> >>>> -    void *dst, size_t dst_bytes)
> >>>> +    size_t offset_bytes, void *dst, size_t dst_bytes)
> >>>>  {
> >>>>      size_t buf_bytes;
> >>>>
> >>>> @@ -48,17 +48,20 @@ static bool _raw_copy_from_guest_buf(
> >>>>
> >>>>      buf_bytes = bufs->buf[idx].size;
> >>>>
> >>>> -    if ( dst_bytes > buf_bytes )
> >>>> +    if ( offset_bytes >= dst_bytes ||
> >>>> +         (offset_bytes + dst_bytes) < offset_bytes ||
> >>>> +         (offset_bytes + dst_bytes) > dst_bytes )
> >>>>          return false;
> >>>>
> >>>>      memset(dst, 0, dst_bytes);
> >>>>
> >>>> -    return !copy_from_guest(dst, bufs->buf[idx].h, dst_bytes);
> >>>> +    return !copy_from_guest_offset(dst, bufs->buf[idx].h,
> >>>> +                                   offset_bytes, dst_bytes);
> >>> Not sure what's going on here. 'buf_bytes' is being assigned but no
> longer
> >> seems to be used (since it's dropped from the if statement). Also, I'm not
> >> entirely sure what range check that if statement is trying to perform. Can
> we
> >> at least have a comment it it's actually correct (which I'm not at all
> convinced
> >> of).
> >>
> >> That is actually because the if statement isn't correct.  The final
> >> comparison should be against buf_bytes, not dst_bytes.
> > Ok, that makes more sense... so the first clause is checking for size_t
> overflow, right?
> 
> The first is a straight "is the offset off the end of the buffer", the
> middle is a size_t overflow check (this is defined behaviour as size_t
> is unsigned.  It would be UB if size_t was signed), and the final was
> supposed to be "(offset_bytes + dst_bytes) > buf_bytes" to check whether
> the entire region wanting copying resides inside the buffer.
> 

Sorry, I meant the middle clause, so with the fix that all makes sense now.

> >
> >> The problem is that copy_from_guest_offset() takes offset in units of
> >> sizeof(typeof(*bufs->buf[idx].h)) (which in this case is bytes, until
> >> the type of buf.h changes), while nr is strictly in bytes.  My
> >> conclusion after Friday's hacking is that this is also a recipe
> >> security-relevant mistakes, and is fiendishly complicated to reason about.
> > Anything using typeof() is a PITA to reason about IMO, so using the offset
> variant is definitely going to be an improvement.
> 
> I'm mulling over rewriting it all, because it is starting to get
> embarrassing how many security issues we have in the existing
> infrastructure.
> 

Certainly removing some of the macrotization would make it easier to follow 
and, if copy_from_guest() is going to use typeof (for convenience of copying an 
op struct in the common case I guess) then it really should be single instance 
for safety, or preferably take an explicit type.

  Paul

> ~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.