[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
This commit is contained in:
@@ -64,13 +64,15 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) {
|
||||
// O_NONBLOCK
|
||||
__rtsan_notify_intercepted_call("open");
|
||||
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (OpenReadsVaArgs(oflag)) {
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
return REAL(open)(path, oflag, mode);
|
||||
}
|
||||
|
||||
const int result = REAL(open)(path, oflag, mode);
|
||||
return result;
|
||||
return REAL(open)(path, oflag);
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_OPEN64
|
||||
@@ -79,13 +81,15 @@ INTERCEPTOR(int, open64, const char *path, int oflag, ...) {
|
||||
// O_NONBLOCK
|
||||
__rtsan_notify_intercepted_call("open64");
|
||||
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (OpenReadsVaArgs(oflag)) {
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
return REAL(open64)(path, oflag, mode);
|
||||
}
|
||||
|
||||
const int result = REAL(open64)(path, oflag, mode);
|
||||
return result;
|
||||
return REAL(open64)(path, oflag);
|
||||
}
|
||||
#define RTSAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
|
||||
#else
|
||||
@@ -97,13 +101,15 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
|
||||
// O_NONBLOCK
|
||||
__rtsan_notify_intercepted_call("openat");
|
||||
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (OpenReadsVaArgs(oflag)) {
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
return REAL(openat)(fd, path, oflag, mode);
|
||||
}
|
||||
|
||||
const int result = REAL(openat)(fd, path, oflag, mode);
|
||||
return result;
|
||||
return REAL(openat)(fd, path, oflag);
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_OPENAT64
|
||||
@@ -112,13 +118,15 @@ INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) {
|
||||
// O_NONBLOCK
|
||||
__rtsan_notify_intercepted_call("openat64");
|
||||
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
if (OpenReadsVaArgs(oflag)) {
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
const mode_t mode = va_arg(args, int);
|
||||
va_end(args);
|
||||
return REAL(openat64)(fd, path, oflag, mode);
|
||||
}
|
||||
|
||||
const int result = REAL(openat64)(fd, path, oflag, mode);
|
||||
return result;
|
||||
return REAL(openat64)(fd, path, oflag);
|
||||
}
|
||||
#define RTSAN_MAYBE_INTERCEPT_OPENAT64 INTERCEPT_FUNCTION(openat64)
|
||||
#else
|
||||
|
||||
@@ -353,7 +353,15 @@ bool ShouldMockFailureToOpen(const char *path) {
|
||||
internal_strncmp(path, "/proc/", 6) == 0;
|
||||
}
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
|
||||
bool OpenReadsVaArgs(int oflag) {
|
||||
# ifdef O_TMPFILE
|
||||
return (oflag & (O_CREAT | O_TMPFILE)) != 0;
|
||||
# else
|
||||
return (oflag & O_CREAT) != 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
# if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO
|
||||
int GetNamedMappingFd(const char *name, uptr size, int *flags) {
|
||||
if (!common_flags()->decorate_proc_maps || !name)
|
||||
return -1;
|
||||
|
||||
@@ -108,6 +108,7 @@ bool IsStateDetached(int state);
|
||||
fd_t ReserveStandardFds(fd_t fd);
|
||||
|
||||
bool ShouldMockFailureToOpen(const char *path);
|
||||
bool OpenReadsVaArgs(int oflag);
|
||||
|
||||
// Create a non-file mapping with a given /proc/self/maps name.
|
||||
uptr MmapNamed(void *addr, uptr length, int prot, int flags, const char *name);
|
||||
|
||||
@@ -1680,13 +1680,23 @@ TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) {
|
||||
#endif
|
||||
|
||||
TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, oflag);
|
||||
mode_t mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
mode_t mode = 0;
|
||||
if (OpenReadsVaArgs(oflag)) {
|
||||
va_list ap;
|
||||
va_start(ap, oflag);
|
||||
mode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
SCOPED_TSAN_INTERCEPTOR(open, name, oflag, mode);
|
||||
READ_STRING(thr, pc, name, 0);
|
||||
int fd = REAL(open)(name, oflag, mode);
|
||||
|
||||
int fd;
|
||||
if (OpenReadsVaArgs(oflag))
|
||||
fd = REAL(open)(name, oflag, mode);
|
||||
else
|
||||
fd = REAL(open)(name, oflag);
|
||||
|
||||
if (fd >= 0)
|
||||
FdFileCreate(thr, pc, fd);
|
||||
return fd;
|
||||
|
||||
Reference in New Issue
Block a user