llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_common_intercepto...

611 lines
22 KiB
PHP
Raw Normal View History

//===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Ioctl handling in common sanitizer interceptors.
//===----------------------------------------------------------------------===//
#if !SANITIZER_NETBSD
#include "sanitizer_flags.h"
struct ioctl_desc {
unsigned req;
// FIXME: support read+write arguments. Currently READWRITE and WRITE do the
// same thing.
// XXX: The declarations below may use WRITE instead of READWRITE, unless
// explicitly noted.
enum {
NONE,
READ,
WRITE,
READWRITE,
CUSTOM
} type : 3;
unsigned size : 29;
const char* name;
};
const unsigned ioctl_table_max = 500;
static ioctl_desc ioctl_table[ioctl_table_max];
static unsigned ioctl_table_size = 0;
// This can not be declared as a global, because references to struct_*_sz
// require a global initializer. And this table must be available before global
// initializers are run.
static void ioctl_table_fill() {
#define _(rq, tp, sz) \
if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
CHECK(ioctl_table_size < ioctl_table_max); \
ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
ioctl_table[ioctl_table_size].size = sz; \
ioctl_table[ioctl_table_size].name = #rq; \
++ioctl_table_size; \
}
_(FIOASYNC, READ, sizeof(int));
_(FIOCLEX, NONE, 0);
_(FIOGETOWN, WRITE, sizeof(int));
_(FIONBIO, READ, sizeof(int));
_(FIONCLEX, NONE, 0);
_(FIOSETOWN, READ, sizeof(int));
_(SIOCATMARK, WRITE, sizeof(int));
_(SIOCGIFCONF, CUSTOM, 0);
_(SIOCGPGRP, WRITE, sizeof(int));
_(SIOCSPGRP, READ, sizeof(int));
[Sanitizers] Basic sanitizer Solaris support (PR 33274) Summary: This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86. It is currently based on Solaris 11.4 Beta. This part was initially developed inside libsanitizer in the GCC tree and should apply to both. Subsequent parts will address changes to clang, the compiler-rt build system and testsuite. I'm not yet sure what the right patch granularity is: if it's profitable to split the patch up, I'd like to get guidance on how to do so. Most of the changes are probably straightforward with a few exceptions: * The Solaris syscall interface isn't stable, undocumented and can change within an OS release. The stable interface is the libc interface, which I'm using here, if possible using the internal _-prefixed names. * While the patch primarily target 32-bit x86, I've left a few sparc changes in. They cannot currently be used with clang due to a backend limitation, but have worked fine inside the gcc tree. * Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that. The patch (with the subsequent ones to be submitted shortly) was tested on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some still TBD: AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations Maybe this is good enough the get the ball rolling. Reviewers: kcc, alekseyshl Reviewed By: alekseyshl Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D40898 llvm-svn: 320740
2017-12-15 04:14:29 +08:00
#if !SANITIZER_SOLARIS
_(TIOCCONS, NONE, 0);
[Sanitizers] Basic sanitizer Solaris support (PR 33274) Summary: This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86. It is currently based on Solaris 11.4 Beta. This part was initially developed inside libsanitizer in the GCC tree and should apply to both. Subsequent parts will address changes to clang, the compiler-rt build system and testsuite. I'm not yet sure what the right patch granularity is: if it's profitable to split the patch up, I'd like to get guidance on how to do so. Most of the changes are probably straightforward with a few exceptions: * The Solaris syscall interface isn't stable, undocumented and can change within an OS release. The stable interface is the libc interface, which I'm using here, if possible using the internal _-prefixed names. * While the patch primarily target 32-bit x86, I've left a few sparc changes in. They cannot currently be used with clang due to a backend limitation, but have worked fine inside the gcc tree. * Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that. The patch (with the subsequent ones to be submitted shortly) was tested on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some still TBD: AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations Maybe this is good enough the get the ball rolling. Reviewers: kcc, alekseyshl Reviewed By: alekseyshl Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D40898 llvm-svn: 320740
2017-12-15 04:14:29 +08:00
#endif
_(TIOCEXCL, NONE, 0);
_(TIOCGETD, WRITE, sizeof(int));
_(TIOCGPGRP, WRITE, pid_t_sz);
_(TIOCGWINSZ, WRITE, struct_winsize_sz);
_(TIOCMBIC, READ, sizeof(int));
_(TIOCMBIS, READ, sizeof(int));
_(TIOCMGET, WRITE, sizeof(int));
_(TIOCMSET, READ, sizeof(int));
_(TIOCNOTTY, NONE, 0);
_(TIOCNXCL, NONE, 0);
_(TIOCOUTQ, WRITE, sizeof(int));
_(TIOCPKT, READ, sizeof(int));
_(TIOCSCTTY, NONE, 0);
_(TIOCSETD, READ, sizeof(int));
_(TIOCSPGRP, READ, pid_t_sz);
_(TIOCSTI, READ, sizeof(char));
_(TIOCSWINSZ, READ, struct_winsize_sz);
#if !SANITIZER_IOS
_(SIOCADDMULTI, READ, struct_ifreq_sz);
_(SIOCDELMULTI, READ, struct_ifreq_sz);
_(SIOCGIFADDR, WRITE, struct_ifreq_sz);
_(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz);
_(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz);
_(SIOCGIFFLAGS, WRITE, struct_ifreq_sz);
_(SIOCGIFMETRIC, WRITE, struct_ifreq_sz);
_(SIOCGIFMTU, WRITE, struct_ifreq_sz);
_(SIOCGIFNETMASK, WRITE, struct_ifreq_sz);
_(SIOCSIFADDR, READ, struct_ifreq_sz);
_(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
_(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
_(SIOCSIFFLAGS, READ, struct_ifreq_sz);
_(SIOCSIFMETRIC, READ, struct_ifreq_sz);
_(SIOCSIFMTU, READ, struct_ifreq_sz);
_(SIOCSIFNETMASK, READ, struct_ifreq_sz);
#endif
#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
_(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz);
_(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz);
#endif
#if SANITIZER_LINUX
// Conflicting request ids.
// _(CDROMAUDIOBUFSIZ, NONE, 0);
// _(SNDCTL_TMR_CONTINUE, NONE, 0);
// _(SNDCTL_TMR_START, NONE, 0);
// _(SNDCTL_TMR_STOP, NONE, 0);
// _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE
// _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE
// _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
// _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
_(BLKFLSBUF, NONE, 0);
_(BLKGETSIZE, WRITE, sizeof(uptr));
_(BLKRAGET, WRITE, sizeof(int));
_(BLKRASET, NONE, 0);
_(BLKROGET, WRITE, sizeof(int));
_(BLKROSET, READ, sizeof(int));
_(BLKRRPART, NONE, 0);
_(CDROMEJECT, NONE, 0);
_(CDROMEJECT_SW, NONE, 0);
_(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
_(CDROMPAUSE, NONE, 0);
_(CDROMPLAYMSF, READ, struct_cdrom_msf_sz);
_(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz);
_(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz);
_(CDROMREADCOOKED, READ, struct_cdrom_msf_sz);
_(CDROMREADMODE1, READ, struct_cdrom_msf_sz);
_(CDROMREADMODE2, READ, struct_cdrom_msf_sz);
_(CDROMREADRAW, READ, struct_cdrom_msf_sz);
_(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz);
_(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz);
_(CDROMRESET, NONE, 0);
_(CDROMRESUME, NONE, 0);
_(CDROMSEEK, READ, struct_cdrom_msf_sz);
_(CDROMSTART, NONE, 0);
_(CDROMSTOP, NONE, 0);
_(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz);
_(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);
_(FDFMTBEG, NONE, 0);
_(FDFMTEND, NONE, 0);
_(FDFMTTRK, READ, struct_format_descr_sz);
_(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz);
_(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
_(FDGETDRVTYP, WRITE, 16);
_(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz);
_(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz);
_(FDGETPRM, WRITE, struct_floppy_struct_sz);
_(FDMSGOFF, NONE, 0);
_(FDMSGON, NONE, 0);
_(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
_(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz);
_(FDRESET, NONE, 0);
_(FDSETDRVPRM, READ, struct_floppy_drive_params_sz);
_(FDSETEMSGTRESH, NONE, 0);
_(FDSETMAXERRS, READ, struct_floppy_max_errors_sz);
_(FDSETPRM, READ, struct_floppy_struct_sz);
_(FDTWADDLE, NONE, 0);
_(FDWERRORCLR, NONE, 0);
_(FDWERRORGET, WRITE, struct_floppy_write_errors_sz);
_(HDIO_DRIVE_CMD, WRITE, sizeof(int));
_(HDIO_GETGEO, WRITE, struct_hd_geometry_sz);
_(HDIO_GET_32BIT, WRITE, sizeof(int));
_(HDIO_GET_DMA, WRITE, sizeof(int));
_(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz);
_(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int));
_(HDIO_GET_MULTCOUNT, WRITE, sizeof(int));
_(HDIO_GET_NOWERR, WRITE, sizeof(int));
_(HDIO_GET_UNMASKINTR, WRITE, sizeof(int));
_(HDIO_SET_32BIT, NONE, 0);
_(HDIO_SET_DMA, NONE, 0);
_(HDIO_SET_KEEPSETTINGS, NONE, 0);
_(HDIO_SET_MULTCOUNT, NONE, 0);
_(HDIO_SET_NOWERR, NONE, 0);
_(HDIO_SET_UNMASKINTR, NONE, 0);
_(MTIOCGET, WRITE, struct_mtget_sz);
_(MTIOCPOS, WRITE, struct_mtpos_sz);
_(MTIOCTOP, READ, struct_mtop_sz);
_(PPPIOCGASYNCMAP, WRITE, sizeof(int));
_(PPPIOCGDEBUG, WRITE, sizeof(int));
_(PPPIOCGFLAGS, WRITE, sizeof(int));
_(PPPIOCGUNIT, WRITE, sizeof(int));
_(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8);
_(PPPIOCSASYNCMAP, READ, sizeof(int));
_(PPPIOCSDEBUG, READ, sizeof(int));
_(PPPIOCSFLAGS, READ, sizeof(int));
_(PPPIOCSMAXCID, READ, sizeof(int));
_(PPPIOCSMRU, READ, sizeof(int));
_(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8);
_(SIOCADDRT, READ, struct_rtentry_sz);
_(SIOCDARP, READ, struct_arpreq_sz);
_(SIOCDELRT, READ, struct_rtentry_sz);
_(SIOCDRARP, READ, struct_arpreq_sz);
_(SIOCGARP, WRITE, struct_arpreq_sz);
_(SIOCGIFENCAP, WRITE, sizeof(int));
_(SIOCGIFHWADDR, WRITE, struct_ifreq_sz);
_(SIOCGIFMAP, WRITE, struct_ifreq_sz);
_(SIOCGIFMEM, WRITE, struct_ifreq_sz);
_(SIOCGIFNAME, NONE, 0);
_(SIOCGIFSLAVE, NONE, 0);
_(SIOCGRARP, WRITE, struct_arpreq_sz);
_(SIOCGSTAMP, WRITE, timeval_sz);
_(SIOCSARP, READ, struct_arpreq_sz);
_(SIOCSIFENCAP, READ, sizeof(int));
_(SIOCSIFHWADDR, READ, struct_ifreq_sz);
_(SIOCSIFLINK, NONE, 0);
_(SIOCSIFMAP, READ, struct_ifreq_sz);
_(SIOCSIFMEM, READ, struct_ifreq_sz);
_(SIOCSIFSLAVE, NONE, 0);
_(SIOCSRARP, READ, struct_arpreq_sz);
_(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz);
_(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz);
_(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz);
_(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz);
_(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz);
_(SNDCTL_COPR_RESET, NONE, 0);
_(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz);
_(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz);
_(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz);
_(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz);
_(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int));
_(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
_(SNDCTL_DSP_NONBLOCK, NONE, 0);
_(SNDCTL_DSP_POST, NONE, 0);
_(SNDCTL_DSP_RESET, NONE, 0);
_(SNDCTL_DSP_SETFMT, WRITE, sizeof(int));
_(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int));
_(SNDCTL_DSP_SPEED, WRITE, sizeof(int));
_(SNDCTL_DSP_STEREO, WRITE, sizeof(int));
_(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int));
_(SNDCTL_DSP_SYNC, NONE, 0);
_(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int));
_(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz);
_(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz);
_(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int));
_(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int));
_(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int));
_(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int));
_(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int));
_(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int));
_(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz);
_(SNDCTL_SEQ_PANIC, NONE, 0);
_(SNDCTL_SEQ_PERCMODE, NONE, 0);
_(SNDCTL_SEQ_RESET, NONE, 0);
_(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int));
_(SNDCTL_SEQ_SYNC, NONE, 0);
_(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int));
_(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int));
_(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz);
_(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int));
_(SNDCTL_TMR_METRONOME, READ, sizeof(int));
_(SNDCTL_TMR_SELECT, WRITE, sizeof(int));
_(SNDCTL_TMR_SOURCE, WRITE, sizeof(int));
_(SNDCTL_TMR_TEMPO, WRITE, sizeof(int));
_(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int));
_(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int));
_(SOUND_MIXER_READ_BASS, WRITE, sizeof(int));
_(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int));
_(SOUND_MIXER_READ_CD, WRITE, sizeof(int));
_(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int));
_(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int));
_(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int));
_(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int));
_(SOUND_MIXER_READ_LINE, WRITE, sizeof(int));
_(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int));
_(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int));
_(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int));
_(SOUND_MIXER_READ_MIC, WRITE, sizeof(int));
_(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int));
_(SOUND_MIXER_READ_PCM, WRITE, sizeof(int));
_(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int));
_(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int));
_(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int));
_(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int));
_(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int));
_(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int));
_(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int));
_(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int));
_(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int));
_(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
_(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
_(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
_(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
_(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
_(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
_(TCFLSH, NONE, 0);
_(TCGETA, WRITE, struct_termio_sz);
_(TCGETS, WRITE, struct_termios_sz);
_(TCSBRK, NONE, 0);
_(TCSBRKP, NONE, 0);
_(TCSETA, READ, struct_termio_sz);
_(TCSETAF, READ, struct_termio_sz);
_(TCSETAW, READ, struct_termio_sz);
_(TCSETS, READ, struct_termios_sz);
_(TCSETSF, READ, struct_termios_sz);
_(TCSETSW, READ, struct_termios_sz);
_(TCXONC, NONE, 0);
_(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
_(TIOCGSOFTCAR, WRITE, sizeof(int));
_(TIOCINQ, WRITE, sizeof(int));
_(TIOCLINUX, READ, sizeof(char));
_(TIOCSERCONFIG, NONE, 0);
_(TIOCSERGETLSR, WRITE, sizeof(int));
_(TIOCSERGWILD, WRITE, sizeof(int));
_(TIOCSERSWILD, READ, sizeof(int));
_(TIOCSLCKTRMIOS, READ, struct_termios_sz);
_(TIOCSSOFTCAR, READ, sizeof(int));
_(VT_ACTIVATE, NONE, 0);
_(VT_DISALLOCATE, NONE, 0);
_(VT_GETMODE, WRITE, struct_vt_mode_sz);
_(VT_GETSTATE, WRITE, struct_vt_stat_sz);
_(VT_OPENQRY, WRITE, sizeof(int));
_(VT_RELDISP, NONE, 0);
_(VT_RESIZE, READ, struct_vt_sizes_sz);
_(VT_RESIZEX, READ, struct_vt_consize_sz);
_(VT_SENDSIG, NONE, 0);
_(VT_SETMODE, READ, struct_vt_mode_sz);
_(VT_WAITACTIVE, NONE, 0);
#endif
#if SANITIZER_LINUX && !SANITIZER_ANDROID
// _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
_(CYGETDEFTHRESH, WRITE, sizeof(int));
_(CYGETDEFTIMEOUT, WRITE, sizeof(int));
_(CYGETMON, WRITE, struct_cyclades_monitor_sz);
_(CYGETTHRESH, WRITE, sizeof(int));
_(CYGETTIMEOUT, WRITE, sizeof(int));
_(CYSETDEFTHRESH, NONE, 0);
_(CYSETDEFTIMEOUT, NONE, 0);
_(CYSETTHRESH, NONE, 0);
_(CYSETTIMEOUT, NONE, 0);
_(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
_(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
_(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz);
_(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));
_(FS_IOC_SETVERSION, READ, sizeof(int));
_(GIO_CMAP, WRITE, 48);
_(GIO_FONT, WRITE, 8192);
_(GIO_SCRNMAP, WRITE, e_tabsz);
_(GIO_UNIMAP, WRITE, struct_unimapdesc_sz);
_(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz);
_(KDADDIO, NONE, 0);
_(KDDELIO, NONE, 0);
_(KDDISABIO, NONE, 0);
_(KDENABIO, NONE, 0);
_(KDGETKEYCODE, WRITE, struct_kbkeycode_sz);
_(KDGETLED, WRITE, 1);
_(KDGETMODE, WRITE, sizeof(int));
_(KDGKBDIACR, WRITE, struct_kbdiacrs_sz);
_(KDGKBENT, WRITE, struct_kbentry_sz);
_(KDGKBLED, WRITE, sizeof(int));
_(KDGKBMETA, WRITE, sizeof(int));
_(KDGKBMODE, WRITE, sizeof(int));
_(KDGKBSENT, WRITE, struct_kbsentry_sz);
_(KDGKBTYPE, WRITE, 1);
_(KDMAPDISP, NONE, 0);
_(KDMKTONE, NONE, 0);
_(KDSETKEYCODE, READ, struct_kbkeycode_sz);
_(KDSETLED, NONE, 0);
_(KDSETMODE, NONE, 0);
_(KDSIGACCEPT, NONE, 0);
_(KDSKBDIACR, READ, struct_kbdiacrs_sz);
_(KDSKBENT, READ, struct_kbentry_sz);
_(KDSKBLED, NONE, 0);
_(KDSKBMETA, NONE, 0);
_(KDSKBMODE, NONE, 0);
_(KDSKBSENT, READ, struct_kbsentry_sz);
_(KDUNMAPDISP, NONE, 0);
_(KIOCSOUND, NONE, 0);
_(LPABORT, NONE, 0);
_(LPABORTOPEN, NONE, 0);
_(LPCAREFUL, NONE, 0);
_(LPCHAR, NONE, 0);
_(LPGETIRQ, WRITE, sizeof(int));
_(LPGETSTATUS, WRITE, sizeof(int));
_(LPRESET, NONE, 0);
_(LPSETIRQ, NONE, 0);
_(LPTIME, NONE, 0);
_(LPWAIT, NONE, 0);
_(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz);
_(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz);
_(PIO_CMAP, NONE, 0);
_(PIO_FONT, READ, 8192);
_(PIO_SCRNMAP, READ, e_tabsz);
_(PIO_UNIMAP, READ, struct_unimapdesc_sz);
_(PIO_UNIMAPCLR, READ, struct_unimapinit_sz);
_(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz);
_(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int));
_(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0);
_(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0);
_(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
_(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
_(TIOCGSERIAL, WRITE, struct_serial_struct_sz);
_(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz);
_(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz);
_(TIOCSSERIAL, READ, struct_serial_struct_sz);
// The following ioctl requests are shared between AX25, IPX, netrom and
// mrouted.
// _(SIOCAIPXITFCRT, READ, sizeof(char));
// _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz);
// _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz);
// _(SIOCAIPXPRISLT, READ, sizeof(char));
// _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz);
// _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz);
// _(SIOCNRDECOBS, NONE, 0);
// _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz);
// _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz);
// _(SIOCAX25NOUID, READ, sizeof(int));
// _(SIOCNRRTCTL, READ, sizeof(int));
// _(SIOCAX25DIGCTL, READ, sizeof(int));
// _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz);
// _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz);
#endif
#undef _
}
static bool ioctl_initialized = false;
struct ioctl_desc_compare {
bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {
return left.req < right.req;
}
};
static void ioctl_init() {
ioctl_table_fill();
InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare());
bool bad = false;
for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
ioctl_table[i + 1].name);
bad = true;
}
}
if (bad) Die();
ioctl_initialized = true;
}
// Handle the most evil ioctls that encode argument value as part of request id.
static unsigned ioctl_request_fixup(unsigned req) {
#if SANITIZER_LINUX
// Strip size and event number.
const unsigned kEviocgbitMask =
(IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX;
if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT)
return IOCTL_EVIOCGBIT;
// Strip absolute axis number.
if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS)
return IOCTL_EVIOCGABS;
if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS)
return IOCTL_EVIOCSABS;
#endif
return req;
}
static const ioctl_desc *ioctl_table_lookup(unsigned req) {
int left = 0;
int right = ioctl_table_size;
while (left < right) {
int mid = (left + right) / 2;
if (ioctl_table[mid].req < req)
left = mid + 1;
else
right = mid;
}
if (left == right && ioctl_table[left].req == req)
return ioctl_table + left;
else
return nullptr;
}
static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
CHECK(desc);
desc->req = req;
desc->name = "<DECODED_IOCTL>";
desc->size = IOC_SIZE(req);
// Sanity check.
if (desc->size > 0xFFFF) return false;
unsigned dir = IOC_DIR(req);
switch (dir) {
case IOC_NONE:
desc->type = ioctl_desc::NONE;
break;
case IOC_READ | IOC_WRITE:
desc->type = ioctl_desc::READWRITE;
break;
case IOC_READ:
desc->type = ioctl_desc::WRITE;
break;
case IOC_WRITE:
desc->type = ioctl_desc::READ;
break;
default:
return false;
}
// Size can be 0 iff type is NONE.
if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;
// Sanity check.
if (IOC_TYPE(req) == 0) return false;
return true;
}
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 & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
// 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::READWRITE || desc->type == ioctl_desc::WRITE ||
desc->type == ioctl_desc::READ))
return desc;
return nullptr;
}
static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
unsigned request, void *arg) {
if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
}
if (desc->type != ioctl_desc::CUSTOM)
return;
if (request == IOCTL_SIOCGIFCONF) {
struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,
sizeof(ifc->ifc_len));
}
}
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 || desc->type == ioctl_desc::READWRITE) {
// FIXME: add verbose output
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
}
if (desc->type != ioctl_desc::CUSTOM)
return;
if (request == IOCTL_SIOCGIFCONF) {
struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
}
}
#endif