Skip to content

Commit 5565fe2

Browse files
committed
[rtsan] Add ioctl interceptor
1 parent a12e79a commit 5565fe2

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,23 @@ INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
190190
return REAL(fcntl)(filedes, cmd, arg);
191191
}
192192

193+
INTERCEPTOR(int, ioctl, int filedes, unsigned long request, ...) {
194+
__rtsan_notify_intercepted_call("ioctl");
195+
196+
// See fcntl for discussion on why we use intptr_t
197+
// And why we read from va_args on all request types
198+
using arg_type = intptr_t;
199+
static_assert(sizeof(arg_type) >= sizeof(struct ifreq *));
200+
static_assert(sizeof(arg_type) >= sizeof(int));
201+
202+
va_list args;
203+
va_start(args, request);
204+
arg_type arg = va_arg(args, arg_type);
205+
va_end(args);
206+
207+
return REAL(ioctl)(filedes, request, arg);
208+
}
209+
193210
#if SANITIZER_INTERCEPT_FCNTL64
194211
INTERCEPTOR(int, fcntl64, int filedes, int cmd, ...) {
195212
__rtsan_notify_intercepted_call("fcntl64");
@@ -801,6 +818,7 @@ void __rtsan::InitializeInterceptors() {
801818
RTSAN_MAYBE_INTERCEPT_LSEEK64;
802819
INTERCEPT_FUNCTION(dup);
803820
INTERCEPT_FUNCTION(dup2);
821+
INTERCEPT_FUNCTION(ioctl);
804822

805823
#if SANITIZER_APPLE
806824
INTERCEPT_FUNCTION(OSSpinLockLock);

compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#if SANITIZER_APPLE
2121
#include <libkern/OSAtomic.h>
2222
#include <os/lock.h>
23-
#include <sys/types.h>
2423
#include <unistd.h>
2524
#endif
2625

@@ -38,12 +37,16 @@
3837
#endif
3938

4039
#include <fcntl.h>
40+
#include <ifaddrs.h>
41+
#include <net/if.h>
4142
#include <netdb.h>
4243
#include <poll.h>
4344
#include <pthread.h>
4445
#include <stdio.h>
46+
#include <sys/ioctl.h>
4547
#include <sys/mman.h>
4648
#include <sys/socket.h>
49+
#include <sys/types.h>
4750
#include <sys/uio.h>
4851

4952
#if _FILE_OFFSET_BITS == 64 && SANITIZER_GLIBC
@@ -245,7 +248,6 @@ TEST(TestRtsanInterceptors, SchedYieldDiesWhenRealtime) {
245248
/*
246249
Filesystem
247250
*/
248-
249251
TEST_F(RtsanFileTest, OpenDiesWhenRealtime) {
250252
auto Func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); };
251253
ExpectRealtimeDeath(Func, MAYBE_APPEND_64("open"));
@@ -373,6 +375,57 @@ class RtsanOpenedFileTest : public RtsanFileTest {
373375
int fd = -1;
374376
};
375377

378+
TEST(TestRtsanInterceptors, IoctlDiesWhenRealtime) {
379+
auto Func = []() { ioctl(0, FIONREAD); };
380+
ExpectRealtimeDeath(Func, "ioctl");
381+
ExpectNonRealtimeSurvival(Func);
382+
}
383+
384+
TEST_F(RtsanOpenedFileTest, IoctlBehavesWithOutputArg) {
385+
int arg{};
386+
ioctl(GetOpenFd(), FIONREAD, &arg);
387+
388+
EXPECT_THAT(arg, Ge(0));
389+
}
390+
391+
TEST(TestRtsanInterceptors, IoctlBehavesWithOutputPointer) {
392+
// These initial checks just see if we CAN run these tests.
393+
// If we can't (can't open a socket, or can't find an interface, just
394+
// gracefully skip.
395+
int sock = socket(AF_INET, SOCK_STREAM, 0);
396+
if (sock == -1) {
397+
perror("socket");
398+
GTEST_SKIP();
399+
return;
400+
}
401+
402+
struct ifaddrs *ifaddr = nullptr;
403+
if (getifaddrs(&ifaddr) == -1 || ifaddr == nullptr) {
404+
perror("getifaddrs");
405+
close(sock);
406+
GTEST_SKIP();
407+
return;
408+
}
409+
410+
struct ifreq ifr {};
411+
strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1);
412+
413+
int retval = ioctl(sock, SIOCGIFADDR, &ifr);
414+
if (retval == -1) {
415+
perror("ioctl");
416+
close(sock);
417+
freeifaddrs(ifaddr);
418+
ASSERT_TRUE(false) << "ioctl failed";
419+
return;
420+
}
421+
422+
freeifaddrs(ifaddr);
423+
close(sock);
424+
425+
ASSERT_THAT(ifr.ifr_addr.sa_data, NotNull());
426+
ASSERT_THAT(ifr.ifr_addr.sa_family, Eq(AF_INET));
427+
}
428+
376429
TEST_F(RtsanOpenedFileTest, LseekDiesWhenRealtime) {
377430
auto Func = [this]() { lseek(GetOpenFd(), 0, SEEK_SET); };
378431
ExpectRealtimeDeath(Func, MAYBE_APPEND_64("lseek"));

0 commit comments

Comments
 (0)