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