[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:
Chris Apple
2024-09-23 07:55:14 -06:00
committed by GitHub
parent d6a6e25c51
commit a4232dc676
4 changed files with 57 additions and 30 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;