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