1274201Sdim//===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===// 2274201Sdim// 3274201Sdim// The LLVM Compiler Infrastructure 4274201Sdim// 5274201Sdim// This file is distributed under the University of Illinois Open Source 6274201Sdim// License. See LICENSE.TXT for details. 7274201Sdim// 8274201Sdim//===----------------------------------------------------------------------===// 9274201Sdim// 10274201Sdim// Ioctl handling in common sanitizer interceptors. 11274201Sdim//===----------------------------------------------------------------------===// 12274201Sdim 13274201Sdim#include "sanitizer_flags.h" 14274201Sdim 15274201Sdimstruct ioctl_desc { 16274201Sdim unsigned req; 17276789Sdim // FIXME: support read+write arguments. Currently READWRITE and WRITE do the 18276789Sdim // same thing. 19276789Sdim // XXX: The declarations below may use WRITE instead of READWRITE, unless 20276789Sdim // explicitly noted. 21274201Sdim enum { 22274201Sdim NONE, 23274201Sdim READ, 24274201Sdim WRITE, 25276789Sdim READWRITE, 26274201Sdim CUSTOM 27276789Sdim } type : 3; 28276789Sdim unsigned size : 29; 29274201Sdim const char* name; 30274201Sdim}; 31274201Sdim 32274201Sdimconst unsigned ioctl_table_max = 500; 33274201Sdimstatic ioctl_desc ioctl_table[ioctl_table_max]; 34274201Sdimstatic unsigned ioctl_table_size = 0; 35274201Sdim 36274201Sdim// This can not be declared as a global, because references to struct_*_sz 37274201Sdim// require a global initializer. And this table must be available before global 38274201Sdim// initializers are run. 39274201Sdimstatic void ioctl_table_fill() { 40274201Sdim#define _(rq, tp, sz) \ 41274201Sdim if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \ 42274201Sdim CHECK(ioctl_table_size < ioctl_table_max); \ 43274201Sdim ioctl_table[ioctl_table_size].req = IOCTL_##rq; \ 44274201Sdim ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \ 45274201Sdim ioctl_table[ioctl_table_size].size = sz; \ 46274201Sdim ioctl_table[ioctl_table_size].name = #rq; \ 47274201Sdim ++ioctl_table_size; \ 48274201Sdim } 49274201Sdim 50274201Sdim _(FIOASYNC, READ, sizeof(int)); 51274201Sdim _(FIOCLEX, NONE, 0); 52274201Sdim _(FIOGETOWN, WRITE, sizeof(int)); 53274201Sdim _(FIONBIO, READ, sizeof(int)); 54274201Sdim _(FIONCLEX, NONE, 0); 55274201Sdim _(FIOSETOWN, READ, sizeof(int)); 56274201Sdim _(SIOCADDMULTI, READ, struct_ifreq_sz); 57274201Sdim _(SIOCATMARK, WRITE, sizeof(int)); 58274201Sdim _(SIOCDELMULTI, READ, struct_ifreq_sz); 59274201Sdim _(SIOCGIFADDR, WRITE, struct_ifreq_sz); 60274201Sdim _(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz); 61274201Sdim _(SIOCGIFCONF, CUSTOM, 0); 62274201Sdim _(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz); 63274201Sdim _(SIOCGIFFLAGS, WRITE, struct_ifreq_sz); 64274201Sdim _(SIOCGIFMETRIC, WRITE, struct_ifreq_sz); 65274201Sdim _(SIOCGIFMTU, WRITE, struct_ifreq_sz); 66274201Sdim _(SIOCGIFNETMASK, WRITE, struct_ifreq_sz); 67274201Sdim _(SIOCGPGRP, WRITE, sizeof(int)); 68274201Sdim _(SIOCSIFADDR, READ, struct_ifreq_sz); 69274201Sdim _(SIOCSIFBRDADDR, READ, struct_ifreq_sz); 70274201Sdim _(SIOCSIFDSTADDR, READ, struct_ifreq_sz); 71274201Sdim _(SIOCSIFFLAGS, READ, struct_ifreq_sz); 72274201Sdim _(SIOCSIFMETRIC, READ, struct_ifreq_sz); 73274201Sdim _(SIOCSIFMTU, READ, struct_ifreq_sz); 74274201Sdim _(SIOCSIFNETMASK, READ, struct_ifreq_sz); 75274201Sdim _(SIOCSPGRP, READ, sizeof(int)); 76274201Sdim _(TIOCCONS, NONE, 0); 77274201Sdim _(TIOCEXCL, NONE, 0); 78274201Sdim _(TIOCGETD, WRITE, sizeof(int)); 79274201Sdim _(TIOCGPGRP, WRITE, pid_t_sz); 80274201Sdim _(TIOCGWINSZ, WRITE, struct_winsize_sz); 81274201Sdim _(TIOCMBIC, READ, sizeof(int)); 82274201Sdim _(TIOCMBIS, READ, sizeof(int)); 83274201Sdim _(TIOCMGET, WRITE, sizeof(int)); 84274201Sdim _(TIOCMSET, READ, sizeof(int)); 85274201Sdim _(TIOCNOTTY, NONE, 0); 86274201Sdim _(TIOCNXCL, NONE, 0); 87274201Sdim _(TIOCOUTQ, WRITE, sizeof(int)); 88274201Sdim _(TIOCPKT, READ, sizeof(int)); 89274201Sdim _(TIOCSCTTY, NONE, 0); 90274201Sdim _(TIOCSETD, READ, sizeof(int)); 91274201Sdim _(TIOCSPGRP, READ, pid_t_sz); 92274201Sdim _(TIOCSTI, READ, sizeof(char)); 93274201Sdim _(TIOCSWINSZ, READ, struct_winsize_sz); 94274201Sdim 95274201Sdim#if (SANITIZER_LINUX && !SANITIZER_ANDROID) 96274201Sdim _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz); 97274201Sdim _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz); 98274201Sdim#endif 99274201Sdim 100274201Sdim#if SANITIZER_LINUX 101274201Sdim // Conflicting request ids. 102274201Sdim // _(CDROMAUDIOBUFSIZ, NONE, 0); 103274201Sdim // _(SNDCTL_TMR_CONTINUE, NONE, 0); 104274201Sdim // _(SNDCTL_TMR_START, NONE, 0); 105274201Sdim // _(SNDCTL_TMR_STOP, NONE, 0); 106274201Sdim // _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE 107274201Sdim // _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE 108274201Sdim // _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE 109274201Sdim // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE 110274201Sdim _(BLKFLSBUF, NONE, 0); 111274201Sdim _(BLKGETSIZE, WRITE, sizeof(uptr)); 112274201Sdim _(BLKRAGET, WRITE, sizeof(int)); 113274201Sdim _(BLKRASET, NONE, 0); 114274201Sdim _(BLKROGET, WRITE, sizeof(int)); 115274201Sdim _(BLKROSET, READ, sizeof(int)); 116274201Sdim _(BLKRRPART, NONE, 0); 117274201Sdim _(CDROMEJECT, NONE, 0); 118274201Sdim _(CDROMEJECT_SW, NONE, 0); 119274201Sdim _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz); 120274201Sdim _(CDROMPAUSE, NONE, 0); 121274201Sdim _(CDROMPLAYMSF, READ, struct_cdrom_msf_sz); 122274201Sdim _(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz); 123274201Sdim _(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz); 124274201Sdim _(CDROMREADCOOKED, READ, struct_cdrom_msf_sz); 125274201Sdim _(CDROMREADMODE1, READ, struct_cdrom_msf_sz); 126274201Sdim _(CDROMREADMODE2, READ, struct_cdrom_msf_sz); 127274201Sdim _(CDROMREADRAW, READ, struct_cdrom_msf_sz); 128274201Sdim _(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz); 129274201Sdim _(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz); 130274201Sdim _(CDROMRESET, NONE, 0); 131274201Sdim _(CDROMRESUME, NONE, 0); 132274201Sdim _(CDROMSEEK, READ, struct_cdrom_msf_sz); 133274201Sdim _(CDROMSTART, NONE, 0); 134274201Sdim _(CDROMSTOP, NONE, 0); 135274201Sdim _(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz); 136274201Sdim _(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz); 137274201Sdim _(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz); 138274201Sdim _(CDROM_GET_UPC, WRITE, 8); 139274201Sdim _(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup 140274201Sdim _(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup 141274201Sdim _(EVIOCGEFFECTS, WRITE, sizeof(int)); 142274201Sdim _(EVIOCGID, WRITE, struct_input_id_sz); 143274201Sdim _(EVIOCGKEY, WRITE, 0); 144274201Sdim _(EVIOCGKEYCODE, WRITE, sizeof(int) * 2); 145274201Sdim _(EVIOCGLED, WRITE, 0); 146274201Sdim _(EVIOCGNAME, WRITE, 0); 147274201Sdim _(EVIOCGPHYS, WRITE, 0); 148274201Sdim _(EVIOCGRAB, READ, sizeof(int)); 149274201Sdim _(EVIOCGREP, WRITE, sizeof(int) * 2); 150274201Sdim _(EVIOCGSND, WRITE, 0); 151274201Sdim _(EVIOCGSW, WRITE, 0); 152274201Sdim _(EVIOCGUNIQ, WRITE, 0); 153274201Sdim _(EVIOCGVERSION, WRITE, sizeof(int)); 154274201Sdim _(EVIOCRMFF, READ, sizeof(int)); 155274201Sdim _(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup 156274201Sdim _(EVIOCSFF, READ, struct_ff_effect_sz); 157274201Sdim _(EVIOCSKEYCODE, READ, sizeof(int) * 2); 158274201Sdim _(EVIOCSREP, READ, sizeof(int) * 2); 159274201Sdim _(FDCLRPRM, NONE, 0); 160274201Sdim _(FDDEFPRM, READ, struct_floppy_struct_sz); 161274201Sdim _(FDFLUSH, NONE, 0); 162274201Sdim _(FDFMTBEG, NONE, 0); 163274201Sdim _(FDFMTEND, NONE, 0); 164274201Sdim _(FDFMTTRK, READ, struct_format_descr_sz); 165274201Sdim _(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz); 166274201Sdim _(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz); 167274201Sdim _(FDGETDRVTYP, WRITE, 16); 168274201Sdim _(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz); 169274201Sdim _(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz); 170274201Sdim _(FDGETPRM, WRITE, struct_floppy_struct_sz); 171274201Sdim _(FDMSGOFF, NONE, 0); 172274201Sdim _(FDMSGON, NONE, 0); 173274201Sdim _(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz); 174274201Sdim _(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz); 175274201Sdim _(FDRESET, NONE, 0); 176274201Sdim _(FDSETDRVPRM, READ, struct_floppy_drive_params_sz); 177274201Sdim _(FDSETEMSGTRESH, NONE, 0); 178274201Sdim _(FDSETMAXERRS, READ, struct_floppy_max_errors_sz); 179274201Sdim _(FDSETPRM, READ, struct_floppy_struct_sz); 180274201Sdim _(FDTWADDLE, NONE, 0); 181274201Sdim _(FDWERRORCLR, NONE, 0); 182274201Sdim _(FDWERRORGET, WRITE, struct_floppy_write_errors_sz); 183274201Sdim _(HDIO_DRIVE_CMD, WRITE, sizeof(int)); 184274201Sdim _(HDIO_GETGEO, WRITE, struct_hd_geometry_sz); 185274201Sdim _(HDIO_GET_32BIT, WRITE, sizeof(int)); 186274201Sdim _(HDIO_GET_DMA, WRITE, sizeof(int)); 187274201Sdim _(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz); 188274201Sdim _(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int)); 189274201Sdim _(HDIO_GET_MULTCOUNT, WRITE, sizeof(int)); 190274201Sdim _(HDIO_GET_NOWERR, WRITE, sizeof(int)); 191274201Sdim _(HDIO_GET_UNMASKINTR, WRITE, sizeof(int)); 192274201Sdim _(HDIO_SET_32BIT, NONE, 0); 193274201Sdim _(HDIO_SET_DMA, NONE, 0); 194274201Sdim _(HDIO_SET_KEEPSETTINGS, NONE, 0); 195274201Sdim _(HDIO_SET_MULTCOUNT, NONE, 0); 196274201Sdim _(HDIO_SET_NOWERR, NONE, 0); 197274201Sdim _(HDIO_SET_UNMASKINTR, NONE, 0); 198274201Sdim _(MTIOCGET, WRITE, struct_mtget_sz); 199274201Sdim _(MTIOCPOS, WRITE, struct_mtpos_sz); 200274201Sdim _(MTIOCTOP, READ, struct_mtop_sz); 201274201Sdim _(PPPIOCGASYNCMAP, WRITE, sizeof(int)); 202274201Sdim _(PPPIOCGDEBUG, WRITE, sizeof(int)); 203274201Sdim _(PPPIOCGFLAGS, WRITE, sizeof(int)); 204274201Sdim _(PPPIOCGUNIT, WRITE, sizeof(int)); 205274201Sdim _(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8); 206274201Sdim _(PPPIOCSASYNCMAP, READ, sizeof(int)); 207274201Sdim _(PPPIOCSDEBUG, READ, sizeof(int)); 208274201Sdim _(PPPIOCSFLAGS, READ, sizeof(int)); 209274201Sdim _(PPPIOCSMAXCID, READ, sizeof(int)); 210274201Sdim _(PPPIOCSMRU, READ, sizeof(int)); 211274201Sdim _(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8); 212274201Sdim _(SIOCADDRT, READ, struct_rtentry_sz); 213274201Sdim _(SIOCDARP, READ, struct_arpreq_sz); 214274201Sdim _(SIOCDELRT, READ, struct_rtentry_sz); 215274201Sdim _(SIOCDRARP, READ, struct_arpreq_sz); 216274201Sdim _(SIOCGARP, WRITE, struct_arpreq_sz); 217274201Sdim _(SIOCGIFENCAP, WRITE, sizeof(int)); 218274201Sdim _(SIOCGIFHWADDR, WRITE, struct_ifreq_sz); 219274201Sdim _(SIOCGIFMAP, WRITE, struct_ifreq_sz); 220274201Sdim _(SIOCGIFMEM, WRITE, struct_ifreq_sz); 221274201Sdim _(SIOCGIFNAME, NONE, 0); 222274201Sdim _(SIOCGIFSLAVE, NONE, 0); 223274201Sdim _(SIOCGRARP, WRITE, struct_arpreq_sz); 224274201Sdim _(SIOCGSTAMP, WRITE, timeval_sz); 225274201Sdim _(SIOCSARP, READ, struct_arpreq_sz); 226274201Sdim _(SIOCSIFENCAP, READ, sizeof(int)); 227274201Sdim _(SIOCSIFHWADDR, READ, struct_ifreq_sz); 228274201Sdim _(SIOCSIFLINK, NONE, 0); 229274201Sdim _(SIOCSIFMAP, READ, struct_ifreq_sz); 230274201Sdim _(SIOCSIFMEM, READ, struct_ifreq_sz); 231274201Sdim _(SIOCSIFSLAVE, NONE, 0); 232274201Sdim _(SIOCSRARP, READ, struct_arpreq_sz); 233274201Sdim _(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz); 234274201Sdim _(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz); 235274201Sdim _(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz); 236274201Sdim _(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz); 237274201Sdim _(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz); 238274201Sdim _(SNDCTL_COPR_RESET, NONE, 0); 239274201Sdim _(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz); 240274201Sdim _(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz); 241274201Sdim _(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz); 242274201Sdim _(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz); 243274201Sdim _(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int)); 244274201Sdim _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int)); 245274201Sdim _(SNDCTL_DSP_NONBLOCK, NONE, 0); 246274201Sdim _(SNDCTL_DSP_POST, NONE, 0); 247274201Sdim _(SNDCTL_DSP_RESET, NONE, 0); 248274201Sdim _(SNDCTL_DSP_SETFMT, WRITE, sizeof(int)); 249274201Sdim _(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int)); 250274201Sdim _(SNDCTL_DSP_SPEED, WRITE, sizeof(int)); 251274201Sdim _(SNDCTL_DSP_STEREO, WRITE, sizeof(int)); 252274201Sdim _(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int)); 253274201Sdim _(SNDCTL_DSP_SYNC, NONE, 0); 254274201Sdim _(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int)); 255274201Sdim _(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz); 256274201Sdim _(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz); 257274201Sdim _(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int)); 258274201Sdim _(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int)); 259274201Sdim _(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int)); 260274201Sdim _(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int)); 261274201Sdim _(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int)); 262274201Sdim _(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int)); 263274201Sdim _(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz); 264274201Sdim _(SNDCTL_SEQ_PANIC, NONE, 0); 265274201Sdim _(SNDCTL_SEQ_PERCMODE, NONE, 0); 266274201Sdim _(SNDCTL_SEQ_RESET, NONE, 0); 267274201Sdim _(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int)); 268274201Sdim _(SNDCTL_SEQ_SYNC, NONE, 0); 269274201Sdim _(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int)); 270274201Sdim _(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int)); 271274201Sdim _(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz); 272274201Sdim _(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int)); 273274201Sdim _(SNDCTL_TMR_METRONOME, READ, sizeof(int)); 274274201Sdim _(SNDCTL_TMR_SELECT, WRITE, sizeof(int)); 275274201Sdim _(SNDCTL_TMR_SOURCE, WRITE, sizeof(int)); 276274201Sdim _(SNDCTL_TMR_TEMPO, WRITE, sizeof(int)); 277274201Sdim _(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int)); 278274201Sdim _(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int)); 279274201Sdim _(SOUND_MIXER_READ_BASS, WRITE, sizeof(int)); 280274201Sdim _(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int)); 281274201Sdim _(SOUND_MIXER_READ_CD, WRITE, sizeof(int)); 282274201Sdim _(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int)); 283274201Sdim _(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int)); 284274201Sdim _(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int)); 285274201Sdim _(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int)); 286274201Sdim _(SOUND_MIXER_READ_LINE, WRITE, sizeof(int)); 287274201Sdim _(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int)); 288274201Sdim _(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int)); 289274201Sdim _(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int)); 290274201Sdim _(SOUND_MIXER_READ_MIC, WRITE, sizeof(int)); 291274201Sdim _(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int)); 292274201Sdim _(SOUND_MIXER_READ_PCM, WRITE, sizeof(int)); 293274201Sdim _(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int)); 294274201Sdim _(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int)); 295274201Sdim _(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int)); 296274201Sdim _(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int)); 297274201Sdim _(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int)); 298274201Sdim _(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int)); 299274201Sdim _(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int)); 300274201Sdim _(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int)); 301274201Sdim _(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int)); 302274201Sdim _(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int)); 303274201Sdim _(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int)); 304274201Sdim _(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int)); 305274201Sdim _(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int)); 306274201Sdim _(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int)); 307274201Sdim _(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int)); 308274201Sdim _(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int)); 309274201Sdim _(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int)); 310274201Sdim _(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int)); 311274201Sdim _(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int)); 312274201Sdim _(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int)); 313274201Sdim _(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int)); 314274201Sdim _(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int)); 315274201Sdim _(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int)); 316274201Sdim _(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int)); 317274201Sdim _(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int)); 318274201Sdim _(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int)); 319274201Sdim _(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int)); 320274201Sdim _(SOUND_PCM_READ_BITS, WRITE, sizeof(int)); 321274201Sdim _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int)); 322274201Sdim _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int)); 323274201Sdim _(SOUND_PCM_READ_RATE, WRITE, sizeof(int)); 324274201Sdim _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int)); 325274201Sdim _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int)); 326274201Sdim _(TCFLSH, NONE, 0); 327274201Sdim _(TCGETA, WRITE, struct_termio_sz); 328274201Sdim _(TCGETS, WRITE, struct_termios_sz); 329274201Sdim _(TCSBRK, NONE, 0); 330274201Sdim _(TCSBRKP, NONE, 0); 331274201Sdim _(TCSETA, READ, struct_termio_sz); 332274201Sdim _(TCSETAF, READ, struct_termio_sz); 333274201Sdim _(TCSETAW, READ, struct_termio_sz); 334274201Sdim _(TCSETS, READ, struct_termios_sz); 335274201Sdim _(TCSETSF, READ, struct_termios_sz); 336274201Sdim _(TCSETSW, READ, struct_termios_sz); 337274201Sdim _(TCXONC, NONE, 0); 338274201Sdim _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz); 339274201Sdim _(TIOCGSOFTCAR, WRITE, sizeof(int)); 340274201Sdim _(TIOCINQ, WRITE, sizeof(int)); 341274201Sdim _(TIOCLINUX, READ, sizeof(char)); 342274201Sdim _(TIOCSERCONFIG, NONE, 0); 343274201Sdim _(TIOCSERGETLSR, WRITE, sizeof(int)); 344274201Sdim _(TIOCSERGWILD, WRITE, sizeof(int)); 345274201Sdim _(TIOCSERSWILD, READ, sizeof(int)); 346274201Sdim _(TIOCSLCKTRMIOS, READ, struct_termios_sz); 347274201Sdim _(TIOCSSOFTCAR, READ, sizeof(int)); 348274201Sdim _(VT_ACTIVATE, NONE, 0); 349274201Sdim _(VT_DISALLOCATE, NONE, 0); 350274201Sdim _(VT_GETMODE, WRITE, struct_vt_mode_sz); 351274201Sdim _(VT_GETSTATE, WRITE, struct_vt_stat_sz); 352274201Sdim _(VT_OPENQRY, WRITE, sizeof(int)); 353274201Sdim _(VT_RELDISP, NONE, 0); 354274201Sdim _(VT_RESIZE, READ, struct_vt_sizes_sz); 355274201Sdim _(VT_RESIZEX, READ, struct_vt_consize_sz); 356274201Sdim _(VT_SENDSIG, NONE, 0); 357274201Sdim _(VT_SETMODE, READ, struct_vt_mode_sz); 358274201Sdim _(VT_WAITACTIVE, NONE, 0); 359274201Sdim#endif 360274201Sdim 361274201Sdim#if SANITIZER_LINUX && !SANITIZER_ANDROID 362274201Sdim // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE 363274201Sdim _(CYGETDEFTHRESH, WRITE, sizeof(int)); 364274201Sdim _(CYGETDEFTIMEOUT, WRITE, sizeof(int)); 365274201Sdim _(CYGETMON, WRITE, struct_cyclades_monitor_sz); 366274201Sdim _(CYGETTHRESH, WRITE, sizeof(int)); 367274201Sdim _(CYGETTIMEOUT, WRITE, sizeof(int)); 368274201Sdim _(CYSETDEFTHRESH, NONE, 0); 369274201Sdim _(CYSETDEFTIMEOUT, NONE, 0); 370274201Sdim _(CYSETTHRESH, NONE, 0); 371274201Sdim _(CYSETTIMEOUT, NONE, 0); 372274201Sdim _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz); 373274201Sdim _(EQL_ENSLAVE, WRITE, struct_ifreq_sz); 374274201Sdim _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz); 375274201Sdim _(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz); 376274201Sdim _(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz); 377274201Sdim _(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz); 378274201Sdim _(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz); 379274201Sdim _(EVIOCGPROP, WRITE, 0); 380274201Sdim _(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz); 381274201Sdim _(FS_IOC_GETFLAGS, WRITE, sizeof(int)); 382274201Sdim _(FS_IOC_GETVERSION, WRITE, sizeof(int)); 383274201Sdim _(FS_IOC_SETFLAGS, READ, sizeof(int)); 384274201Sdim _(FS_IOC_SETVERSION, READ, sizeof(int)); 385274201Sdim _(GIO_CMAP, WRITE, 48); 386274201Sdim _(GIO_FONT, WRITE, 8192); 387274201Sdim _(GIO_SCRNMAP, WRITE, e_tabsz); 388274201Sdim _(GIO_UNIMAP, WRITE, struct_unimapdesc_sz); 389274201Sdim _(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz); 390274201Sdim _(KDADDIO, NONE, 0); 391274201Sdim _(KDDELIO, NONE, 0); 392274201Sdim _(KDDISABIO, NONE, 0); 393274201Sdim _(KDENABIO, NONE, 0); 394274201Sdim _(KDGETKEYCODE, WRITE, struct_kbkeycode_sz); 395274201Sdim _(KDGETLED, WRITE, 1); 396274201Sdim _(KDGETMODE, WRITE, sizeof(int)); 397274201Sdim _(KDGKBDIACR, WRITE, struct_kbdiacrs_sz); 398274201Sdim _(KDGKBENT, WRITE, struct_kbentry_sz); 399274201Sdim _(KDGKBLED, WRITE, sizeof(int)); 400274201Sdim _(KDGKBMETA, WRITE, sizeof(int)); 401274201Sdim _(KDGKBMODE, WRITE, sizeof(int)); 402274201Sdim _(KDGKBSENT, WRITE, struct_kbsentry_sz); 403274201Sdim _(KDGKBTYPE, WRITE, 1); 404274201Sdim _(KDMAPDISP, NONE, 0); 405274201Sdim _(KDMKTONE, NONE, 0); 406274201Sdim _(KDSETKEYCODE, READ, struct_kbkeycode_sz); 407274201Sdim _(KDSETLED, NONE, 0); 408274201Sdim _(KDSETMODE, NONE, 0); 409274201Sdim _(KDSIGACCEPT, NONE, 0); 410274201Sdim _(KDSKBDIACR, READ, struct_kbdiacrs_sz); 411274201Sdim _(KDSKBENT, READ, struct_kbentry_sz); 412274201Sdim _(KDSKBLED, NONE, 0); 413274201Sdim _(KDSKBMETA, NONE, 0); 414274201Sdim _(KDSKBMODE, NONE, 0); 415274201Sdim _(KDSKBSENT, READ, struct_kbsentry_sz); 416274201Sdim _(KDUNMAPDISP, NONE, 0); 417274201Sdim _(KIOCSOUND, NONE, 0); 418274201Sdim _(LPABORT, NONE, 0); 419274201Sdim _(LPABORTOPEN, NONE, 0); 420274201Sdim _(LPCAREFUL, NONE, 0); 421274201Sdim _(LPCHAR, NONE, 0); 422274201Sdim _(LPGETIRQ, WRITE, sizeof(int)); 423274201Sdim _(LPGETSTATUS, WRITE, sizeof(int)); 424274201Sdim _(LPRESET, NONE, 0); 425274201Sdim _(LPSETIRQ, NONE, 0); 426274201Sdim _(LPTIME, NONE, 0); 427274201Sdim _(LPWAIT, NONE, 0); 428274201Sdim _(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz); 429274201Sdim _(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz); 430274201Sdim _(PIO_CMAP, NONE, 0); 431274201Sdim _(PIO_FONT, READ, 8192); 432274201Sdim _(PIO_SCRNMAP, READ, e_tabsz); 433274201Sdim _(PIO_UNIMAP, READ, struct_unimapdesc_sz); 434274201Sdim _(PIO_UNIMAPCLR, READ, struct_unimapinit_sz); 435274201Sdim _(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz); 436274201Sdim _(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int)); 437274201Sdim _(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0); 438274201Sdim _(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0); 439274201Sdim _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz); 440274201Sdim _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz); 441274201Sdim _(TIOCGSERIAL, WRITE, struct_serial_struct_sz); 442274201Sdim _(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz); 443274201Sdim _(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz); 444274201Sdim _(TIOCSSERIAL, READ, struct_serial_struct_sz); 445274201Sdim 446274201Sdim // The following ioctl requests are shared between AX25, IPX, netrom and 447274201Sdim // mrouted. 448274201Sdim // _(SIOCAIPXITFCRT, READ, sizeof(char)); 449274201Sdim // _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz); 450274201Sdim // _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz); 451274201Sdim // _(SIOCAIPXPRISLT, READ, sizeof(char)); 452274201Sdim // _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz); 453274201Sdim // _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz); 454274201Sdim // _(SIOCNRDECOBS, NONE, 0); 455274201Sdim // _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz); 456274201Sdim // _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz); 457274201Sdim // _(SIOCAX25NOUID, READ, sizeof(int)); 458274201Sdim // _(SIOCNRRTCTL, READ, sizeof(int)); 459274201Sdim // _(SIOCAX25DIGCTL, READ, sizeof(int)); 460274201Sdim // _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz); 461274201Sdim // _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz); 462274201Sdim#endif 463274201Sdim#undef _ 464274201Sdim} 465274201Sdim 466274201Sdimstatic bool ioctl_initialized = false; 467274201Sdim 468274201Sdimstruct ioctl_desc_compare { 469274201Sdim bool operator()(const ioctl_desc& left, const ioctl_desc& right) const { 470274201Sdim return left.req < right.req; 471274201Sdim } 472274201Sdim}; 473274201Sdim 474274201Sdimstatic void ioctl_init() { 475274201Sdim ioctl_table_fill(); 476274201Sdim InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare()); 477274201Sdim 478274201Sdim bool bad = false; 479274201Sdim for (unsigned i = 0; i < ioctl_table_size - 1; ++i) { 480274201Sdim if (ioctl_table[i].req >= ioctl_table[i + 1].req) { 481274201Sdim Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n", 482274201Sdim ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name, 483274201Sdim ioctl_table[i + 1].name); 484274201Sdim bad = true; 485274201Sdim } 486274201Sdim } 487274201Sdim 488274201Sdim if (bad) Die(); 489274201Sdim 490274201Sdim ioctl_initialized = true; 491274201Sdim} 492274201Sdim 493274201Sdim// Handle the most evil ioctls that encode argument value as part of request id. 494274201Sdimstatic unsigned ioctl_request_fixup(unsigned req) { 495274201Sdim#if SANITIZER_LINUX 496276789Sdim // Strip size and event number. 497276789Sdim const unsigned kEviocgbitMask = 498276789Sdim (IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX; 499276789Sdim if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT) 500274201Sdim return IOCTL_EVIOCGBIT; 501276789Sdim // Strip absolute axis number. 502276789Sdim if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS) 503274201Sdim return IOCTL_EVIOCGABS; 504276789Sdim if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS) 505274201Sdim return IOCTL_EVIOCSABS; 506274201Sdim#endif 507274201Sdim return req; 508274201Sdim} 509274201Sdim 510274201Sdimstatic const ioctl_desc *ioctl_table_lookup(unsigned req) { 511274201Sdim int left = 0; 512274201Sdim int right = ioctl_table_size; 513274201Sdim while (left < right) { 514274201Sdim int mid = (left + right) / 2; 515274201Sdim if (ioctl_table[mid].req < req) 516274201Sdim left = mid + 1; 517274201Sdim else 518274201Sdim right = mid; 519274201Sdim } 520274201Sdim if (left == right && ioctl_table[left].req == req) 521274201Sdim return ioctl_table + left; 522274201Sdim else 523296417Sdim return nullptr; 524274201Sdim} 525274201Sdim 526276789Sdimstatic bool ioctl_decode(unsigned req, ioctl_desc *desc) { 527276789Sdim CHECK(desc); 528276789Sdim desc->req = req; 529276789Sdim desc->name = "<DECODED_IOCTL>"; 530276789Sdim desc->size = IOC_SIZE(req); 531276789Sdim // Sanity check. 532276789Sdim if (desc->size > 0xFFFF) return false; 533276789Sdim unsigned dir = IOC_DIR(req); 534276789Sdim switch (dir) { 535276789Sdim case IOC_NONE: 536276789Sdim desc->type = ioctl_desc::NONE; 537276789Sdim break; 538276789Sdim case IOC_READ | IOC_WRITE: 539276789Sdim desc->type = ioctl_desc::READWRITE; 540276789Sdim break; 541276789Sdim case IOC_READ: 542276789Sdim desc->type = ioctl_desc::WRITE; 543276789Sdim break; 544276789Sdim case IOC_WRITE: 545276789Sdim desc->type = ioctl_desc::READ; 546276789Sdim break; 547276789Sdim default: 548276789Sdim return false; 549276789Sdim } 550276789Sdim // Size can be 0 iff type is NONE. 551276789Sdim if ((desc->type == IOC_NONE) != (desc->size == 0)) return false; 552276789Sdim // Sanity check. 553276789Sdim if (IOC_TYPE(req) == 0) return false; 554276789Sdim return true; 555276789Sdim} 556276789Sdim 557274201Sdimstatic const ioctl_desc *ioctl_lookup(unsigned req) { 558274201Sdim req = ioctl_request_fixup(req); 559274201Sdim const ioctl_desc *desc = ioctl_table_lookup(req); 560274201Sdim if (desc) return desc; 561274201Sdim 562274201Sdim // Try stripping access size from the request id. 563276789Sdim desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT)); 564274201Sdim // Sanity check: requests that encode access size are either read or write and 565274201Sdim // have size of 0 in the table. 566274201Sdim if (desc && desc->size == 0 && 567276789Sdim (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE || 568276789Sdim desc->type == ioctl_desc::READ)) 569274201Sdim return desc; 570296417Sdim return nullptr; 571274201Sdim} 572274201Sdim 573274201Sdimstatic void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d, 574274201Sdim unsigned request, void *arg) { 575276789Sdim if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) { 576274201Sdim unsigned size = desc->size ? desc->size : IOC_SIZE(request); 577274201Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size); 578274201Sdim } 579274201Sdim if (desc->type != ioctl_desc::CUSTOM) 580274201Sdim return; 581288943Sdim if (request == IOCTL_SIOCGIFCONF) { 582288943Sdim struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg; 583288943Sdim COMMON_INTERCEPTOR_READ_RANGE(ctx, &ifc->ifc_len, sizeof(ifc->ifc_len)); 584274201Sdim } 585274201Sdim} 586274201Sdim 587274201Sdimstatic void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d, 588274201Sdim unsigned request, void *arg) { 589276789Sdim if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) { 590274201Sdim // FIXME: add verbose output 591274201Sdim unsigned size = desc->size ? desc->size : IOC_SIZE(request); 592274201Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size); 593274201Sdim } 594274201Sdim if (desc->type != ioctl_desc::CUSTOM) 595274201Sdim return; 596288943Sdim if (request == IOCTL_SIOCGIFCONF) { 597288943Sdim struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg; 598288943Sdim COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len); 599274201Sdim } 600274201Sdim} 601