This is an archive of the discontinued LLVM Phabricator instance.

[Arm][libsanitizer] Fix arm libsanitizer failure with bleeding edge glibc
ClosedPublic

Authored by tnfchris on Oct 17 2019, 5:07 AM.

Details

Summary

Glibc has recently introduced changed to the mode field in ipc_perm in commit 2f959dfe849e0646e27403f2e4091536496ac0f0. For Arm this means that the mode field no longer has the same size.

This causes an assert failure against libsanitizer's internal copy of ipc_perm. Since this change can't be easily detected I am adding arm to the list of targets that are excluded from this check.

Diff Detail

Event Timeline

tnfchris created this revision.Oct 17 2019, 5:07 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptOct 17 2019, 5:07 AM
Herald added subscribers: llvm-commits, Restricted Project, kristof.beyls. · View Herald Transcript

Please update the patch with more context, i.e., run git diff -U99999 or something similar. See https://llvm.org/docs/Phabricator.html#requesting-a-review-via-the-web-interface

tnfchris updated this revision to Diff 225412.Oct 17 2019, 5:44 AM

Add more context, to diff.

eugenis accepted this revision.Oct 17 2019, 4:33 PM
eugenis added a subscriber: eugenis.

LGTM
We only really care about the size of struct shmid_ds AFAIK, not any of its fields individually.

This revision is now accepted and ready to land.Oct 17 2019, 4:33 PM
This revision was automatically updated to reflect the committed changes.

The change looks wrong, the upcoming glibc 2.31 changes aren't just about ARM, but actually most of the architectures, so adding a special case just for ARM is just weird.
Either we should change the structures to match what glibc 2.31 will have and disable this ipc_perm mode checking if not __GLIBC_PREREQ (2, 31) on SANITIZER_LINUX,
or the check needs to be disabled on most Linux architectures.
Affected are e.g. x86_64, i?86, riscv*, sparc 32-bit, s390 31-bit, arm. And, on arm big endian and s390 31-bit there is even an important ABI change, so shmctl interception
won't be able to use dlsym but will need to use dlvsym.
Completely untested patch would be something like:

  • sanitizer_common/sanitizer_platform_limits_posix.h 2019-11-07 17:56:23.530835549 +0100

+++ sanitizer_common/sanitizer_platform_limits_posix.h 2019-11-12 12:22:26.314511706 +0100
@@ -207,26 +207,13 @@ struct __sanitizer_ipc_perm {

u64 __unused1;                                                                                                                                  
u64 __unused2;

#elif defined(sparc)
-#if defined(arch64)

unsigned mode;
  • unsigned short __pad1;

-#else

  • unsigned short __pad1;
  • unsigned short mode; unsigned short __pad2;

-#endif

unsigned short __seq;                                                                                                                           
unsigned long long __unused1;                                                                                                                   
unsigned long long __unused2;

-#elif defined(mips) || defined(aarch64) || defined(s390x)

  • unsigned int mode;
  • unsigned short __seq;
  • unsigned short __pad1;
  • unsigned long __unused1;
  • unsigned long __unused2; #else
  • unsigned short mode;
  • unsigned short __pad1;

+ unsigned int mode;

unsigned short __seq;                                                                                                                           
unsigned short __pad2;

#if defined(x86_64) && !defined(_LP64)
---sanitizer_common/sanitizer_platform_limits_posix.cpp 2019-11-07 17:56:23.551835239 +0100
+++ sanitizer_common/sanitizer_platform_limits_posix.cpp 2019-11-12 12:23:42.959358844 +0100
@@ -1128,11 +1128,9 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
-#if (!defined(aarch64) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \

  • !defined(arm)

-/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */
-/* On Arm newer glibc provide a different mode field, it's hard to detect

  • so just disable the check. */

+#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
+/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
+ on most architectures. */
CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
#endif