Skip to content

Commit baa7aca

Browse files
committed
[rtsan] Fix comment about fcntl, fix va_args type
1 parent 5a2071b commit baa7aca

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,38 @@ INTERCEPTOR(int, creat, const char *path, mode_t mode) {
9898
INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
9999
__rtsan_expect_not_realtime("fcntl");
100100

101-
va_list args;
102-
va_start(args, cmd);
103-
104101
// Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
105102
// final argument in a variable that will hold the largest of the possible
106-
// argument types (pointers and ints are typical in fcntl) It is then assumed
107-
// that the implementation of fcntl will cast it properly depending on cmd.
103+
// argument types. It is then assumed that the implementation of fcntl will
104+
// cast it properly depending on cmd.
105+
//
106+
// The two types we expect for possible args are `struct flock*` and `int`
107+
// we will cast to `intptr_t` which should hold both comfortably.
108+
// Why `intptr_t`? It should fit both types, and it follows the freeBSD
109+
// approach linked below.
110+
using arg_type = intptr_t;
111+
static_assert(sizeof(arg_type) >= sizeof(struct flock *));
112+
static_assert(sizeof(arg_type) >= sizeof(int));
113+
114+
// Some cmds will not actually have an argument passed in this va_list.
115+
// Calling va_arg when no arg exists is UB, however all currently
116+
// supported architectures will give us a result in all three cases
117+
// (no arg/int arg/struct flock* arg)
118+
// va_arg() will generally read the next argument register or the
119+
// stack. If we ever support an arch like CHERI with bounds checking, we
120+
// may have to re-evaluate this approach.
108121
//
109-
// This is also similar to what is done in
110-
// sanitizer_common/sanitizer_common_syscalls.inc
111-
const unsigned long arg = va_arg(args, unsigned long);
112-
int result = REAL(fcntl)(filedes, cmd, arg);
122+
// More discussion, and other examples following this approach
123+
// https://discourse.llvm.org/t/how-to-write-an-interceptor-for-fcntl/81203
124+
// https://reviews.freebsd.org/D46403
125+
// https://github.com/bminor/glibc/blob/c444cc1d8335243c5c4e636d6a26c472df85522c/sysdeps/unix/sysv/linux/fcntl64.c#L37-L46
113126

127+
va_list args;
128+
va_start(args, cmd);
129+
const arg_type arg = va_arg(args, arg_type);
114130
va_end(args);
115131

116-
return result;
132+
return REAL(fcntl)(filedes, cmd, arg);
117133
}
118134

119135
INTERCEPTOR(int, close, int filedes) {

0 commit comments

Comments
 (0)