]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // Ioctl handling in common sanitizer interceptors. | |
11 | //===----------------------------------------------------------------------===// | |
12 | ||
13 | #include "sanitizer_flags.h" | |
14 | ||
15 | struct ioctl_desc { | |
16 | unsigned req; | |
17 | // FIXME: support read+write arguments. Currently READWRITE and WRITE do the | |
18 | // same thing. | |
19 | // XXX: The declarations below may use WRITE instead of READWRITE, unless | |
20 | // explicitly noted. | |
21 | enum { | |
22 | NONE, | |
23 | READ, | |
24 | WRITE, | |
25 | READWRITE, | |
26 | CUSTOM | |
27 | } type : 3; | |
28 | unsigned size : 29; | |
29 | const char* name; | |
30 | }; | |
31 | ||
32 | const unsigned ioctl_table_max = 500; | |
33 | static ioctl_desc ioctl_table[ioctl_table_max]; | |
34 | static unsigned ioctl_table_size = 0; | |
35 | ||
36 | // This can not be declared as a global, because references to struct_*_sz | |
37 | // require a global initializer. And this table must be available before global | |
38 | // initializers are run. | |
39 | static void ioctl_table_fill() { | |
40 | #define _(rq, tp, sz) \ | |
41 | if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \ | |
42 | CHECK(ioctl_table_size < ioctl_table_max); \ | |
43 | ioctl_table[ioctl_table_size].req = IOCTL_##rq; \ | |
44 | ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \ | |
45 | ioctl_table[ioctl_table_size].size = sz; \ | |
46 | ioctl_table[ioctl_table_size].name = #rq; \ | |
47 | ++ioctl_table_size; \ | |
48 | } | |
49 | ||
50 | _(FIOASYNC, READ, sizeof(int)); | |
51 | _(FIOCLEX, NONE, 0); | |
52 | _(FIOGETOWN, WRITE, sizeof(int)); | |
53 | _(FIONBIO, READ, sizeof(int)); | |
54 | _(FIONCLEX, NONE, 0); | |
55 | _(FIOSETOWN, READ, sizeof(int)); | |
1a4d82fc | 56 | _(SIOCATMARK, WRITE, sizeof(int)); |
1a4d82fc | 57 | _(SIOCGIFCONF, CUSTOM, 0); |
1a4d82fc | 58 | _(SIOCGPGRP, WRITE, sizeof(int)); |
1a4d82fc JJ |
59 | _(SIOCSPGRP, READ, sizeof(int)); |
60 | _(TIOCCONS, NONE, 0); | |
61 | _(TIOCEXCL, NONE, 0); | |
62 | _(TIOCGETD, WRITE, sizeof(int)); | |
63 | _(TIOCGPGRP, WRITE, pid_t_sz); | |
64 | _(TIOCGWINSZ, WRITE, struct_winsize_sz); | |
65 | _(TIOCMBIC, READ, sizeof(int)); | |
66 | _(TIOCMBIS, READ, sizeof(int)); | |
67 | _(TIOCMGET, WRITE, sizeof(int)); | |
68 | _(TIOCMSET, READ, sizeof(int)); | |
69 | _(TIOCNOTTY, NONE, 0); | |
70 | _(TIOCNXCL, NONE, 0); | |
71 | _(TIOCOUTQ, WRITE, sizeof(int)); | |
72 | _(TIOCPKT, READ, sizeof(int)); | |
73 | _(TIOCSCTTY, NONE, 0); | |
74 | _(TIOCSETD, READ, sizeof(int)); | |
75 | _(TIOCSPGRP, READ, pid_t_sz); | |
76 | _(TIOCSTI, READ, sizeof(char)); | |
77 | _(TIOCSWINSZ, READ, struct_winsize_sz); | |
78 | ||
5bcae85e SL |
79 | #if !SANITIZER_IOS |
80 | _(SIOCADDMULTI, READ, struct_ifreq_sz); | |
81 | _(SIOCDELMULTI, READ, struct_ifreq_sz); | |
82 | _(SIOCGIFADDR, WRITE, struct_ifreq_sz); | |
83 | _(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz); | |
84 | _(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz); | |
85 | _(SIOCGIFFLAGS, WRITE, struct_ifreq_sz); | |
86 | _(SIOCGIFMETRIC, WRITE, struct_ifreq_sz); | |
87 | _(SIOCGIFMTU, WRITE, struct_ifreq_sz); | |
88 | _(SIOCGIFNETMASK, WRITE, struct_ifreq_sz); | |
89 | _(SIOCSIFADDR, READ, struct_ifreq_sz); | |
90 | _(SIOCSIFBRDADDR, READ, struct_ifreq_sz); | |
91 | _(SIOCSIFDSTADDR, READ, struct_ifreq_sz); | |
92 | _(SIOCSIFFLAGS, READ, struct_ifreq_sz); | |
93 | _(SIOCSIFMETRIC, READ, struct_ifreq_sz); | |
94 | _(SIOCSIFMTU, READ, struct_ifreq_sz); | |
95 | _(SIOCSIFNETMASK, READ, struct_ifreq_sz); | |
96 | #endif | |
97 | ||
1a4d82fc JJ |
98 | #if (SANITIZER_LINUX && !SANITIZER_ANDROID) |
99 | _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz); | |
100 | _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz); | |
101 | #endif | |
102 | ||
103 | #if SANITIZER_LINUX | |
104 | // Conflicting request ids. | |
105 | // _(CDROMAUDIOBUFSIZ, NONE, 0); | |
106 | // _(SNDCTL_TMR_CONTINUE, NONE, 0); | |
107 | // _(SNDCTL_TMR_START, NONE, 0); | |
108 | // _(SNDCTL_TMR_STOP, NONE, 0); | |
109 | // _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE | |
110 | // _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE | |
111 | // _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE | |
112 | // _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE | |
113 | _(BLKFLSBUF, NONE, 0); | |
114 | _(BLKGETSIZE, WRITE, sizeof(uptr)); | |
115 | _(BLKRAGET, WRITE, sizeof(int)); | |
116 | _(BLKRASET, NONE, 0); | |
117 | _(BLKROGET, WRITE, sizeof(int)); | |
118 | _(BLKROSET, READ, sizeof(int)); | |
119 | _(BLKRRPART, NONE, 0); | |
120 | _(CDROMEJECT, NONE, 0); | |
121 | _(CDROMEJECT_SW, NONE, 0); | |
122 | _(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz); | |
123 | _(CDROMPAUSE, NONE, 0); | |
124 | _(CDROMPLAYMSF, READ, struct_cdrom_msf_sz); | |
125 | _(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz); | |
126 | _(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz); | |
127 | _(CDROMREADCOOKED, READ, struct_cdrom_msf_sz); | |
128 | _(CDROMREADMODE1, READ, struct_cdrom_msf_sz); | |
129 | _(CDROMREADMODE2, READ, struct_cdrom_msf_sz); | |
130 | _(CDROMREADRAW, READ, struct_cdrom_msf_sz); | |
131 | _(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz); | |
132 | _(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz); | |
133 | _(CDROMRESET, NONE, 0); | |
134 | _(CDROMRESUME, NONE, 0); | |
135 | _(CDROMSEEK, READ, struct_cdrom_msf_sz); | |
136 | _(CDROMSTART, NONE, 0); | |
137 | _(CDROMSTOP, NONE, 0); | |
138 | _(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz); | |
139 | _(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz); | |
140 | _(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz); | |
141 | _(CDROM_GET_UPC, WRITE, 8); | |
142 | _(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup | |
143 | _(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup | |
144 | _(EVIOCGEFFECTS, WRITE, sizeof(int)); | |
145 | _(EVIOCGID, WRITE, struct_input_id_sz); | |
146 | _(EVIOCGKEY, WRITE, 0); | |
147 | _(EVIOCGKEYCODE, WRITE, sizeof(int) * 2); | |
148 | _(EVIOCGLED, WRITE, 0); | |
149 | _(EVIOCGNAME, WRITE, 0); | |
150 | _(EVIOCGPHYS, WRITE, 0); | |
151 | _(EVIOCGRAB, READ, sizeof(int)); | |
152 | _(EVIOCGREP, WRITE, sizeof(int) * 2); | |
153 | _(EVIOCGSND, WRITE, 0); | |
154 | _(EVIOCGSW, WRITE, 0); | |
155 | _(EVIOCGUNIQ, WRITE, 0); | |
156 | _(EVIOCGVERSION, WRITE, sizeof(int)); | |
157 | _(EVIOCRMFF, READ, sizeof(int)); | |
158 | _(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup | |
159 | _(EVIOCSFF, READ, struct_ff_effect_sz); | |
160 | _(EVIOCSKEYCODE, READ, sizeof(int) * 2); | |
161 | _(EVIOCSREP, READ, sizeof(int) * 2); | |
162 | _(FDCLRPRM, NONE, 0); | |
163 | _(FDDEFPRM, READ, struct_floppy_struct_sz); | |
164 | _(FDFLUSH, NONE, 0); | |
165 | _(FDFMTBEG, NONE, 0); | |
166 | _(FDFMTEND, NONE, 0); | |
167 | _(FDFMTTRK, READ, struct_format_descr_sz); | |
168 | _(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz); | |
169 | _(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz); | |
170 | _(FDGETDRVTYP, WRITE, 16); | |
171 | _(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz); | |
172 | _(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz); | |
173 | _(FDGETPRM, WRITE, struct_floppy_struct_sz); | |
174 | _(FDMSGOFF, NONE, 0); | |
175 | _(FDMSGON, NONE, 0); | |
176 | _(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz); | |
177 | _(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz); | |
178 | _(FDRESET, NONE, 0); | |
179 | _(FDSETDRVPRM, READ, struct_floppy_drive_params_sz); | |
180 | _(FDSETEMSGTRESH, NONE, 0); | |
181 | _(FDSETMAXERRS, READ, struct_floppy_max_errors_sz); | |
182 | _(FDSETPRM, READ, struct_floppy_struct_sz); | |
183 | _(FDTWADDLE, NONE, 0); | |
184 | _(FDWERRORCLR, NONE, 0); | |
185 | _(FDWERRORGET, WRITE, struct_floppy_write_errors_sz); | |
186 | _(HDIO_DRIVE_CMD, WRITE, sizeof(int)); | |
187 | _(HDIO_GETGEO, WRITE, struct_hd_geometry_sz); | |
188 | _(HDIO_GET_32BIT, WRITE, sizeof(int)); | |
189 | _(HDIO_GET_DMA, WRITE, sizeof(int)); | |
190 | _(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz); | |
191 | _(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int)); | |
192 | _(HDIO_GET_MULTCOUNT, WRITE, sizeof(int)); | |
193 | _(HDIO_GET_NOWERR, WRITE, sizeof(int)); | |
194 | _(HDIO_GET_UNMASKINTR, WRITE, sizeof(int)); | |
195 | _(HDIO_SET_32BIT, NONE, 0); | |
196 | _(HDIO_SET_DMA, NONE, 0); | |
197 | _(HDIO_SET_KEEPSETTINGS, NONE, 0); | |
198 | _(HDIO_SET_MULTCOUNT, NONE, 0); | |
199 | _(HDIO_SET_NOWERR, NONE, 0); | |
200 | _(HDIO_SET_UNMASKINTR, NONE, 0); | |
201 | _(MTIOCGET, WRITE, struct_mtget_sz); | |
202 | _(MTIOCPOS, WRITE, struct_mtpos_sz); | |
203 | _(MTIOCTOP, READ, struct_mtop_sz); | |
204 | _(PPPIOCGASYNCMAP, WRITE, sizeof(int)); | |
205 | _(PPPIOCGDEBUG, WRITE, sizeof(int)); | |
206 | _(PPPIOCGFLAGS, WRITE, sizeof(int)); | |
207 | _(PPPIOCGUNIT, WRITE, sizeof(int)); | |
208 | _(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8); | |
209 | _(PPPIOCSASYNCMAP, READ, sizeof(int)); | |
210 | _(PPPIOCSDEBUG, READ, sizeof(int)); | |
211 | _(PPPIOCSFLAGS, READ, sizeof(int)); | |
212 | _(PPPIOCSMAXCID, READ, sizeof(int)); | |
213 | _(PPPIOCSMRU, READ, sizeof(int)); | |
214 | _(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8); | |
215 | _(SIOCADDRT, READ, struct_rtentry_sz); | |
216 | _(SIOCDARP, READ, struct_arpreq_sz); | |
217 | _(SIOCDELRT, READ, struct_rtentry_sz); | |
218 | _(SIOCDRARP, READ, struct_arpreq_sz); | |
219 | _(SIOCGARP, WRITE, struct_arpreq_sz); | |
220 | _(SIOCGIFENCAP, WRITE, sizeof(int)); | |
221 | _(SIOCGIFHWADDR, WRITE, struct_ifreq_sz); | |
222 | _(SIOCGIFMAP, WRITE, struct_ifreq_sz); | |
223 | _(SIOCGIFMEM, WRITE, struct_ifreq_sz); | |
224 | _(SIOCGIFNAME, NONE, 0); | |
225 | _(SIOCGIFSLAVE, NONE, 0); | |
226 | _(SIOCGRARP, WRITE, struct_arpreq_sz); | |
227 | _(SIOCGSTAMP, WRITE, timeval_sz); | |
228 | _(SIOCSARP, READ, struct_arpreq_sz); | |
229 | _(SIOCSIFENCAP, READ, sizeof(int)); | |
230 | _(SIOCSIFHWADDR, READ, struct_ifreq_sz); | |
231 | _(SIOCSIFLINK, NONE, 0); | |
232 | _(SIOCSIFMAP, READ, struct_ifreq_sz); | |
233 | _(SIOCSIFMEM, READ, struct_ifreq_sz); | |
234 | _(SIOCSIFSLAVE, NONE, 0); | |
235 | _(SIOCSRARP, READ, struct_arpreq_sz); | |
236 | _(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz); | |
237 | _(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz); | |
238 | _(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz); | |
239 | _(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz); | |
240 | _(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz); | |
241 | _(SNDCTL_COPR_RESET, NONE, 0); | |
242 | _(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz); | |
243 | _(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz); | |
244 | _(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz); | |
245 | _(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz); | |
246 | _(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int)); | |
247 | _(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int)); | |
248 | _(SNDCTL_DSP_NONBLOCK, NONE, 0); | |
249 | _(SNDCTL_DSP_POST, NONE, 0); | |
250 | _(SNDCTL_DSP_RESET, NONE, 0); | |
251 | _(SNDCTL_DSP_SETFMT, WRITE, sizeof(int)); | |
252 | _(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int)); | |
253 | _(SNDCTL_DSP_SPEED, WRITE, sizeof(int)); | |
254 | _(SNDCTL_DSP_STEREO, WRITE, sizeof(int)); | |
255 | _(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int)); | |
256 | _(SNDCTL_DSP_SYNC, NONE, 0); | |
257 | _(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int)); | |
258 | _(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz); | |
259 | _(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz); | |
260 | _(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int)); | |
261 | _(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int)); | |
262 | _(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int)); | |
263 | _(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int)); | |
264 | _(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int)); | |
265 | _(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int)); | |
266 | _(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz); | |
267 | _(SNDCTL_SEQ_PANIC, NONE, 0); | |
268 | _(SNDCTL_SEQ_PERCMODE, NONE, 0); | |
269 | _(SNDCTL_SEQ_RESET, NONE, 0); | |
270 | _(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int)); | |
271 | _(SNDCTL_SEQ_SYNC, NONE, 0); | |
272 | _(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int)); | |
273 | _(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int)); | |
274 | _(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz); | |
275 | _(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int)); | |
276 | _(SNDCTL_TMR_METRONOME, READ, sizeof(int)); | |
277 | _(SNDCTL_TMR_SELECT, WRITE, sizeof(int)); | |
278 | _(SNDCTL_TMR_SOURCE, WRITE, sizeof(int)); | |
279 | _(SNDCTL_TMR_TEMPO, WRITE, sizeof(int)); | |
280 | _(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int)); | |
281 | _(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int)); | |
282 | _(SOUND_MIXER_READ_BASS, WRITE, sizeof(int)); | |
283 | _(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int)); | |
284 | _(SOUND_MIXER_READ_CD, WRITE, sizeof(int)); | |
285 | _(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int)); | |
286 | _(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int)); | |
287 | _(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int)); | |
288 | _(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int)); | |
289 | _(SOUND_MIXER_READ_LINE, WRITE, sizeof(int)); | |
290 | _(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int)); | |
291 | _(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int)); | |
292 | _(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int)); | |
293 | _(SOUND_MIXER_READ_MIC, WRITE, sizeof(int)); | |
294 | _(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int)); | |
295 | _(SOUND_MIXER_READ_PCM, WRITE, sizeof(int)); | |
296 | _(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int)); | |
297 | _(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int)); | |
298 | _(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int)); | |
299 | _(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int)); | |
300 | _(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int)); | |
301 | _(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int)); | |
302 | _(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int)); | |
303 | _(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int)); | |
304 | _(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int)); | |
305 | _(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int)); | |
306 | _(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int)); | |
307 | _(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int)); | |
308 | _(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int)); | |
309 | _(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int)); | |
310 | _(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int)); | |
311 | _(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int)); | |
312 | _(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int)); | |
313 | _(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int)); | |
314 | _(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int)); | |
315 | _(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int)); | |
316 | _(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int)); | |
317 | _(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int)); | |
318 | _(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int)); | |
319 | _(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int)); | |
320 | _(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int)); | |
321 | _(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int)); | |
322 | _(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int)); | |
323 | _(SOUND_PCM_READ_BITS, WRITE, sizeof(int)); | |
324 | _(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int)); | |
325 | _(SOUND_PCM_READ_FILTER, WRITE, sizeof(int)); | |
326 | _(SOUND_PCM_READ_RATE, WRITE, sizeof(int)); | |
327 | _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int)); | |
328 | _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int)); | |
329 | _(TCFLSH, NONE, 0); | |
330 | _(TCGETA, WRITE, struct_termio_sz); | |
331 | _(TCGETS, WRITE, struct_termios_sz); | |
332 | _(TCSBRK, NONE, 0); | |
333 | _(TCSBRKP, NONE, 0); | |
334 | _(TCSETA, READ, struct_termio_sz); | |
335 | _(TCSETAF, READ, struct_termio_sz); | |
336 | _(TCSETAW, READ, struct_termio_sz); | |
337 | _(TCSETS, READ, struct_termios_sz); | |
338 | _(TCSETSF, READ, struct_termios_sz); | |
339 | _(TCSETSW, READ, struct_termios_sz); | |
340 | _(TCXONC, NONE, 0); | |
341 | _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz); | |
342 | _(TIOCGSOFTCAR, WRITE, sizeof(int)); | |
343 | _(TIOCINQ, WRITE, sizeof(int)); | |
344 | _(TIOCLINUX, READ, sizeof(char)); | |
345 | _(TIOCSERCONFIG, NONE, 0); | |
346 | _(TIOCSERGETLSR, WRITE, sizeof(int)); | |
347 | _(TIOCSERGWILD, WRITE, sizeof(int)); | |
348 | _(TIOCSERSWILD, READ, sizeof(int)); | |
349 | _(TIOCSLCKTRMIOS, READ, struct_termios_sz); | |
350 | _(TIOCSSOFTCAR, READ, sizeof(int)); | |
351 | _(VT_ACTIVATE, NONE, 0); | |
352 | _(VT_DISALLOCATE, NONE, 0); | |
353 | _(VT_GETMODE, WRITE, struct_vt_mode_sz); | |
354 | _(VT_GETSTATE, WRITE, struct_vt_stat_sz); | |
355 | _(VT_OPENQRY, WRITE, sizeof(int)); | |
356 | _(VT_RELDISP, NONE, 0); | |
357 | _(VT_RESIZE, READ, struct_vt_sizes_sz); | |
358 | _(VT_RESIZEX, READ, struct_vt_consize_sz); | |
359 | _(VT_SENDSIG, NONE, 0); | |
360 | _(VT_SETMODE, READ, struct_vt_mode_sz); | |
361 | _(VT_WAITACTIVE, NONE, 0); | |
362 | #endif | |
363 | ||
364 | #if SANITIZER_LINUX && !SANITIZER_ANDROID | |
365 | // _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE | |
366 | _(CYGETDEFTHRESH, WRITE, sizeof(int)); | |
367 | _(CYGETDEFTIMEOUT, WRITE, sizeof(int)); | |
368 | _(CYGETMON, WRITE, struct_cyclades_monitor_sz); | |
369 | _(CYGETTHRESH, WRITE, sizeof(int)); | |
370 | _(CYGETTIMEOUT, WRITE, sizeof(int)); | |
371 | _(CYSETDEFTHRESH, NONE, 0); | |
372 | _(CYSETDEFTIMEOUT, NONE, 0); | |
373 | _(CYSETTHRESH, NONE, 0); | |
374 | _(CYSETTIMEOUT, NONE, 0); | |
375 | _(EQL_EMANCIPATE, WRITE, struct_ifreq_sz); | |
376 | _(EQL_ENSLAVE, WRITE, struct_ifreq_sz); | |
377 | _(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz); | |
378 | _(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz); | |
379 | _(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz); | |
380 | _(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz); | |
381 | _(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz); | |
382 | _(EVIOCGPROP, WRITE, 0); | |
383 | _(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz); | |
384 | _(FS_IOC_GETFLAGS, WRITE, sizeof(int)); | |
385 | _(FS_IOC_GETVERSION, WRITE, sizeof(int)); | |
386 | _(FS_IOC_SETFLAGS, READ, sizeof(int)); | |
387 | _(FS_IOC_SETVERSION, READ, sizeof(int)); | |
388 | _(GIO_CMAP, WRITE, 48); | |
389 | _(GIO_FONT, WRITE, 8192); | |
390 | _(GIO_SCRNMAP, WRITE, e_tabsz); | |
391 | _(GIO_UNIMAP, WRITE, struct_unimapdesc_sz); | |
392 | _(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz); | |
393 | _(KDADDIO, NONE, 0); | |
394 | _(KDDELIO, NONE, 0); | |
395 | _(KDDISABIO, NONE, 0); | |
396 | _(KDENABIO, NONE, 0); | |
397 | _(KDGETKEYCODE, WRITE, struct_kbkeycode_sz); | |
398 | _(KDGETLED, WRITE, 1); | |
399 | _(KDGETMODE, WRITE, sizeof(int)); | |
400 | _(KDGKBDIACR, WRITE, struct_kbdiacrs_sz); | |
401 | _(KDGKBENT, WRITE, struct_kbentry_sz); | |
402 | _(KDGKBLED, WRITE, sizeof(int)); | |
403 | _(KDGKBMETA, WRITE, sizeof(int)); | |
404 | _(KDGKBMODE, WRITE, sizeof(int)); | |
405 | _(KDGKBSENT, WRITE, struct_kbsentry_sz); | |
406 | _(KDGKBTYPE, WRITE, 1); | |
407 | _(KDMAPDISP, NONE, 0); | |
408 | _(KDMKTONE, NONE, 0); | |
409 | _(KDSETKEYCODE, READ, struct_kbkeycode_sz); | |
410 | _(KDSETLED, NONE, 0); | |
411 | _(KDSETMODE, NONE, 0); | |
412 | _(KDSIGACCEPT, NONE, 0); | |
413 | _(KDSKBDIACR, READ, struct_kbdiacrs_sz); | |
414 | _(KDSKBENT, READ, struct_kbentry_sz); | |
415 | _(KDSKBLED, NONE, 0); | |
416 | _(KDSKBMETA, NONE, 0); | |
417 | _(KDSKBMODE, NONE, 0); | |
418 | _(KDSKBSENT, READ, struct_kbsentry_sz); | |
419 | _(KDUNMAPDISP, NONE, 0); | |
420 | _(KIOCSOUND, NONE, 0); | |
421 | _(LPABORT, NONE, 0); | |
422 | _(LPABORTOPEN, NONE, 0); | |
423 | _(LPCAREFUL, NONE, 0); | |
424 | _(LPCHAR, NONE, 0); | |
425 | _(LPGETIRQ, WRITE, sizeof(int)); | |
426 | _(LPGETSTATUS, WRITE, sizeof(int)); | |
427 | _(LPRESET, NONE, 0); | |
428 | _(LPSETIRQ, NONE, 0); | |
429 | _(LPTIME, NONE, 0); | |
430 | _(LPWAIT, NONE, 0); | |
431 | _(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz); | |
432 | _(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz); | |
433 | _(PIO_CMAP, NONE, 0); | |
434 | _(PIO_FONT, READ, 8192); | |
435 | _(PIO_SCRNMAP, READ, e_tabsz); | |
436 | _(PIO_UNIMAP, READ, struct_unimapdesc_sz); | |
437 | _(PIO_UNIMAPCLR, READ, struct_unimapinit_sz); | |
438 | _(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz); | |
439 | _(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int)); | |
440 | _(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0); | |
441 | _(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0); | |
442 | _(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz); | |
443 | _(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz); | |
444 | _(TIOCGSERIAL, WRITE, struct_serial_struct_sz); | |
445 | _(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz); | |
446 | _(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz); | |
447 | _(TIOCSSERIAL, READ, struct_serial_struct_sz); | |
448 | ||
449 | // The following ioctl requests are shared between AX25, IPX, netrom and | |
450 | // mrouted. | |
451 | // _(SIOCAIPXITFCRT, READ, sizeof(char)); | |
452 | // _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz); | |
453 | // _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz); | |
454 | // _(SIOCAIPXPRISLT, READ, sizeof(char)); | |
455 | // _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz); | |
456 | // _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz); | |
457 | // _(SIOCNRDECOBS, NONE, 0); | |
458 | // _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz); | |
459 | // _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz); | |
460 | // _(SIOCAX25NOUID, READ, sizeof(int)); | |
461 | // _(SIOCNRRTCTL, READ, sizeof(int)); | |
462 | // _(SIOCAX25DIGCTL, READ, sizeof(int)); | |
463 | // _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz); | |
464 | // _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz); | |
465 | #endif | |
466 | #undef _ | |
467 | } | |
468 | ||
469 | static bool ioctl_initialized = false; | |
470 | ||
471 | struct ioctl_desc_compare { | |
472 | bool operator()(const ioctl_desc& left, const ioctl_desc& right) const { | |
473 | return left.req < right.req; | |
474 | } | |
475 | }; | |
476 | ||
477 | static void ioctl_init() { | |
478 | ioctl_table_fill(); | |
479 | InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare()); | |
480 | ||
481 | bool bad = false; | |
482 | for (unsigned i = 0; i < ioctl_table_size - 1; ++i) { | |
483 | if (ioctl_table[i].req >= ioctl_table[i + 1].req) { | |
484 | Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n", | |
485 | ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name, | |
486 | ioctl_table[i + 1].name); | |
487 | bad = true; | |
488 | } | |
489 | } | |
490 | ||
491 | if (bad) Die(); | |
492 | ||
493 | ioctl_initialized = true; | |
494 | } | |
495 | ||
496 | // Handle the most evil ioctls that encode argument value as part of request id. | |
497 | static unsigned ioctl_request_fixup(unsigned req) { | |
498 | #if SANITIZER_LINUX | |
499 | // Strip size and event number. | |
500 | const unsigned kEviocgbitMask = | |
501 | (IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX; | |
502 | if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT) | |
503 | return IOCTL_EVIOCGBIT; | |
504 | // Strip absolute axis number. | |
505 | if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS) | |
506 | return IOCTL_EVIOCGABS; | |
507 | if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS) | |
508 | return IOCTL_EVIOCSABS; | |
509 | #endif | |
510 | return req; | |
511 | } | |
512 | ||
513 | static const ioctl_desc *ioctl_table_lookup(unsigned req) { | |
514 | int left = 0; | |
515 | int right = ioctl_table_size; | |
516 | while (left < right) { | |
517 | int mid = (left + right) / 2; | |
518 | if (ioctl_table[mid].req < req) | |
519 | left = mid + 1; | |
520 | else | |
521 | right = mid; | |
522 | } | |
523 | if (left == right && ioctl_table[left].req == req) | |
524 | return ioctl_table + left; | |
525 | else | |
92a42be0 | 526 | return nullptr; |
1a4d82fc JJ |
527 | } |
528 | ||
529 | static bool ioctl_decode(unsigned req, ioctl_desc *desc) { | |
530 | CHECK(desc); | |
531 | desc->req = req; | |
532 | desc->name = "<DECODED_IOCTL>"; | |
533 | desc->size = IOC_SIZE(req); | |
534 | // Sanity check. | |
92a42be0 | 535 | if (desc->size > 0xFFFF) return false; |
1a4d82fc JJ |
536 | unsigned dir = IOC_DIR(req); |
537 | switch (dir) { | |
538 | case IOC_NONE: | |
539 | desc->type = ioctl_desc::NONE; | |
540 | break; | |
541 | case IOC_READ | IOC_WRITE: | |
542 | desc->type = ioctl_desc::READWRITE; | |
543 | break; | |
544 | case IOC_READ: | |
545 | desc->type = ioctl_desc::WRITE; | |
546 | break; | |
547 | case IOC_WRITE: | |
548 | desc->type = ioctl_desc::READ; | |
549 | break; | |
550 | default: | |
551 | return false; | |
552 | } | |
92a42be0 SL |
553 | // Size can be 0 iff type is NONE. |
554 | if ((desc->type == IOC_NONE) != (desc->size == 0)) return false; | |
1a4d82fc | 555 | // Sanity check. |
92a42be0 | 556 | if (IOC_TYPE(req) == 0) return false; |
1a4d82fc JJ |
557 | return true; |
558 | } | |
559 | ||
560 | static const ioctl_desc *ioctl_lookup(unsigned req) { | |
561 | req = ioctl_request_fixup(req); | |
562 | const ioctl_desc *desc = ioctl_table_lookup(req); | |
563 | if (desc) return desc; | |
564 | ||
565 | // Try stripping access size from the request id. | |
566 | desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT)); | |
567 | // Sanity check: requests that encode access size are either read or write and | |
568 | // have size of 0 in the table. | |
569 | if (desc && desc->size == 0 && | |
570 | (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE || | |
571 | desc->type == ioctl_desc::READ)) | |
572 | return desc; | |
92a42be0 | 573 | return nullptr; |
1a4d82fc JJ |
574 | } |
575 | ||
576 | static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d, | |
577 | unsigned request, void *arg) { | |
578 | if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) { | |
579 | unsigned size = desc->size ? desc->size : IOC_SIZE(request); | |
580 | COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size); | |
581 | } | |
582 | if (desc->type != ioctl_desc::CUSTOM) | |
583 | return; | |
92a42be0 SL |
584 | if (request == IOCTL_SIOCGIFCONF) { |
585 | struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg; | |
7cac9316 XL |
586 | COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len, |
587 | sizeof(ifc->ifc_len)); | |
1a4d82fc | 588 | } |
1a4d82fc JJ |
589 | } |
590 | ||
591 | static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d, | |
592 | unsigned request, void *arg) { | |
593 | if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) { | |
594 | // FIXME: add verbose output | |
595 | unsigned size = desc->size ? desc->size : IOC_SIZE(request); | |
596 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size); | |
597 | } | |
598 | if (desc->type != ioctl_desc::CUSTOM) | |
599 | return; | |
92a42be0 SL |
600 | if (request == IOCTL_SIOCGIFCONF) { |
601 | struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg; | |
602 | COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len); | |
1a4d82fc | 603 | } |
1a4d82fc | 604 | } |