diff mbox series

[v2,3/5] x86/xlat: fix UB pointer arithmetic in COMPAT_ARG_XLAT_VIRT_BASE

Message ID 20250318091904.52903-4-roger.pau@citrix.com (mailing list archive)
State New
Headers show
Series x86/ubsan: fix ubsan on clang + code fixes | expand

Commit Message

Roger Pau Monne March 18, 2025, 9:19 a.m. UTC
UBSAN complains with:

UBSAN: Undefined behaviour in common/compat/memory.c:90:9
pointer operation overflowed ffff820080000000 to 0000020080000000
[...]
Xen call trace:
   [<ffff82d040303882>] R common/ubsan/ubsan.c#ubsan_epilogue+0xa/0xc0
   [<ffff82d040304cc3>] F lib/xxhash64.c#__ubsan_handle_pointer_overflow+0xcb/0x100
   [<ffff82d0402a6359>] F lib/xxhash64.c#compat_memory_op+0xf1/0x4d20
   [<ffff82d04041545d>] F lib/xxhash64.c#hvm_memory_op+0x55/0xe0
   [<ffff82d040416280>] F lib/xxhash64.c#hvm_hypercall+0xae8/0x21b0
   [<ffff82d0403b25ca>] F lib/xxhash64.c#svm_vmexit_handler+0x1252/0x2450
   [<ffff82d0402049c0>] F lib/xxhash64.c#svm_stgi_label+0x5/0x15

Adjust the calculations in COMPAT_ARG_XLAT_VIRT_BASE to subtract from the
per-domain area to obtain the mirrored linear address in the 4th slot,
instead of overflowing the per-domain linear address.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Changes since v1:
 - New in this version.
---
 xen/arch/x86/include/asm/x86_64/uaccess.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Andrew Cooper March 18, 2025, 12:51 p.m. UTC | #1
On 18/03/2025 9:19 am, Roger Pau Monne wrote:
> UBSAN complains with:
>
> UBSAN: Undefined behaviour in common/compat/memory.c:90:9
> pointer operation overflowed ffff820080000000 to 0000020080000000
> [...]
> Xen call trace:
>    [<ffff82d040303882>] R common/ubsan/ubsan.c#ubsan_epilogue+0xa/0xc0
>    [<ffff82d040304cc3>] F lib/xxhash64.c#__ubsan_handle_pointer_overflow+0xcb/0x100
>    [<ffff82d0402a6359>] F lib/xxhash64.c#compat_memory_op+0xf1/0x4d20
>    [<ffff82d04041545d>] F lib/xxhash64.c#hvm_memory_op+0x55/0xe0
>    [<ffff82d040416280>] F lib/xxhash64.c#hvm_hypercall+0xae8/0x21b0
>    [<ffff82d0403b25ca>] F lib/xxhash64.c#svm_vmexit_handler+0x1252/0x2450
>    [<ffff82d0402049c0>] F lib/xxhash64.c#svm_stgi_label+0x5/0x15
>
> Adjust the calculations in COMPAT_ARG_XLAT_VIRT_BASE to subtract from the
> per-domain area to obtain the mirrored linear address in the 4th slot,
> instead of overflowing the per-domain linear address.
>
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>

Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
Jan Beulich March 18, 2025, 2:33 p.m. UTC | #2
On 18.03.2025 10:19, Roger Pau Monne wrote:
> --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
> +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
> @@ -9,9 +9,9 @@
>   * a secondary mapping installed, which needs to be used for such accesses in
>   * the PV case, and will also be used for HVM to avoid extra conditionals.
>   */
> -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
> -                                   (PERDOMAIN_ALT_VIRT_START - \
> -                                    PERDOMAIN_VIRT_START))
> +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> +                                   (PERDOMAIN_VIRT_START - \
> +                                    PERDOMAIN_ALT_VIRT_START))

Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
and PERDOMAIN_ALT_VIRT_START? Would

#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
                                   PERDOMAIN_VIRT_START + \
                                   PERDOMAIN_ALT_VIRT_START)

perhaps be less fragile?

Jan
Roger Pau Monne March 18, 2025, 3:35 p.m. UTC | #3
On Tue, Mar 18, 2025 at 03:33:03PM +0100, Jan Beulich wrote:
> On 18.03.2025 10:19, Roger Pau Monne wrote:
> > --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
> > +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
> > @@ -9,9 +9,9 @@
> >   * a secondary mapping installed, which needs to be used for such accesses in
> >   * the PV case, and will also be used for HVM to avoid extra conditionals.
> >   */
> > -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
> > -                                   (PERDOMAIN_ALT_VIRT_START - \
> > -                                    PERDOMAIN_VIRT_START))
> > +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> > +                                   (PERDOMAIN_VIRT_START - \
> > +                                    PERDOMAIN_ALT_VIRT_START))
> 
> Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
> and PERDOMAIN_ALT_VIRT_START? Would
> 
> #define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
>                                    PERDOMAIN_VIRT_START + \
>                                    PERDOMAIN_ALT_VIRT_START)
> 
> perhaps be less fragile?

PERDOMAIN_{ALT_,}VIRT_START are unsigned long, so this might work.

Note however that even with your suggestion we are still dependant on
ARG_XLAT_START(v) > PERDOMAIN_ALT_VIRT_START, or else the '-' won't
work.  I think I prefer my proposed version, because it's clear that
PERDOMAIN_VIRT_START, ARG_XLAT_START(current) >
PERDOMAIN_ALT_VIRT_START.  With your suggestion that's not obvious.

Thanks, Roger.
Jan Beulich March 18, 2025, 3:50 p.m. UTC | #4
On 18.03.2025 16:35, Roger Pau Monné wrote:
> On Tue, Mar 18, 2025 at 03:33:03PM +0100, Jan Beulich wrote:
>> On 18.03.2025 10:19, Roger Pau Monne wrote:
>>> --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
>>> +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
>>> @@ -9,9 +9,9 @@
>>>   * a secondary mapping installed, which needs to be used for such accesses in
>>>   * the PV case, and will also be used for HVM to avoid extra conditionals.
>>>   */
>>> -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
>>> -                                   (PERDOMAIN_ALT_VIRT_START - \
>>> -                                    PERDOMAIN_VIRT_START))
>>> +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
>>> +                                   (PERDOMAIN_VIRT_START - \
>>> +                                    PERDOMAIN_ALT_VIRT_START))
>>
>> Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
>> and PERDOMAIN_ALT_VIRT_START? Would
>>
>> #define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
>>                                    PERDOMAIN_VIRT_START + \
>>                                    PERDOMAIN_ALT_VIRT_START)
>>
>> perhaps be less fragile?
> 
> PERDOMAIN_{ALT_,}VIRT_START are unsigned long, so this might work.
> 
> Note however that even with your suggestion we are still dependant on
> ARG_XLAT_START(v) > PERDOMAIN_ALT_VIRT_START, or else the '-' won't
> work.  I think I prefer my proposed version, because it's clear that
> PERDOMAIN_VIRT_START, ARG_XLAT_START(current) >
> PERDOMAIN_ALT_VIRT_START.

What makes that clear? Can't we move PERDOMAIN_ALT_VIRT_START pretty
much at will?

Jan

>  With your suggestion that's not obvious.
> 
> Thanks, Roger.
Roger Pau Monne March 18, 2025, 4:47 p.m. UTC | #5
On Tue, Mar 18, 2025 at 04:50:58PM +0100, Jan Beulich wrote:
> On 18.03.2025 16:35, Roger Pau Monné wrote:
> > On Tue, Mar 18, 2025 at 03:33:03PM +0100, Jan Beulich wrote:
> >> On 18.03.2025 10:19, Roger Pau Monne wrote:
> >>> --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
> >>> +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
> >>> @@ -9,9 +9,9 @@
> >>>   * a secondary mapping installed, which needs to be used for such accesses in
> >>>   * the PV case, and will also be used for HVM to avoid extra conditionals.
> >>>   */
> >>> -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
> >>> -                                   (PERDOMAIN_ALT_VIRT_START - \
> >>> -                                    PERDOMAIN_VIRT_START))
> >>> +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> >>> +                                   (PERDOMAIN_VIRT_START - \
> >>> +                                    PERDOMAIN_ALT_VIRT_START))
> >>
> >> Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
> >> and PERDOMAIN_ALT_VIRT_START? Would
> >>
> >> #define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> >>                                    PERDOMAIN_VIRT_START + \
> >>                                    PERDOMAIN_ALT_VIRT_START)
> >>
> >> perhaps be less fragile?
> > 
> > PERDOMAIN_{ALT_,}VIRT_START are unsigned long, so this might work.
> > 
> > Note however that even with your suggestion we are still dependant on
> > ARG_XLAT_START(v) > PERDOMAIN_ALT_VIRT_START, or else the '-' won't
> > work.  I think I prefer my proposed version, because it's clear that
> > PERDOMAIN_VIRT_START, ARG_XLAT_START(current) >
> > PERDOMAIN_ALT_VIRT_START.
> 
> What makes that clear? Can't we move PERDOMAIN_ALT_VIRT_START pretty
> much at will?

We would need to adjust the calculations here again, if
PERDOMAIN_ALT_VIRT_START > PERDOMAIN_VIRT_START the subtraction would
lead to an underflow, and would also be UB pointer arithmetic?

Thanks, Roger.
Jan Beulich March 18, 2025, 5:01 p.m. UTC | #6
On 18.03.2025 17:47, Roger Pau Monné wrote:
> On Tue, Mar 18, 2025 at 04:50:58PM +0100, Jan Beulich wrote:
>> On 18.03.2025 16:35, Roger Pau Monné wrote:
>>> On Tue, Mar 18, 2025 at 03:33:03PM +0100, Jan Beulich wrote:
>>>> On 18.03.2025 10:19, Roger Pau Monne wrote:
>>>>> --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
>>>>> +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
>>>>> @@ -9,9 +9,9 @@
>>>>>   * a secondary mapping installed, which needs to be used for such accesses in
>>>>>   * the PV case, and will also be used for HVM to avoid extra conditionals.
>>>>>   */
>>>>> -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
>>>>> -                                   (PERDOMAIN_ALT_VIRT_START - \
>>>>> -                                    PERDOMAIN_VIRT_START))
>>>>> +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
>>>>> +                                   (PERDOMAIN_VIRT_START - \
>>>>> +                                    PERDOMAIN_ALT_VIRT_START))
>>>>
>>>> Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
>>>> and PERDOMAIN_ALT_VIRT_START? Would
>>>>
>>>> #define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
>>>>                                    PERDOMAIN_VIRT_START + \
>>>>                                    PERDOMAIN_ALT_VIRT_START)
>>>>
>>>> perhaps be less fragile?
>>>
>>> PERDOMAIN_{ALT_,}VIRT_START are unsigned long, so this might work.
>>>
>>> Note however that even with your suggestion we are still dependant on
>>> ARG_XLAT_START(v) > PERDOMAIN_ALT_VIRT_START, or else the '-' won't
>>> work.  I think I prefer my proposed version, because it's clear that
>>> PERDOMAIN_VIRT_START, ARG_XLAT_START(current) >
>>> PERDOMAIN_ALT_VIRT_START.
>>
>> What makes that clear? Can't we move PERDOMAIN_ALT_VIRT_START pretty
>> much at will?
> 
> We would need to adjust the calculations here again, if
> PERDOMAIN_ALT_VIRT_START > PERDOMAIN_VIRT_START the subtraction would
> lead to an underflow, and would also be UB pointer arithmetic?

With

#define ARG_XLAT_VIRT_START      PERDOMAIN_VIRT_SLOT(2)

I can't see how subtracting PERDOMAIN_VIRT_START could lead to an underflow.
The idea of the expression suggested is to first subtract the area base (no
underflow) and then add the other area's base (no overflow).

Jan
Roger Pau Monne March 18, 2025, 5:50 p.m. UTC | #7
On Tue, Mar 18, 2025 at 06:01:46PM +0100, Jan Beulich wrote:
> On 18.03.2025 17:47, Roger Pau Monné wrote:
> > On Tue, Mar 18, 2025 at 04:50:58PM +0100, Jan Beulich wrote:
> >> On 18.03.2025 16:35, Roger Pau Monné wrote:
> >>> On Tue, Mar 18, 2025 at 03:33:03PM +0100, Jan Beulich wrote:
> >>>> On 18.03.2025 10:19, Roger Pau Monne wrote:
> >>>>> --- a/xen/arch/x86/include/asm/x86_64/uaccess.h
> >>>>> +++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
> >>>>> @@ -9,9 +9,9 @@
> >>>>>   * a secondary mapping installed, which needs to be used for such accesses in
> >>>>>   * the PV case, and will also be used for HVM to avoid extra conditionals.
> >>>>>   */
> >>>>> -#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
> >>>>> -                                   (PERDOMAIN_ALT_VIRT_START - \
> >>>>> -                                    PERDOMAIN_VIRT_START))
> >>>>> +#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> >>>>> +                                   (PERDOMAIN_VIRT_START - \
> >>>>> +                                    PERDOMAIN_ALT_VIRT_START))
> >>>>
> >>>> Aren't we then (still) dependent on ordering between PERDOMAIN_VIRT_START
> >>>> and PERDOMAIN_ALT_VIRT_START? Would
> >>>>
> >>>> #define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
> >>>>                                    PERDOMAIN_VIRT_START + \
> >>>>                                    PERDOMAIN_ALT_VIRT_START)
> >>>>
> >>>> perhaps be less fragile?
> >>>
> >>> PERDOMAIN_{ALT_,}VIRT_START are unsigned long, so this might work.
> >>>
> >>> Note however that even with your suggestion we are still dependant on
> >>> ARG_XLAT_START(v) > PERDOMAIN_ALT_VIRT_START, or else the '-' won't
> >>> work.  I think I prefer my proposed version, because it's clear that
> >>> PERDOMAIN_VIRT_START, ARG_XLAT_START(current) >
> >>> PERDOMAIN_ALT_VIRT_START.
> >>
> >> What makes that clear? Can't we move PERDOMAIN_ALT_VIRT_START pretty
> >> much at will?
> > 
> > We would need to adjust the calculations here again, if
> > PERDOMAIN_ALT_VIRT_START > PERDOMAIN_VIRT_START the subtraction would
> > lead to an underflow, and would also be UB pointer arithmetic?
> 
> With
> 
> #define ARG_XLAT_VIRT_START      PERDOMAIN_VIRT_SLOT(2)
> 
> I can't see how subtracting PERDOMAIN_VIRT_START could lead to an underflow.
> The idea of the expression suggested is to first subtract the area base (no
> underflow) and then add the other area's base (no overflow).

Oh, right, I was reading it wrong sorry, somehow I was (still) seeing
a pair of braces around PERDOMAIN_VIRT_START +
PERDOMAIN_ALT_VIRT_START when there are none.  Yes, I will adjust to
your suggestion.

Thanks, Roger.
diff mbox series

Patch

diff --git a/xen/arch/x86/include/asm/x86_64/uaccess.h b/xen/arch/x86/include/asm/x86_64/uaccess.h
index c6fa3fd381bc..f933707e109f 100644
--- a/xen/arch/x86/include/asm/x86_64/uaccess.h
+++ b/xen/arch/x86/include/asm/x86_64/uaccess.h
@@ -9,9 +9,9 @@ 
  * a secondary mapping installed, which needs to be used for such accesses in
  * the PV case, and will also be used for HVM to avoid extra conditionals.
  */
-#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) + \
-                                   (PERDOMAIN_ALT_VIRT_START - \
-                                    PERDOMAIN_VIRT_START))
+#define COMPAT_ARG_XLAT_VIRT_BASE ((void *)ARG_XLAT_START(current) - \
+                                   (PERDOMAIN_VIRT_START - \
+                                    PERDOMAIN_ALT_VIRT_START))
 #define COMPAT_ARG_XLAT_SIZE      (2*PAGE_SIZE)
 struct vcpu;
 int setup_compat_arg_xlat(struct vcpu *v);