-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Sanitizers] Avoid overload ambiguity for interceptors #100986
Conversation
Since glibc 2.40 some functions like openat make use of overloads when built with `-D_FORTIFY_SOURCE=2`, see: https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h This means that doing something like `(uintptr_t) openat` or `(void *) openat` is now ambiguous, breaking the compiler-rt build on new glibc versions. Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as `decltype(REAL(func))` so we don't have to repeat the signature from INTERCEPTOR in the INTERCEPT_FUNTION macro.
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Nikita Popov (nikic) ChangesSince glibc 2.40 some functions like openat make use of overloads when built with This means that doing something like Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as Fixes #100754. Full diff: https://github.com/llvm/llvm-project/pull/100986.diff 1 Files Affected:
diff --git a/compiler-rt/lib/interception/interception_linux.h b/compiler-rt/lib/interception/interception_linux.h
index 433a3d9bd7fa7..2e01ff44578c3 100644
--- a/compiler-rt/lib/interception/interception_linux.h
+++ b/compiler-rt/lib/interception/interception_linux.h
@@ -28,12 +28,14 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
uptr func, uptr trampoline);
} // namespace __interception
-#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
- ::__interception::InterceptFunction( \
- #func, \
- (::__interception::uptr *)&REAL(func), \
- (::__interception::uptr)&(func), \
- (::__interception::uptr)&TRAMPOLINE(func))
+// Cast func to type of REAL(func) before casting to uptr in case it is an
+// overloaded function, which is the case for some glibc functions when
+// _FORTIFY_SOURCE is used. This disambiguates which overload to use.
+#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
+ ::__interception::InterceptFunction( \
+ #func, (::__interception::uptr *)&REAL(func), \
+ (::__interception::uptr)(decltype(REAL(func)))&(func), \
+ (::__interception::uptr) &TRAMPOLINE(func))
// dlvsym is a GNU extension supported by some other platforms.
#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
@@ -41,7 +43,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
::__interception::InterceptFunction( \
#func, symver, \
(::__interception::uptr *)&REAL(func), \
- (::__interception::uptr)&(func), \
+ (::__interception::uptr)(decltype(REAL(func)))&(func), \
(::__interception::uptr)&TRAMPOLINE(func))
#else
#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
|
You can test this locally with the following command:git-clang-format --diff 73c72f2c6505d5bc8b47bb0420f6cba5b24270fe 256149db05b803f22e7baadbccb8c0c097c7ee27 --extensions h -- compiler-rt/lib/interception/interception_linux.h View the diff from clang-format here.diff --git a/compiler-rt/lib/interception/interception_linux.h b/compiler-rt/lib/interception/interception_linux.h
index 2e01ff4457..0f0724419a 100644
--- a/compiler-rt/lib/interception/interception_linux.h
+++ b/compiler-rt/lib/interception/interception_linux.h
@@ -31,20 +31,19 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real,
// Cast func to type of REAL(func) before casting to uptr in case it is an
// overloaded function, which is the case for some glibc functions when
// _FORTIFY_SOURCE is used. This disambiguates which overload to use.
-#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
- ::__interception::InterceptFunction( \
- #func, (::__interception::uptr *)&REAL(func), \
- (::__interception::uptr)(decltype(REAL(func)))&(func), \
- (::__interception::uptr) &TRAMPOLINE(func))
+# define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \
+ ::__interception::InterceptFunction( \
+ #func, (::__interception::uptr *)&REAL(func), \
+ (::__interception::uptr)(decltype(REAL(func)))&(func), \
+ (::__interception::uptr) & TRAMPOLINE(func))
// dlvsym is a GNU extension supported by some other platforms.
#if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD
-#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
- ::__interception::InterceptFunction( \
- #func, symver, \
- (::__interception::uptr *)&REAL(func), \
- (::__interception::uptr)(decltype(REAL(func)))&(func), \
- (::__interception::uptr)&TRAMPOLINE(func))
+# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+ ::__interception::InterceptFunction( \
+ #func, symver, (::__interception::uptr *)&REAL(func), \
+ (::__interception::uptr)(decltype(REAL(func)))&(func), \
+ (::__interception::uptr) & TRAMPOLINE(func))
#else
#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
|
I can confirm that this fixes the build failure on Gentoo. |
Excellent. Thank you from the rtsan team @nikic! |
/cherry-pick 155b7a1 |
Since glibc 2.40 some functions like openat make use of overloads when built with `-D_FORTIFY_SOURCE=2`, see: https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h This means that doing something like `(uintptr_t) openat` or `(void *) openat` is now ambiguous, breaking the compiler-rt build on new glibc versions. Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as `decltype(REAL(func))` so we don't have to repeat the signature from INTERCEPTOR in the INTERCEPT_FUNTION macro. Fixes llvm#100754. (cherry picked from commit 155b7a1)
/pull-request #101150 |
Since glibc 2.40 some functions like openat make use of overloads when built with `-D_FORTIFY_SOURCE=2`, see: https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h This means that doing something like `(uintptr_t) openat` or `(void *) openat` is now ambiguous, breaking the compiler-rt build on new glibc versions. Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as `decltype(REAL(func))` so we don't have to repeat the signature from INTERCEPTOR in the INTERCEPT_FUNTION macro. Fixes llvm#100754. (cherry picked from commit 155b7a1)
Since glibc 2.40 some functions like openat make use of overloads when built with `-D_FORTIFY_SOURCE=2`, see: https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h This means that doing something like `(uintptr_t) openat` or `(void *) openat` is now ambiguous, breaking the compiler-rt build on new glibc versions. Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as `decltype(REAL(func))` so we don't have to repeat the signature from INTERCEPTOR in the INTERCEPT_FUNTION macro. Fixes llvm#100754.
Since glibc 2.40 some functions like openat make use of overloads when built with
-D_FORTIFY_SOURCE=2
, see:https://github.com/bminor/glibc/blob/master/io/bits/fcntl2.h
This means that doing something like
(uintptr_t) openat
or(void *) openat
is now ambiguous, breaking the compiler-rt build on new glibc versions.Fix this by explicitly casting the symbol to the expected function type before casting it to an intptr. The expected type is obtained as
decltype(REAL(func))
so we don't have to repeat the signature from INTERCEPTOR in the INTERCEPT_FUNTION macro.Fixes #100754.