[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: UBSan bug in real mode fpu emulation
- To: Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
- From: Manuel Andreas <manuel.andreas@xxxxxx>
- Date: Thu, 8 May 2025 12:14:19 +0200
- Authentication-results: postout.lrz.de (amavis); dkim=pass (2048-bit key) reason="pass (just generated, assumed good)" header.d=tum.de
- Autocrypt: addr=manuel.andreas@xxxxxx; keydata= xjMEY9Zx/RYJKwYBBAHaRw8BAQdALWzRzW9a74DX4l6i8VzXGvv72Vz0qfvj9s7bjBD905nN Jk1hbnVlbCBBbmRyZWFzIDxtYW51ZWwuYW5kcmVhc0B0dW0uZGU+wokEExYIADEWIQQuSfNX 11QV6exAUmOqZGwY4LuingUCY9Zx/QIbAwQLCQgHBRUICQoLBRYCAwEAAAoJEKpkbBjgu6Ke McQBAPyP530S365I50I5rM2XjH5Hr9YcUQATD5dusZJMDgejAP9T/wUurwQSuRfm1rK8cNcf w4wP3+PLvL+J+kuVku93CM44BGPWcf0SCisGAQQBl1UBBQEBB0AmCAf31tLBD5tvtdZ0XX1B yGLUAxhgmFskGyPhY8wOKQMBCAfCeAQYFggAIBYhBC5J81fXVBXp7EBSY6pkbBjgu6KeBQJj 1nH9AhsMAAoJEKpkbBjgu6Kej6YA/RvJdXMjsD5csifolLw53KX0/ElM22SvaGym1+KiiVND AQDy+y+bCXI+J713/AwLBsDxTEXmP7Cp49ZqbAu83NnpBQ==
- Cc: Fabian Specht <f.specht@xxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
- Delivery-date: Thu, 08 May 2025 10:14:38 +0000
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
On 4/25/25 11:11, Jan Beulich wrote:
On 24.04.2025 16:04, Andrew Cooper wrote:
I have a sneaking suspicion that this is sufficient:
diff --git a/xen/arch/x86/x86_emulate/private.h
b/xen/arch/x86/x86_emulate/private.h
index 30be59547032..9f3d6f0e5357 100644
--- a/xen/arch/x86/x86_emulate/private.h
+++ b/xen/arch/x86/x86_emulate/private.h
@@ -385,9 +385,9 @@ struct x87_env16 {
union {
struct {
uint16_t fip_lo;
- uint16_t fop:11, :1, fip_hi:4;
+ uint32_t fop:11, :1, fip_hi:4;
uint16_t fdp_lo;
- uint16_t :12, fdp_hi:4;
+ uint32_t :12, fdp_hi:4;
} real;
struct {
uint16_t fip;
The problem is that a uint16_t bitfield promotes into int. A base type
of uint32_t should cause the bitfield to promote into unsigned int directly.
I fear that's not gcc's way of thinking. In fact, the other involved structure
already uses bitfields with uint32_t base type, and the issue was reported
there nevertheless. Having known only compilers which respect declared type of
bitfields, I was rather surprised by gcc not doing so when I first started
using it on not exactly trivial code. Just to learn that they are free to do
so. Looks like I never dared to submit a patch I've been carrying to optionally
alter that behavior.
So I took some time to play around with this and you're definitely right
about GCC not respecting the declared type. Even in the struct
`x87_env32`, where the types are already declared as `uint32_t`, GCC
will just pick `short unsigned int` as the type for a 16-bit wide
bit-field. As such, in the offending left-shift expression the bit-field
will be promoted to an `int`, thereby causing the observed UB.
I could not find a way to make GCC actually pick a correctly sized
unsigned type in this context, without also modifying the width of the
bit-field. So I'm relatively sure the only way to fix this is to
properly adjust the usages of these bit-fields (as was suggested
previously).
For completeness sake I also checked how Clang deals with this issue and
the UB manifests in the same manner.
What's worse is that I didn't find any proper documentation on this
behavior for neither GCC or Clang. If you have anything I would be very
interested to know.
Best,
Manuel
|