forked from OSchip/llvm-project
parent
686c229b03
commit
fbea5b95c6
|
@ -40,6 +40,7 @@ set(SANITIZER_HEADERS
|
|||
sanitizer_atomic.h
|
||||
sanitizer_common.h
|
||||
sanitizer_common_interceptors.inc
|
||||
sanitizer_common_interceptors_ioctl.inc
|
||||
sanitizer_common_interceptors_scanf.inc
|
||||
sanitizer_common_syscalls.inc
|
||||
sanitizer_flags.h
|
||||
|
|
|
@ -130,6 +130,26 @@ static void ioctl_table_fill() {
|
|||
_(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz);
|
||||
_(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz);
|
||||
_(CDROM_GET_UPC, WRITE, 8);
|
||||
_(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup
|
||||
_(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup
|
||||
_(EVIOCGEFFECTS, WRITE, sizeof(int));
|
||||
_(EVIOCGID, WRITE, struct_input_id_sz);
|
||||
_(EVIOCGKEY, WRITE, 0);
|
||||
_(EVIOCGKEYCODE, WRITE, sizeof(int) * 2);
|
||||
_(EVIOCGLED, WRITE, 0);
|
||||
_(EVIOCGNAME, WRITE, 0);
|
||||
_(EVIOCGPHYS, WRITE, 0);
|
||||
_(EVIOCGRAB, READ, sizeof(int));
|
||||
_(EVIOCGREP, WRITE, sizeof(int) * 2);
|
||||
_(EVIOCGSND, WRITE, 0);
|
||||
_(EVIOCGSW, WRITE, 0);
|
||||
_(EVIOCGUNIQ, WRITE, 0);
|
||||
_(EVIOCGVERSION, WRITE, sizeof(int));
|
||||
_(EVIOCRMFF, READ, sizeof(int));
|
||||
_(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup
|
||||
_(EVIOCSFF, READ, struct_ff_effect_sz);
|
||||
_(EVIOCSKEYCODE, READ, sizeof(int) * 2);
|
||||
_(EVIOCSREP, READ, sizeof(int) * 2);
|
||||
_(FDCLRPRM, NONE, 0);
|
||||
_(FDDEFPRM, READ, struct_floppy_struct_sz);
|
||||
_(FDFLUSH, NONE, 0);
|
||||
|
@ -350,6 +370,9 @@ static void ioctl_table_fill() {
|
|||
_(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz);
|
||||
_(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz);
|
||||
_(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz);
|
||||
_(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz);
|
||||
_(EVIOCGPROP, WRITE, 0);
|
||||
_(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz);
|
||||
_(FS_IOC_GETFLAGS, WRITE, sizeof(int));
|
||||
_(FS_IOC_GETVERSION, WRITE, sizeof(int));
|
||||
_(FS_IOC_SETFLAGS, READ, sizeof(int));
|
||||
|
@ -463,7 +486,18 @@ static void ioctl_init() {
|
|||
ioctl_initialized = true;
|
||||
}
|
||||
|
||||
static const ioctl_desc *ioctl_lookup(unsigned req) {
|
||||
// Handle the most evil ioctls that encode argument value as part of request id.
|
||||
static unsigned ioctl_request_fixup(unsigned req) {
|
||||
if ((req & ~0x3fff001fU) == IOCTL_EVIOCGBIT)
|
||||
return IOCTL_EVIOCGBIT;
|
||||
if ((req & ~0x3fU) == IOCTL_EVIOCGABS)
|
||||
return IOCTL_EVIOCGABS;
|
||||
if ((req & ~0x3fU) == IOCTL_EVIOCSABS)
|
||||
return IOCTL_EVIOCSABS;
|
||||
return req;
|
||||
}
|
||||
|
||||
static const ioctl_desc *ioctl_table_lookup(unsigned req) {
|
||||
int left = 0;
|
||||
int right = ioctl_table_size;
|
||||
while (left < right) {
|
||||
|
@ -479,10 +513,27 @@ static const ioctl_desc *ioctl_lookup(unsigned req) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const ioctl_desc *ioctl_lookup(unsigned req) {
|
||||
req = ioctl_request_fixup(req);
|
||||
const ioctl_desc *desc = ioctl_table_lookup(req);
|
||||
if (desc) return desc;
|
||||
|
||||
// Try stripping access size from the request id.
|
||||
desc = ioctl_table_lookup(req & ~0x3fff0000U);
|
||||
// Sanity check: requests that encode access size are either read or write and
|
||||
// have size of 0 in the table.
|
||||
if (desc && desc->size == 0 &&
|
||||
(desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READ))
|
||||
return desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
|
||||
unsigned request, void *arg) {
|
||||
if (desc->type == ioctl_desc::READ)
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, desc->size);
|
||||
if (desc->type == ioctl_desc::READ) {
|
||||
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
|
||||
}
|
||||
if (desc->type != ioctl_desc::CUSTOM)
|
||||
return;
|
||||
switch (request) {
|
||||
|
@ -499,7 +550,8 @@ static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
|
|||
unsigned request, void *arg) {
|
||||
if (desc->type == ioctl_desc::WRITE) {
|
||||
// FIXME: add verbose output
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, desc->size);
|
||||
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
|
||||
}
|
||||
if (desc->type != ioctl_desc::CUSTOM)
|
||||
return;
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include <linux/fd.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/soundcard.h>
|
||||
#endif
|
||||
|
||||
|
@ -173,6 +175,7 @@ namespace __sanitizer {
|
|||
unsigned struct_copr_buffer_sz = sizeof(struct copr_buffer);
|
||||
unsigned struct_copr_debug_buf_sz = sizeof(struct copr_debug_buf);
|
||||
unsigned struct_copr_msg_sz = sizeof(struct copr_msg);
|
||||
unsigned struct_ff_effect_sz = sizeof(struct ff_effect);
|
||||
unsigned struct_floppy_drive_params_sz = sizeof(struct floppy_drive_params);
|
||||
unsigned struct_floppy_drive_struct_sz = sizeof(struct floppy_drive_struct);
|
||||
unsigned struct_floppy_fdc_state_sz = sizeof(struct floppy_fdc_state);
|
||||
|
@ -183,6 +186,8 @@ namespace __sanitizer {
|
|||
unsigned struct_format_descr_sz = sizeof(struct format_descr);
|
||||
unsigned struct_hd_driveid_sz = sizeof(struct hd_driveid);
|
||||
unsigned struct_hd_geometry_sz = sizeof(struct hd_geometry);
|
||||
unsigned struct_input_absinfo_sz = sizeof(struct input_absinfo);
|
||||
unsigned struct_input_id_sz = sizeof(struct input_id);
|
||||
unsigned struct_midi_info_sz = sizeof(struct midi_info);
|
||||
unsigned struct_mtget_sz = sizeof(struct mtget);
|
||||
unsigned struct_mtop_sz = sizeof(struct mtop);
|
||||
|
@ -199,15 +204,16 @@ namespace __sanitizer {
|
|||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
unsigned mpu_command_rec_sz = sizeof(mpu_command_rec);
|
||||
unsigned struct_audio_buf_info_sz = sizeof(struct audio_buf_info);
|
||||
unsigned struct_ax25_parms_struct_sz = sizeof(struct ax25_parms_struct);
|
||||
unsigned struct_cyclades_monitor_sz = sizeof(struct cyclades_monitor);
|
||||
unsigned struct_input_keymap_entry_sz = sizeof(struct input_keymap_entry);
|
||||
unsigned struct_ipx_config_data_sz = sizeof(struct ipx_config_data);
|
||||
unsigned struct_kbdiacrs_sz = sizeof(struct kbdiacrs);
|
||||
unsigned struct_kbentry_sz = sizeof(struct kbentry);
|
||||
unsigned struct_kbkeycode_sz = sizeof(struct kbkeycode);
|
||||
unsigned struct_kbsentry_sz = sizeof(struct kbsentry);
|
||||
unsigned mpu_command_rec_sz = sizeof(mpu_command_rec);
|
||||
unsigned struct_mtconfiginfo_sz = sizeof(struct mtconfiginfo);
|
||||
unsigned struct_nr_parms_struct_sz = sizeof(struct nr_parms_struct);
|
||||
unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats);
|
||||
|
@ -275,6 +281,26 @@ namespace __sanitizer {
|
|||
unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT;
|
||||
#endif
|
||||
#if SANITIZER_LINUX
|
||||
unsigned IOCTL_EVIOCGABS = EVIOCGABS(0);
|
||||
unsigned IOCTL_EVIOCGBIT = EVIOCGBIT(0, 0);
|
||||
unsigned IOCTL_EVIOCGEFFECTS = EVIOCGEFFECTS;
|
||||
unsigned IOCTL_EVIOCGID = EVIOCGID;
|
||||
unsigned IOCTL_EVIOCGKEY = EVIOCGKEY(0);
|
||||
unsigned IOCTL_EVIOCGKEYCODE = EVIOCGKEYCODE;
|
||||
unsigned IOCTL_EVIOCGLED = EVIOCGLED(0);
|
||||
unsigned IOCTL_EVIOCGNAME = EVIOCGNAME(0);
|
||||
unsigned IOCTL_EVIOCGPHYS = EVIOCGPHYS(0);
|
||||
unsigned IOCTL_EVIOCGRAB = EVIOCGRAB;
|
||||
unsigned IOCTL_EVIOCGREP = EVIOCGREP;
|
||||
unsigned IOCTL_EVIOCGSND = EVIOCGSND(0);
|
||||
unsigned IOCTL_EVIOCGSW = EVIOCGSW(0);
|
||||
unsigned IOCTL_EVIOCGUNIQ = EVIOCGUNIQ(0);
|
||||
unsigned IOCTL_EVIOCGVERSION = EVIOCGVERSION;
|
||||
unsigned IOCTL_EVIOCRMFF = EVIOCRMFF;
|
||||
unsigned IOCTL_EVIOCSABS = EVIOCSABS(0);
|
||||
unsigned IOCTL_EVIOCSFF = EVIOCSFF;
|
||||
unsigned IOCTL_EVIOCSKEYCODE = EVIOCSKEYCODE;
|
||||
unsigned IOCTL_EVIOCSREP = EVIOCSREP;
|
||||
unsigned IOCTL_BLKFLSBUF = BLKFLSBUF;
|
||||
unsigned IOCTL_BLKGETSIZE = BLKGETSIZE;
|
||||
unsigned IOCTL_BLKRAGET = BLKRAGET;
|
||||
|
@ -530,6 +556,9 @@ namespace __sanitizer {
|
|||
unsigned IOCTL_EQL_GETSLAVECFG = EQL_GETSLAVECFG;
|
||||
unsigned IOCTL_EQL_SETMASTRCFG = EQL_SETMASTRCFG;
|
||||
unsigned IOCTL_EQL_SETSLAVECFG = EQL_SETSLAVECFG;
|
||||
unsigned IOCTL_EVIOCGKEYCODE_V2 = EVIOCGKEYCODE_V2;
|
||||
unsigned IOCTL_EVIOCGPROP = EVIOCGPROP(0);
|
||||
unsigned IOCTL_EVIOCSKEYCODE_V2 = EVIOCSKEYCODE_V2;
|
||||
unsigned IOCTL_FS_IOC_GETFLAGS = FS_IOC_GETFLAGS;
|
||||
unsigned IOCTL_FS_IOC_GETVERSION = FS_IOC_GETVERSION;
|
||||
unsigned IOCTL_FS_IOC_SETFLAGS = FS_IOC_SETFLAGS;
|
||||
|
@ -635,6 +664,8 @@ CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_addr);
|
|||
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_name);
|
||||
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phdr);
|
||||
CHECK_SIZE_AND_OFFSET(dl_phdr_info, dlpi_phnum);
|
||||
|
||||
COMPILER_CHECK(IOC_SIZE(0x12345678) == _IOC_SIZE(0x12345678));
|
||||
#endif
|
||||
|
||||
CHECK_TYPE_SIZE(addrinfo);
|
||||
|
|
|
@ -160,6 +160,8 @@ namespace __sanitizer {
|
|||
};
|
||||
#endif
|
||||
|
||||
#define IOC_SIZE(nr) (((nr) >> 16) & 0x3fff)
|
||||
|
||||
extern unsigned struct_arpreq_sz;
|
||||
extern unsigned struct_ifreq_sz;
|
||||
extern unsigned struct_termios_sz;
|
||||
|
@ -177,6 +179,7 @@ namespace __sanitizer {
|
|||
extern unsigned struct_copr_buffer_sz;
|
||||
extern unsigned struct_copr_debug_buf_sz;
|
||||
extern unsigned struct_copr_msg_sz;
|
||||
extern unsigned struct_ff_effect_sz;
|
||||
extern unsigned struct_floppy_drive_params_sz;
|
||||
extern unsigned struct_floppy_drive_struct_sz;
|
||||
extern unsigned struct_floppy_fdc_state_sz;
|
||||
|
@ -187,6 +190,8 @@ namespace __sanitizer {
|
|||
extern unsigned struct_format_descr_sz;
|
||||
extern unsigned struct_hd_driveid_sz;
|
||||
extern unsigned struct_hd_geometry_sz;
|
||||
extern unsigned struct_input_absinfo_sz;
|
||||
extern unsigned struct_input_id_sz;
|
||||
extern unsigned struct_midi_info_sz;
|
||||
extern unsigned struct_mtget_sz;
|
||||
extern unsigned struct_mtop_sz;
|
||||
|
@ -203,15 +208,16 @@ namespace __sanitizer {
|
|||
#endif
|
||||
|
||||
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
||||
extern unsigned mpu_command_rec_sz;
|
||||
extern unsigned struct_audio_buf_info_sz;
|
||||
extern unsigned struct_ax25_parms_struct_sz;
|
||||
extern unsigned struct_cyclades_monitor_sz;
|
||||
extern unsigned struct_input_keymap_entry_sz;
|
||||
extern unsigned struct_ipx_config_data_sz;
|
||||
extern unsigned struct_kbdiacrs_sz;
|
||||
extern unsigned struct_kbentry_sz;
|
||||
extern unsigned struct_kbkeycode_sz;
|
||||
extern unsigned struct_kbsentry_sz;
|
||||
extern unsigned mpu_command_rec_sz;
|
||||
extern unsigned struct_mtconfiginfo_sz;
|
||||
extern unsigned struct_nr_parms_struct_sz;
|
||||
extern unsigned struct_ppp_stats_sz;
|
||||
|
@ -279,6 +285,26 @@ namespace __sanitizer {
|
|||
extern unsigned IOCTL_SIOCGETVIFCNT;
|
||||
#endif
|
||||
#if SANITIZER_LINUX
|
||||
extern unsigned IOCTL_EVIOCGABS;
|
||||
extern unsigned IOCTL_EVIOCGBIT;
|
||||
extern unsigned IOCTL_EVIOCGEFFECTS;
|
||||
extern unsigned IOCTL_EVIOCGID;
|
||||
extern unsigned IOCTL_EVIOCGKEY;
|
||||
extern unsigned IOCTL_EVIOCGKEYCODE;
|
||||
extern unsigned IOCTL_EVIOCGLED;
|
||||
extern unsigned IOCTL_EVIOCGNAME;
|
||||
extern unsigned IOCTL_EVIOCGPHYS;
|
||||
extern unsigned IOCTL_EVIOCGRAB;
|
||||
extern unsigned IOCTL_EVIOCGREP;
|
||||
extern unsigned IOCTL_EVIOCGSND;
|
||||
extern unsigned IOCTL_EVIOCGSW;
|
||||
extern unsigned IOCTL_EVIOCGUNIQ;
|
||||
extern unsigned IOCTL_EVIOCGVERSION;
|
||||
extern unsigned IOCTL_EVIOCRMFF;
|
||||
extern unsigned IOCTL_EVIOCSABS;
|
||||
extern unsigned IOCTL_EVIOCSFF;
|
||||
extern unsigned IOCTL_EVIOCSKEYCODE;
|
||||
extern unsigned IOCTL_EVIOCSREP;
|
||||
extern unsigned IOCTL_BLKFLSBUF;
|
||||
extern unsigned IOCTL_BLKGETSIZE;
|
||||
extern unsigned IOCTL_BLKRAGET;
|
||||
|
@ -534,6 +560,9 @@ namespace __sanitizer {
|
|||
extern unsigned IOCTL_EQL_GETSLAVECFG;
|
||||
extern unsigned IOCTL_EQL_SETMASTRCFG;
|
||||
extern unsigned IOCTL_EQL_SETSLAVECFG;
|
||||
extern unsigned IOCTL_EVIOCGKEYCODE_V2;
|
||||
extern unsigned IOCTL_EVIOCGPROP;
|
||||
extern unsigned IOCTL_EVIOCSKEYCODE_V2;
|
||||
extern unsigned IOCTL_FS_IOC_GETFLAGS;
|
||||
extern unsigned IOCTL_FS_IOC_GETVERSION;
|
||||
extern unsigned IOCTL_FS_IOC_SETFLAGS;
|
||||
|
|
|
@ -5,6 +5,7 @@ set(SANITIZER_UNITTESTS
|
|||
sanitizer_atomic_test.cc
|
||||
sanitizer_common_test.cc
|
||||
sanitizer_flags_test.cc
|
||||
sanitizer_ioctl_test.cc
|
||||
sanitizer_libc_test.cc
|
||||
sanitizer_linux_test.cc
|
||||
sanitizer_list_test.cc
|
||||
|
@ -31,7 +32,8 @@ set(SANITIZER_TEST_CFLAGS_COMMON
|
|||
-I${COMPILER_RT_SOURCE_DIR}/lib/sanitizer_common
|
||||
-DGTEST_HAS_RTTI=0
|
||||
-O2 -g -fno-rtti
|
||||
-Wall -Werror -Werror=sign-compare)
|
||||
-Wall -Werror -Werror=sign-compare
|
||||
-Wno-unused-function)
|
||||
|
||||
set(SANITIZER_TEST_LINK_FLAGS_COMMON
|
||||
-lstdc++ -ldl)
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
//===-- sanitizer_ioctl_test.cc -------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Tests for ioctl interceptor implementation in sanitizer_common.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_LINUX
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <vector>
|
||||
|
||||
#include "interception/interception.h"
|
||||
#include "sanitizer_test_utils.h"
|
||||
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
using namespace __sanitizer;
|
||||
|
||||
#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, sz) \
|
||||
do { \
|
||||
(void) ctx; \
|
||||
(void) ptr; \
|
||||
(void) sz; \
|
||||
} while (0)
|
||||
#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sz) \
|
||||
do { \
|
||||
(void) ctx; \
|
||||
(void) ptr; \
|
||||
(void) sz; \
|
||||
} while (0)
|
||||
|
||||
#include "sanitizer_common/sanitizer_common_interceptors_ioctl.inc"
|
||||
|
||||
static struct IoctlInit {
|
||||
IoctlInit() { ioctl_init(); }
|
||||
} ioctl_static_initializer;
|
||||
|
||||
TEST(SanitizerIoctl, Fixup) {
|
||||
EXPECT_EQ((unsigned)FIONBIO, ioctl_request_fixup(FIONBIO));
|
||||
|
||||
EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(0, 16)));
|
||||
EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 16)));
|
||||
EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(1, 17)));
|
||||
EXPECT_EQ(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(31, 16)));
|
||||
EXPECT_NE(EVIOCGBIT(0, 0), ioctl_request_fixup(EVIOCGBIT(32, 16)));
|
||||
|
||||
EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(0)));
|
||||
EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(5)));
|
||||
EXPECT_EQ(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(63)));
|
||||
EXPECT_NE(EVIOCGABS(0), ioctl_request_fixup(EVIOCGABS(64)));
|
||||
|
||||
EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(0)));
|
||||
EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(5)));
|
||||
EXPECT_EQ(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(63)));
|
||||
EXPECT_NE(EVIOCSABS(0), ioctl_request_fixup(EVIOCSABS(64)));
|
||||
|
||||
const ioctl_desc *desc = ioctl_lookup(EVIOCGKEY(16));
|
||||
EXPECT_NE((void *)0, desc);
|
||||
EXPECT_EQ(EVIOCGKEY(0), desc->req);
|
||||
}
|
||||
|
||||
#endif // SANITIZER_LINUX
|
Loading…
Reference in New Issue