Skip to content

Commit a4232dc

Browse files
authored
[rtsan][tsan] Fix va_args handling in open functions (#108291)
Check oflag to see if it contains O_CREAT / O_TMPFILE before unpacking parameters to avoid UB
1 parent d6a6e25 commit a4232dc

File tree

4 files changed

+57
-30
lines changed

4 files changed

+57
-30
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors.cpp

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,15 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) {
6464
// O_NONBLOCK
6565
__rtsan_notify_intercepted_call("open");
6666

67-
va_list args;
68-
va_start(args, oflag);
69-
const mode_t mode = va_arg(args, int);
70-
va_end(args);
67+
if (OpenReadsVaArgs(oflag)) {
68+
va_list args;
69+
va_start(args, oflag);
70+
const mode_t mode = va_arg(args, int);
71+
va_end(args);
72+
return REAL(open)(path, oflag, mode);
73+
}
7174

72-
const int result = REAL(open)(path, oflag, mode);
73-
return result;
75+
return REAL(open)(path, oflag);
7476
}
7577

7678
#if SANITIZER_INTERCEPT_OPEN64
@@ -79,13 +81,15 @@ INTERCEPTOR(int, open64, const char *path, int oflag, ...) {
7981
// O_NONBLOCK
8082
__rtsan_notify_intercepted_call("open64");
8183

82-
va_list args;
83-
va_start(args, oflag);
84-
const mode_t mode = va_arg(args, int);
85-
va_end(args);
84+
if (OpenReadsVaArgs(oflag)) {
85+
va_list args;
86+
va_start(args, oflag);
87+
const mode_t mode = va_arg(args, int);
88+
va_end(args);
89+
return REAL(open64)(path, oflag, mode);
90+
}
8691

87-
const int result = REAL(open64)(path, oflag, mode);
88-
return result;
92+
return REAL(open64)(path, oflag);
8993
}
9094
#define RTSAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
9195
#else
@@ -97,13 +101,15 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
97101
// O_NONBLOCK
98102
__rtsan_notify_intercepted_call("openat");
99103

100-
va_list args;
101-
va_start(args, oflag);
102-
mode_t mode = va_arg(args, int);
103-
va_end(args);
104+
if (OpenReadsVaArgs(oflag)) {
105+
va_list args;
106+
va_start(args, oflag);
107+
const mode_t mode = va_arg(args, int);
108+
va_end(args);
109+
return REAL(openat)(fd, path, oflag, mode);
110+
}
104111

105-
const int result = REAL(openat)(fd, path, oflag, mode);
106-
return result;
112+
return REAL(openat)(fd, path, oflag);
107113
}
108114

109115
#if SANITIZER_INTERCEPT_OPENAT64
@@ -112,13 +118,15 @@ INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) {
112118
// O_NONBLOCK
113119
__rtsan_notify_intercepted_call("openat64");
114120

115-
va_list args;
116-
va_start(args, oflag);
117-
mode_t mode = va_arg(args, int);
118-
va_end(args);
121+
if (OpenReadsVaArgs(oflag)) {
122+
va_list args;
123+
va_start(args, oflag);
124+
const mode_t mode = va_arg(args, int);
125+
va_end(args);
126+
return REAL(openat64)(fd, path, oflag, mode);
127+
}
119128

120-
const int result = REAL(openat64)(fd, path, oflag, mode);
121-
return result;
129+
return REAL(openat64)(fd, path, oflag);
122130
}
123131
#define RTSAN_MAYBE_INTERCEPT_OPENAT64 INTERCEPT_FUNCTION(openat64)
124132
#else

compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,15 @@ bool ShouldMockFailureToOpen(const char *path) {
353353
internal_strncmp(path, "/proc/", 6) == 0;
354354
}
355355

356-
#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
356+
bool OpenReadsVaArgs(int oflag) {
357+
# ifdef O_TMPFILE
358+
return (oflag & (O_CREAT | O_TMPFILE)) != 0;
359+
# else
360+
return (oflag & O_CREAT) != 0;
361+
# endif
362+
}
363+
364+
# if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
357365
int GetNamedMappingFd(const char *name, uptr size, int *flags) {
358366
if (!common_flags()->decorate_proc_maps || !name)
359367
return -1;

compiler-rt/lib/sanitizer_common/sanitizer_posix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ bool IsStateDetached(int state);
108108
fd_t ReserveStandardFds(fd_t fd);
109109

110110
bool ShouldMockFailureToOpen(const char *path);
111+
bool OpenReadsVaArgs(int oflag);
111112

112113
// Create a non-file mapping with a given /proc/self/maps name.
113114
uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);

compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,13 +1680,23 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
16801680
#endif
16811681

16821682
TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
1683-
va_list ap;
1684-
va_start(ap, oflag);
1685-
mode_t mode = va_arg(ap, int);
1686-
va_end(ap);
1683+
mode_t mode = 0;
1684+
if (OpenReadsVaArgs(oflag)) {
1685+
va_list ap;
1686+
va_start(ap, oflag);
1687+
mode = va_arg(ap, int);
1688+
va_end(ap);
1689+
}
1690+
16871691
SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);
16881692
READ_STRING(thr, pc, name, 0);
1689-
int fd = REAL(open)(name, oflag, mode);
1693+
1694+
int fd;
1695+
if (OpenReadsVaArgs(oflag))
1696+
fd = REAL(open)(name, oflag, mode);
1697+
else
1698+
fd = REAL(open)(name, oflag);
1699+
16901700
if (fd >= 0)
16911701
FdFileCreate(thr, pc, fd);
16921702
return fd;

0 commit comments

Comments
 (0)