Skip to content

Commit 14b0cff

Browse files
committed
Fix issue where CREAT flag was not properly passing mode (#23)
* Pass on CREAT mode propertly in open interceptors * Add unit tests * Remove two unneccessary bits * Fix fcntl
1 parent 17cbd59 commit 14b0cff

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

compiler-rt/lib/radsan/radsan_interceptors.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) {
5252
// TODO Establish whether we should intercept here if the flag contains
5353
// O_NONBLOCK
5454
__radsan::ExpectNotRealtime("open");
55+
5556
va_list args;
5657
va_start(args, oflag);
5758
const mode_t mode = va_arg(args, int);
@@ -65,6 +66,7 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
6566
// TODO Establish whether we should intercept here if the flag contains
6667
// O_NONBLOCK
6768
__radsan::ExpectNotRealtime("openat");
69+
6870
va_list args;
6971
va_start(args, oflag);
7072
mode_t mode = va_arg(args, int);
@@ -84,22 +86,13 @@ INTERCEPTOR(int, creat, const char *path, mode_t mode) {
8486

8587
INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
8688
__radsan::ExpectNotRealtime("fcntl");
89+
8790
va_list args;
8891
va_start(args, cmd);
89-
90-
// Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
91-
// final argument in a variable that will hold the largest of the possible
92-
// argument types (pointers and ints are typical in fcntl) It is then assumed
93-
// that the implementation of fcntl will cast it properly depending on cmd.
94-
//
95-
// This is also similar to what is done in
96-
// sanitizer_common/sanitizer_common_syscalls.inc
97-
const unsigned long arg = va_arg(args, unsigned long);
98-
int result = REAL(fcntl)(filedes, cmd, arg);
99-
92+
void *arg = va_arg(args, void *);
10093
va_end(args);
10194

102-
return result;
95+
return fcntl(filedes, cmd, arg);
10396
}
10497

10598
INTERCEPTOR(int, close, int filedes) {

compiler-rt/lib/radsan/tests/radsan_test_interceptors.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,22 @@ TEST(TestRadsanInterceptors, OpenatDiesWhenRealtime) {
204204
std::remove(TemporaryFilePath());
205205
}
206206

207+
TEST(TestRadsanInterceptors, openCreatesFileWithProperMode) {
208+
const int mode = S_IRGRP | S_IROTH | S_IRUSR | S_IWUSR;
209+
210+
const int fd = open(TemporaryFilePath(), O_CREAT | O_WRONLY, mode);
211+
ASSERT_THAT(fd, Ne(-1));
212+
close(fd);
213+
214+
struct stat st;
215+
ASSERT_THAT(stat(TemporaryFilePath(), &st), Eq(0));
216+
217+
// Mask st_mode to get permission bits only
218+
ASSERT_THAT(st.st_mode & 0777, Eq(mode));
219+
220+
std::remove(TemporaryFilePath());
221+
}
222+
207223
TEST(TestRadsanInterceptors, CreatDiesWhenRealtime) {
208224
auto Func = []() { creat(TemporaryFilePath(), S_IWOTH | S_IROTH); };
209225
ExpectRealtimeDeath(Func, "creat");
@@ -217,6 +233,28 @@ TEST(TestRadsanInterceptors, FcntlDiesWhenRealtime) {
217233
ExpectNonRealtimeSurvival(Func);
218234
}
219235

236+
TEST(TestRadsanInterceptors, FcntlFlockDiesWhenRealtime) {
237+
int fd = creat(TemporaryFilePath(), S_IRUSR | S_IWUSR);
238+
ASSERT_THAT(fd, Ne(-1));
239+
240+
auto func = [fd]() {
241+
struct flock lock {};
242+
lock.l_type = F_RDLCK;
243+
lock.l_whence = SEEK_SET;
244+
lock.l_start = 0;
245+
lock.l_len = 0;
246+
lock.l_pid = ::getpid();
247+
248+
ASSERT_THAT(fcntl(fd, F_GETLK, &lock), Eq(0));
249+
ASSERT_THAT(lock.l_type, F_UNLCK);
250+
};
251+
ExpectRealtimeDeath(func, "fcntl");
252+
ExpectNonRealtimeSurvival(func);
253+
254+
close(fd);
255+
std::remove(TemporaryFilePath());
256+
}
257+
220258
TEST(TestRadsanInterceptors, CloseDiesWhenRealtime) {
221259
auto Func = []() { close(0); };
222260
expectRealtimeDeath(Func, "close");

0 commit comments

Comments
 (0)