[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




 


Rackspace

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