Skip to content

Commit 1298273

Browse files
committed
msan: account for AVX state when unpoison ucontext_t
ucontext_t can be larger than its static size if it contains AVX state and YMM/ZMM registers. Currently a signal handler that tries to access that state can produce false positives with random origins on stack. Account for the additional ucontext_t state. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D116208
1 parent ea83517 commit 1298273

11 files changed

+69
-16
lines changed

compiler-rt/lib/msan/msan_interceptors.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ static void SignalAction(int signo, void *si, void *uc) {
990990
ScopedThreadLocalStateBackup stlsb;
991991
UnpoisonParam(3);
992992
__msan_unpoison(si, sizeof(__sanitizer_sigaction));
993-
__msan_unpoison(uc, __sanitizer::ucontext_t_sz);
993+
__msan_unpoison(uc, ucontext_t_sz(uc));
994994

995995
typedef void (*sigaction_cb)(int, void *, void *);
996996
sigaction_cb cb =

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ unsigned struct_sigevent_sz = sizeof(struct sigevent);
130130
unsigned struct_sched_param_sz = sizeof(struct sched_param);
131131
unsigned struct_statfs_sz = sizeof(struct statfs);
132132
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
133-
unsigned ucontext_t_sz = sizeof(ucontext_t);
133+
unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
134134
unsigned struct_rlimit_sz = sizeof(struct rlimit);
135135
unsigned struct_timespec_sz = sizeof(struct timespec);
136136
unsigned struct_utimbuf_sz = sizeof(struct utimbuf);

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ extern unsigned struct_sched_param_sz;
5757
extern unsigned struct_statfs64_sz;
5858
extern unsigned struct_statfs_sz;
5959
extern unsigned struct_sockaddr_sz;
60-
extern unsigned ucontext_t_sz;
60+
unsigned ucontext_t_sz(void *ctx);
6161
extern unsigned struct_rlimit_sz;
6262
extern unsigned struct_utimbuf_sz;
6363
extern unsigned struct_timespec_sz;

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ unsigned struct_tms_sz = sizeof(struct tms);
554554
unsigned struct_sigevent_sz = sizeof(struct sigevent);
555555
unsigned struct_sched_param_sz = sizeof(struct sched_param);
556556
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
557-
unsigned ucontext_t_sz = sizeof(ucontext_t);
557+
unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
558558
unsigned struct_rlimit_sz = sizeof(struct rlimit);
559559
unsigned struct_timespec_sz = sizeof(struct timespec);
560560
unsigned struct_sembuf_sz = sizeof(struct sembuf);

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern unsigned struct_stack_t_sz;
4545
extern unsigned struct_sched_param_sz;
4646
extern unsigned struct_statfs_sz;
4747
extern unsigned struct_sockaddr_sz;
48-
extern unsigned ucontext_t_sz;
48+
unsigned ucontext_t_sz(void *ctx);
4949

5050
extern unsigned struct_rlimit_sz;
5151
extern unsigned struct_utimbuf_sz;

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ typedef struct user_fpregs elf_fpregset_t;
173173
#include "sanitizer_internal_defs.h"
174174
#include "sanitizer_platform_limits_posix.h"
175175

176+
// To prevent macro redefinition warning between our sanitizer_thread_safety.h
177+
// and system's scsi.h.
178+
# undef RELEASE
179+
# include "sanitizer_common.h"
180+
176181
namespace __sanitizer {
177182
unsigned struct_utsname_sz = sizeof(struct utsname);
178183
unsigned struct_stat_sz = sizeof(struct stat);
@@ -214,10 +219,20 @@ namespace __sanitizer {
214219
#if !SANITIZER_ANDROID
215220
unsigned struct_statfs_sz = sizeof(struct statfs);
216221
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
217-
unsigned ucontext_t_sz = sizeof(ucontext_t);
218-
#endif // !SANITIZER_ANDROID
219222

220-
#if SANITIZER_LINUX
223+
unsigned ucontext_t_sz(void *ctx) {
224+
# if SANITIZER_LINUX && SANITIZER_X64
225+
// See kernel arch/x86/kernel/fpu/signal.c for details.
226+
const auto *fpregs = static_cast<ucontext_t *>(ctx)->uc_mcontext.fpregs;
227+
if (fpregs->__glibc_reserved1[12] == FP_XSTATE_MAGIC1)
228+
return reinterpret_cast<const char *>(fpregs) +
229+
fpregs->__glibc_reserved1[13] - static_cast<const char *>(ctx);
230+
# endif
231+
return sizeof(ucontext_t);
232+
}
233+
# endif // !SANITIZER_ANDROID
234+
235+
# if SANITIZER_LINUX
221236
unsigned struct_epoll_event_sz = sizeof(struct epoll_event);
222237
unsigned struct_sysinfo_sz = sizeof(struct sysinfo);
223238
unsigned __user_cap_header_struct_sz =

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ extern unsigned struct_regmatch_sz;
5757
extern unsigned struct_fstab_sz;
5858
extern unsigned struct_statfs_sz;
5959
extern unsigned struct_sockaddr_sz;
60-
extern unsigned ucontext_t_sz;
61-
#endif // !SANITIZER_ANDROID
60+
unsigned ucontext_t_sz(void *uctx);
61+
# endif // !SANITIZER_ANDROID
6262

63-
#if SANITIZER_LINUX
63+
# if SANITIZER_LINUX
6464

65-
#if defined(__x86_64__)
65+
# if defined(__x86_64__)
6666
const unsigned struct_kernel_stat_sz = 144;
6767
const unsigned struct_kernel_stat64_sz = 0;
6868
#elif defined(__i386__)

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ namespace __sanitizer {
8989
unsigned struct_sched_param_sz = sizeof(struct sched_param);
9090
unsigned struct_statfs_sz = sizeof(struct statfs);
9191
unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
92-
unsigned ucontext_t_sz = sizeof(ucontext_t);
92+
unsigned ucontext_t_sz(void *ctx) { return sizeof(ucontext_t); }
9393
unsigned struct_timespec_sz = sizeof(struct timespec);
9494
#if SANITIZER_SOLARIS32
9595
unsigned struct_statvfs64_sz = sizeof(struct statvfs64);

compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_solaris.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ extern unsigned struct_sched_param_sz;
4343
extern unsigned struct_statfs64_sz;
4444
extern unsigned struct_statfs_sz;
4545
extern unsigned struct_sockaddr_sz;
46-
extern unsigned ucontext_t_sz;
46+
unsigned ucontext_t_sz(void *ctx);
4747

4848
extern unsigned struct_timespec_sz;
4949
extern unsigned struct_rlimit_sz;

compiler-rt/lib/sanitizer_common/sanitizer_syscalls_netbsd.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,13 +2255,13 @@ PRE_SYSCALL(getcontext)(void *ucp_) { /* Nothing to do */ }
22552255
POST_SYSCALL(getcontext)(long long res, void *ucp_) { /* Nothing to do */ }
22562256
PRE_SYSCALL(setcontext)(void *ucp_) {
22572257
if (ucp_) {
2258-
PRE_READ(ucp_, ucontext_t_sz);
2258+
PRE_READ(ucp_, ucontext_t_sz(ucp_));
22592259
}
22602260
}
22612261
POST_SYSCALL(setcontext)(long long res, void *ucp_) {}
22622262
PRE_SYSCALL(_lwp_create)(void *ucp_, long long flags_, void *new_lwp_) {
22632263
if (ucp_) {
2264-
PRE_READ(ucp_, ucontext_t_sz);
2264+
PRE_READ(ucp_, ucontext_t_sz(ucp_));
22652265
}
22662266
}
22672267
POST_SYSCALL(_lwp_create)

0 commit comments

Comments
 (0)