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