2013-06-07 21:00:47 +08:00
|
|
|
//===-- sanitizer_common_interceptors_ioctl.inc -----------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Ioctl handling in common sanitizer interceptors.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-02-15 11:36:16 +08:00
|
|
|
#if !SANITIZER_NETBSD
|
|
|
|
|
2013-06-07 21:00:47 +08:00
|
|
|
#include "sanitizer_flags.h"
|
|
|
|
|
|
|
|
struct ioctl_desc {
|
|
|
|
unsigned req;
|
2014-01-31 22:02:21 +08:00
|
|
|
// FIXME: support read+write arguments. Currently READWRITE and WRITE do the
|
|
|
|
// same thing.
|
|
|
|
// XXX: The declarations below may use WRITE instead of READWRITE, unless
|
|
|
|
// explicitly noted.
|
2013-06-07 21:00:47 +08:00
|
|
|
enum {
|
|
|
|
NONE,
|
|
|
|
READ,
|
|
|
|
WRITE,
|
2014-01-31 22:02:21 +08:00
|
|
|
READWRITE,
|
2013-06-07 21:00:47 +08:00
|
|
|
CUSTOM
|
2014-01-31 22:02:21 +08:00
|
|
|
} type : 3;
|
|
|
|
unsigned size : 29;
|
2013-06-18 17:22:24 +08:00
|
|
|
const char* name;
|
2013-06-07 21:00:47 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const unsigned ioctl_table_max = 500;
|
|
|
|
static ioctl_desc ioctl_table[ioctl_table_max];
|
|
|
|
static unsigned ioctl_table_size = 0;
|
|
|
|
|
|
|
|
// This can not be declared as a global, because references to struct_*_sz
|
|
|
|
// require a global initializer. And this table must be available before global
|
|
|
|
// initializers are run.
|
|
|
|
static void ioctl_table_fill() {
|
2013-06-21 18:54:57 +08:00
|
|
|
#define _(rq, tp, sz) \
|
|
|
|
if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \
|
|
|
|
CHECK(ioctl_table_size < ioctl_table_max); \
|
|
|
|
ioctl_table[ioctl_table_size].req = IOCTL_##rq; \
|
|
|
|
ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \
|
|
|
|
ioctl_table[ioctl_table_size].size = sz; \
|
|
|
|
ioctl_table[ioctl_table_size].name = #rq; \
|
|
|
|
++ioctl_table_size; \
|
|
|
|
}
|
2013-06-07 21:00:47 +08:00
|
|
|
|
2013-06-18 17:22:24 +08:00
|
|
|
_(FIOASYNC, READ, sizeof(int));
|
|
|
|
_(FIOCLEX, NONE, 0);
|
|
|
|
_(FIOGETOWN, WRITE, sizeof(int));
|
|
|
|
_(FIONBIO, READ, sizeof(int));
|
|
|
|
_(FIONCLEX, NONE, 0);
|
|
|
|
_(FIOSETOWN, READ, sizeof(int));
|
|
|
|
_(SIOCATMARK, WRITE, sizeof(int));
|
|
|
|
_(SIOCGIFCONF, CUSTOM, 0);
|
|
|
|
_(SIOCGPGRP, WRITE, sizeof(int));
|
|
|
|
_(SIOCSPGRP, READ, sizeof(int));
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-06-18 17:22:24 +08:00
|
|
|
_(TIOCCONS, NONE, 0);
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif
|
2013-06-18 17:22:24 +08:00
|
|
|
_(TIOCEXCL, NONE, 0);
|
|
|
|
_(TIOCGETD, WRITE, sizeof(int));
|
|
|
|
_(TIOCGPGRP, WRITE, pid_t_sz);
|
|
|
|
_(TIOCGWINSZ, WRITE, struct_winsize_sz);
|
|
|
|
_(TIOCMBIC, READ, sizeof(int));
|
|
|
|
_(TIOCMBIS, READ, sizeof(int));
|
|
|
|
_(TIOCMGET, WRITE, sizeof(int));
|
|
|
|
_(TIOCMSET, READ, sizeof(int));
|
|
|
|
_(TIOCNOTTY, NONE, 0);
|
|
|
|
_(TIOCNXCL, NONE, 0);
|
|
|
|
_(TIOCOUTQ, WRITE, sizeof(int));
|
|
|
|
_(TIOCPKT, READ, sizeof(int));
|
|
|
|
_(TIOCSCTTY, NONE, 0);
|
|
|
|
_(TIOCSETD, READ, sizeof(int));
|
|
|
|
_(TIOCSPGRP, READ, pid_t_sz);
|
|
|
|
_(TIOCSTI, READ, sizeof(char));
|
|
|
|
_(TIOCSWINSZ, READ, struct_winsize_sz);
|
2013-06-07 22:56:54 +08:00
|
|
|
|
2016-02-02 10:01:17 +08:00
|
|
|
#if !SANITIZER_IOS
|
|
|
|
_(SIOCADDMULTI, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCDELMULTI, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFADDR, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFBRDADDR, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFDSTADDR, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFFLAGS, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFMETRIC, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFMTU, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFNETMASK, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFADDR, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFBRDADDR, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFDSTADDR, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFFLAGS, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFMETRIC, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFMTU, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFNETMASK, READ, struct_ifreq_sz);
|
|
|
|
#endif
|
|
|
|
|
2013-11-16 03:13:08 +08:00
|
|
|
#if (SANITIZER_LINUX && !SANITIZER_ANDROID)
|
2013-06-18 17:22:24 +08:00
|
|
|
_(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz);
|
|
|
|
_(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz);
|
2013-06-07 22:56:54 +08:00
|
|
|
#endif
|
2013-06-07 21:00:47 +08:00
|
|
|
|
|
|
|
#if SANITIZER_LINUX
|
2013-06-18 17:22:24 +08:00
|
|
|
// Conflicting request ids.
|
|
|
|
// _(CDROMAUDIOBUFSIZ, NONE, 0);
|
|
|
|
// _(SNDCTL_TMR_CONTINUE, NONE, 0);
|
|
|
|
// _(SNDCTL_TMR_START, NONE, 0);
|
|
|
|
// _(SNDCTL_TMR_STOP, NONE, 0);
|
|
|
|
// _(SOUND_MIXER_READ_LOUD, WRITE, sizeof(int)); // same as ...READ_ENHANCE
|
|
|
|
// _(SOUND_MIXER_READ_MUTE, WRITE, sizeof(int)); // same as ...READ_ENHANCE
|
|
|
|
// _(SOUND_MIXER_WRITE_LOUD, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
|
|
|
|
// _(SOUND_MIXER_WRITE_MUTE, WRITE, sizeof(int)); // same as ...WRITE_ENHANCE
|
|
|
|
_(BLKFLSBUF, NONE, 0);
|
|
|
|
_(BLKGETSIZE, WRITE, sizeof(uptr));
|
|
|
|
_(BLKRAGET, WRITE, sizeof(int));
|
|
|
|
_(BLKRASET, NONE, 0);
|
|
|
|
_(BLKROGET, WRITE, sizeof(int));
|
|
|
|
_(BLKROSET, READ, sizeof(int));
|
|
|
|
_(BLKRRPART, NONE, 0);
|
|
|
|
_(CDROMEJECT, NONE, 0);
|
|
|
|
_(CDROMEJECT_SW, NONE, 0);
|
|
|
|
_(CDROMMULTISESSION, WRITE, struct_cdrom_multisession_sz);
|
|
|
|
_(CDROMPAUSE, NONE, 0);
|
|
|
|
_(CDROMPLAYMSF, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMPLAYTRKIND, READ, struct_cdrom_ti_sz);
|
|
|
|
_(CDROMREADAUDIO, READ, struct_cdrom_read_audio_sz);
|
|
|
|
_(CDROMREADCOOKED, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMREADMODE1, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMREADMODE2, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMREADRAW, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMREADTOCENTRY, WRITE, struct_cdrom_tocentry_sz);
|
|
|
|
_(CDROMREADTOCHDR, WRITE, struct_cdrom_tochdr_sz);
|
|
|
|
_(CDROMRESET, NONE, 0);
|
|
|
|
_(CDROMRESUME, NONE, 0);
|
|
|
|
_(CDROMSEEK, READ, struct_cdrom_msf_sz);
|
|
|
|
_(CDROMSTART, NONE, 0);
|
|
|
|
_(CDROMSTOP, NONE, 0);
|
|
|
|
_(CDROMSUBCHNL, WRITE, struct_cdrom_subchnl_sz);
|
|
|
|
_(CDROMVOLCTRL, READ, struct_cdrom_volctrl_sz);
|
|
|
|
_(CDROMVOLREAD, WRITE, struct_cdrom_volctrl_sz);
|
|
|
|
_(CDROM_GET_UPC, WRITE, 8);
|
2013-06-20 17:19:28 +08:00
|
|
|
_(EVIOCGABS, WRITE, struct_input_absinfo_sz); // fixup
|
|
|
|
_(EVIOCGBIT, WRITE, struct_input_id_sz); // fixup
|
|
|
|
_(EVIOCGEFFECTS, WRITE, sizeof(int));
|
|
|
|
_(EVIOCGID, WRITE, struct_input_id_sz);
|
|
|
|
_(EVIOCGKEY, WRITE, 0);
|
|
|
|
_(EVIOCGKEYCODE, WRITE, sizeof(int) * 2);
|
|
|
|
_(EVIOCGLED, WRITE, 0);
|
|
|
|
_(EVIOCGNAME, WRITE, 0);
|
|
|
|
_(EVIOCGPHYS, WRITE, 0);
|
|
|
|
_(EVIOCGRAB, READ, sizeof(int));
|
|
|
|
_(EVIOCGREP, WRITE, sizeof(int) * 2);
|
|
|
|
_(EVIOCGSND, WRITE, 0);
|
|
|
|
_(EVIOCGSW, WRITE, 0);
|
|
|
|
_(EVIOCGUNIQ, WRITE, 0);
|
|
|
|
_(EVIOCGVERSION, WRITE, sizeof(int));
|
|
|
|
_(EVIOCRMFF, READ, sizeof(int));
|
|
|
|
_(EVIOCSABS, READ, struct_input_absinfo_sz); // fixup
|
|
|
|
_(EVIOCSFF, READ, struct_ff_effect_sz);
|
|
|
|
_(EVIOCSKEYCODE, READ, sizeof(int) * 2);
|
|
|
|
_(EVIOCSREP, READ, sizeof(int) * 2);
|
2013-06-18 17:22:24 +08:00
|
|
|
_(FDCLRPRM, NONE, 0);
|
|
|
|
_(FDDEFPRM, READ, struct_floppy_struct_sz);
|
|
|
|
_(FDFLUSH, NONE, 0);
|
|
|
|
_(FDFMTBEG, NONE, 0);
|
|
|
|
_(FDFMTEND, NONE, 0);
|
|
|
|
_(FDFMTTRK, READ, struct_format_descr_sz);
|
|
|
|
_(FDGETDRVPRM, WRITE, struct_floppy_drive_params_sz);
|
|
|
|
_(FDGETDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
|
|
|
|
_(FDGETDRVTYP, WRITE, 16);
|
|
|
|
_(FDGETFDCSTAT, WRITE, struct_floppy_fdc_state_sz);
|
|
|
|
_(FDGETMAXERRS, WRITE, struct_floppy_max_errors_sz);
|
|
|
|
_(FDGETPRM, WRITE, struct_floppy_struct_sz);
|
|
|
|
_(FDMSGOFF, NONE, 0);
|
|
|
|
_(FDMSGON, NONE, 0);
|
|
|
|
_(FDPOLLDRVSTAT, WRITE, struct_floppy_drive_struct_sz);
|
|
|
|
_(FDRAWCMD, WRITE, struct_floppy_raw_cmd_sz);
|
|
|
|
_(FDRESET, NONE, 0);
|
|
|
|
_(FDSETDRVPRM, READ, struct_floppy_drive_params_sz);
|
|
|
|
_(FDSETEMSGTRESH, NONE, 0);
|
|
|
|
_(FDSETMAXERRS, READ, struct_floppy_max_errors_sz);
|
|
|
|
_(FDSETPRM, READ, struct_floppy_struct_sz);
|
|
|
|
_(FDTWADDLE, NONE, 0);
|
|
|
|
_(FDWERRORCLR, NONE, 0);
|
|
|
|
_(FDWERRORGET, WRITE, struct_floppy_write_errors_sz);
|
|
|
|
_(HDIO_DRIVE_CMD, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GETGEO, WRITE, struct_hd_geometry_sz);
|
|
|
|
_(HDIO_GET_32BIT, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GET_DMA, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GET_IDENTITY, WRITE, struct_hd_driveid_sz);
|
|
|
|
_(HDIO_GET_KEEPSETTINGS, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GET_MULTCOUNT, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GET_NOWERR, WRITE, sizeof(int));
|
|
|
|
_(HDIO_GET_UNMASKINTR, WRITE, sizeof(int));
|
|
|
|
_(HDIO_SET_32BIT, NONE, 0);
|
|
|
|
_(HDIO_SET_DMA, NONE, 0);
|
|
|
|
_(HDIO_SET_KEEPSETTINGS, NONE, 0);
|
|
|
|
_(HDIO_SET_MULTCOUNT, NONE, 0);
|
|
|
|
_(HDIO_SET_NOWERR, NONE, 0);
|
|
|
|
_(HDIO_SET_UNMASKINTR, NONE, 0);
|
|
|
|
_(MTIOCGET, WRITE, struct_mtget_sz);
|
|
|
|
_(MTIOCPOS, WRITE, struct_mtpos_sz);
|
|
|
|
_(MTIOCTOP, READ, struct_mtop_sz);
|
|
|
|
_(PPPIOCGASYNCMAP, WRITE, sizeof(int));
|
|
|
|
_(PPPIOCGDEBUG, WRITE, sizeof(int));
|
|
|
|
_(PPPIOCGFLAGS, WRITE, sizeof(int));
|
|
|
|
_(PPPIOCGUNIT, WRITE, sizeof(int));
|
|
|
|
_(PPPIOCGXASYNCMAP, WRITE, sizeof(int) * 8);
|
|
|
|
_(PPPIOCSASYNCMAP, READ, sizeof(int));
|
|
|
|
_(PPPIOCSDEBUG, READ, sizeof(int));
|
|
|
|
_(PPPIOCSFLAGS, READ, sizeof(int));
|
|
|
|
_(PPPIOCSMAXCID, READ, sizeof(int));
|
|
|
|
_(PPPIOCSMRU, READ, sizeof(int));
|
|
|
|
_(PPPIOCSXASYNCMAP, READ, sizeof(int) * 8);
|
|
|
|
_(SIOCADDRT, READ, struct_rtentry_sz);
|
|
|
|
_(SIOCDARP, READ, struct_arpreq_sz);
|
|
|
|
_(SIOCDELRT, READ, struct_rtentry_sz);
|
|
|
|
_(SIOCDRARP, READ, struct_arpreq_sz);
|
|
|
|
_(SIOCGARP, WRITE, struct_arpreq_sz);
|
|
|
|
_(SIOCGIFENCAP, WRITE, sizeof(int));
|
|
|
|
_(SIOCGIFHWADDR, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFMAP, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFMEM, WRITE, struct_ifreq_sz);
|
|
|
|
_(SIOCGIFNAME, NONE, 0);
|
|
|
|
_(SIOCGIFSLAVE, NONE, 0);
|
|
|
|
_(SIOCGRARP, WRITE, struct_arpreq_sz);
|
|
|
|
_(SIOCGSTAMP, WRITE, timeval_sz);
|
|
|
|
_(SIOCSARP, READ, struct_arpreq_sz);
|
|
|
|
_(SIOCSIFENCAP, READ, sizeof(int));
|
|
|
|
_(SIOCSIFHWADDR, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFLINK, NONE, 0);
|
|
|
|
_(SIOCSIFMAP, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFMEM, READ, struct_ifreq_sz);
|
|
|
|
_(SIOCSIFSLAVE, NONE, 0);
|
|
|
|
_(SIOCSRARP, READ, struct_arpreq_sz);
|
|
|
|
_(SNDCTL_COPR_HALT, WRITE, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_COPR_LOAD, READ, struct_copr_buffer_sz);
|
|
|
|
_(SNDCTL_COPR_RCODE, WRITE, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_COPR_RCVMSG, WRITE, struct_copr_msg_sz);
|
|
|
|
_(SNDCTL_COPR_RDATA, WRITE, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_COPR_RESET, NONE, 0);
|
|
|
|
_(SNDCTL_COPR_RUN, WRITE, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_COPR_SENDMSG, READ, struct_copr_msg_sz);
|
|
|
|
_(SNDCTL_COPR_WCODE, READ, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_COPR_WDATA, READ, struct_copr_debug_buf_sz);
|
|
|
|
_(SNDCTL_DSP_GETBLKSIZE, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_GETFMTS, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_NONBLOCK, NONE, 0);
|
|
|
|
_(SNDCTL_DSP_POST, NONE, 0);
|
|
|
|
_(SNDCTL_DSP_RESET, NONE, 0);
|
|
|
|
_(SNDCTL_DSP_SETFMT, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_SETFRAGMENT, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_SPEED, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_STEREO, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_SUBDIVIDE, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_DSP_SYNC, NONE, 0);
|
|
|
|
_(SNDCTL_FM_4OP_ENABLE, READ, sizeof(int));
|
|
|
|
_(SNDCTL_FM_LOAD_INSTR, READ, struct_sbi_instrument_sz);
|
|
|
|
_(SNDCTL_MIDI_INFO, WRITE, struct_midi_info_sz);
|
|
|
|
_(SNDCTL_MIDI_PRETIME, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_CTRLRATE, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_GETINCOUNT, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_GETOUTCOUNT, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_NRMIDIS, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_NRSYNTHS, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_OUTOFBAND, READ, struct_seq_event_rec_sz);
|
|
|
|
_(SNDCTL_SEQ_PANIC, NONE, 0);
|
|
|
|
_(SNDCTL_SEQ_PERCMODE, NONE, 0);
|
|
|
|
_(SNDCTL_SEQ_RESET, NONE, 0);
|
|
|
|
_(SNDCTL_SEQ_RESETSAMPLES, READ, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_SYNC, NONE, 0);
|
|
|
|
_(SNDCTL_SEQ_TESTMIDI, READ, sizeof(int));
|
|
|
|
_(SNDCTL_SEQ_THRESHOLD, READ, sizeof(int));
|
|
|
|
_(SNDCTL_SYNTH_INFO, WRITE, struct_synth_info_sz);
|
|
|
|
_(SNDCTL_SYNTH_MEMAVL, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_TMR_METRONOME, READ, sizeof(int));
|
|
|
|
_(SNDCTL_TMR_SELECT, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_TMR_SOURCE, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_TMR_TEMPO, WRITE, sizeof(int));
|
|
|
|
_(SNDCTL_TMR_TIMEBASE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_ALTPCM, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_BASS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_CAPS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_CD, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_DEVMASK, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_ENHANCE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_IGAIN, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_IMIX, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_LINE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_LINE1, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_LINE2, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_LINE3, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_MIC, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_OGAIN, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_PCM, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_RECLEV, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_RECMASK, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_RECSRC, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_SPEAKER, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_STEREODEVS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_SYNTH, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_TREBLE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_READ_VOLUME, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_ALTPCM, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_BASS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_CD, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_ENHANCE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_IGAIN, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_IMIX, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_LINE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_LINE1, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_LINE2, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_LINE3, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_MIC, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_OGAIN, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_PCM, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_RECLEV, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_RECSRC, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_SPEAKER, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_SYNTH, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_TREBLE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_MIXER_WRITE_VOLUME, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_READ_BITS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_READ_CHANNELS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_READ_FILTER, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_READ_RATE, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
|
|
|
|
_(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
|
|
|
|
_(TCFLSH, NONE, 0);
|
|
|
|
_(TCGETA, WRITE, struct_termio_sz);
|
|
|
|
_(TCGETS, WRITE, struct_termios_sz);
|
|
|
|
_(TCSBRK, NONE, 0);
|
|
|
|
_(TCSBRKP, NONE, 0);
|
|
|
|
_(TCSETA, READ, struct_termio_sz);
|
|
|
|
_(TCSETAF, READ, struct_termio_sz);
|
|
|
|
_(TCSETAW, READ, struct_termio_sz);
|
|
|
|
_(TCSETS, READ, struct_termios_sz);
|
|
|
|
_(TCSETSF, READ, struct_termios_sz);
|
|
|
|
_(TCSETSW, READ, struct_termios_sz);
|
|
|
|
_(TCXONC, NONE, 0);
|
|
|
|
_(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
|
|
|
|
_(TIOCGSOFTCAR, WRITE, sizeof(int));
|
|
|
|
_(TIOCINQ, WRITE, sizeof(int));
|
|
|
|
_(TIOCLINUX, READ, sizeof(char));
|
|
|
|
_(TIOCSERCONFIG, NONE, 0);
|
|
|
|
_(TIOCSERGETLSR, WRITE, sizeof(int));
|
|
|
|
_(TIOCSERGWILD, WRITE, sizeof(int));
|
|
|
|
_(TIOCSERSWILD, READ, sizeof(int));
|
|
|
|
_(TIOCSLCKTRMIOS, READ, struct_termios_sz);
|
|
|
|
_(TIOCSSOFTCAR, READ, sizeof(int));
|
|
|
|
_(VT_ACTIVATE, NONE, 0);
|
|
|
|
_(VT_DISALLOCATE, NONE, 0);
|
|
|
|
_(VT_GETMODE, WRITE, struct_vt_mode_sz);
|
|
|
|
_(VT_GETSTATE, WRITE, struct_vt_stat_sz);
|
|
|
|
_(VT_OPENQRY, WRITE, sizeof(int));
|
|
|
|
_(VT_RELDISP, NONE, 0);
|
|
|
|
_(VT_RESIZE, READ, struct_vt_sizes_sz);
|
|
|
|
_(VT_RESIZEX, READ, struct_vt_consize_sz);
|
|
|
|
_(VT_SENDSIG, NONE, 0);
|
|
|
|
_(VT_SETMODE, READ, struct_vt_mode_sz);
|
|
|
|
_(VT_WAITACTIVE, NONE, 0);
|
2014-01-31 22:28:32 +08:00
|
|
|
#endif
|
2014-01-31 22:02:21 +08:00
|
|
|
|
2014-01-31 22:28:32 +08:00
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
2013-06-18 17:22:24 +08:00
|
|
|
// _(SIOCDEVPLIP, WRITE, struct_ifreq_sz); // the same as EQL_ENSLAVE
|
|
|
|
_(CYGETDEFTHRESH, WRITE, sizeof(int));
|
|
|
|
_(CYGETDEFTIMEOUT, WRITE, sizeof(int));
|
|
|
|
_(CYGETMON, WRITE, struct_cyclades_monitor_sz);
|
|
|
|
_(CYGETTHRESH, WRITE, sizeof(int));
|
|
|
|
_(CYGETTIMEOUT, WRITE, sizeof(int));
|
|
|
|
_(CYSETDEFTHRESH, NONE, 0);
|
|
|
|
_(CYSETDEFTIMEOUT, NONE, 0);
|
|
|
|
_(CYSETTHRESH, NONE, 0);
|
|
|
|
_(CYSETTIMEOUT, NONE, 0);
|
|
|
|
_(EQL_EMANCIPATE, WRITE, struct_ifreq_sz);
|
|
|
|
_(EQL_ENSLAVE, WRITE, struct_ifreq_sz);
|
|
|
|
_(EQL_GETMASTRCFG, WRITE, struct_ifreq_sz);
|
|
|
|
_(EQL_GETSLAVECFG, WRITE, struct_ifreq_sz);
|
|
|
|
_(EQL_SETMASTRCFG, WRITE, struct_ifreq_sz);
|
|
|
|
_(EQL_SETSLAVECFG, WRITE, struct_ifreq_sz);
|
2013-06-20 17:19:28 +08:00
|
|
|
_(EVIOCGKEYCODE_V2, WRITE, struct_input_keymap_entry_sz);
|
|
|
|
_(EVIOCGPROP, WRITE, 0);
|
|
|
|
_(EVIOCSKEYCODE_V2, READ, struct_input_keymap_entry_sz);
|
2013-06-18 21:56:12 +08:00
|
|
|
_(FS_IOC_GETFLAGS, WRITE, sizeof(int));
|
|
|
|
_(FS_IOC_GETVERSION, WRITE, sizeof(int));
|
|
|
|
_(FS_IOC_SETFLAGS, READ, sizeof(int));
|
|
|
|
_(FS_IOC_SETVERSION, READ, sizeof(int));
|
2013-06-18 17:22:24 +08:00
|
|
|
_(GIO_CMAP, WRITE, 48);
|
|
|
|
_(GIO_FONT, WRITE, 8192);
|
|
|
|
_(GIO_SCRNMAP, WRITE, e_tabsz);
|
|
|
|
_(GIO_UNIMAP, WRITE, struct_unimapdesc_sz);
|
|
|
|
_(GIO_UNISCRNMAP, WRITE, sizeof(short) * e_tabsz);
|
|
|
|
_(KDADDIO, NONE, 0);
|
|
|
|
_(KDDELIO, NONE, 0);
|
|
|
|
_(KDDISABIO, NONE, 0);
|
|
|
|
_(KDENABIO, NONE, 0);
|
|
|
|
_(KDGETKEYCODE, WRITE, struct_kbkeycode_sz);
|
|
|
|
_(KDGETLED, WRITE, 1);
|
|
|
|
_(KDGETMODE, WRITE, sizeof(int));
|
|
|
|
_(KDGKBDIACR, WRITE, struct_kbdiacrs_sz);
|
|
|
|
_(KDGKBENT, WRITE, struct_kbentry_sz);
|
|
|
|
_(KDGKBLED, WRITE, sizeof(int));
|
|
|
|
_(KDGKBMETA, WRITE, sizeof(int));
|
|
|
|
_(KDGKBMODE, WRITE, sizeof(int));
|
|
|
|
_(KDGKBSENT, WRITE, struct_kbsentry_sz);
|
|
|
|
_(KDGKBTYPE, WRITE, 1);
|
|
|
|
_(KDMAPDISP, NONE, 0);
|
|
|
|
_(KDMKTONE, NONE, 0);
|
|
|
|
_(KDSETKEYCODE, READ, struct_kbkeycode_sz);
|
|
|
|
_(KDSETLED, NONE, 0);
|
|
|
|
_(KDSETMODE, NONE, 0);
|
|
|
|
_(KDSIGACCEPT, NONE, 0);
|
|
|
|
_(KDSKBDIACR, READ, struct_kbdiacrs_sz);
|
|
|
|
_(KDSKBENT, READ, struct_kbentry_sz);
|
|
|
|
_(KDSKBLED, NONE, 0);
|
|
|
|
_(KDSKBMETA, NONE, 0);
|
|
|
|
_(KDSKBMODE, NONE, 0);
|
|
|
|
_(KDSKBSENT, READ, struct_kbsentry_sz);
|
|
|
|
_(KDUNMAPDISP, NONE, 0);
|
|
|
|
_(KIOCSOUND, NONE, 0);
|
|
|
|
_(LPABORT, NONE, 0);
|
|
|
|
_(LPABORTOPEN, NONE, 0);
|
|
|
|
_(LPCAREFUL, NONE, 0);
|
|
|
|
_(LPCHAR, NONE, 0);
|
|
|
|
_(LPGETIRQ, WRITE, sizeof(int));
|
|
|
|
_(LPGETSTATUS, WRITE, sizeof(int));
|
|
|
|
_(LPRESET, NONE, 0);
|
|
|
|
_(LPSETIRQ, NONE, 0);
|
|
|
|
_(LPTIME, NONE, 0);
|
|
|
|
_(LPWAIT, NONE, 0);
|
2013-08-18 16:47:06 +08:00
|
|
|
_(MTIOCGETCONFIG, WRITE, struct_mtconfiginfo_sz);
|
|
|
|
_(MTIOCSETCONFIG, READ, struct_mtconfiginfo_sz);
|
2013-06-18 17:22:24 +08:00
|
|
|
_(PIO_CMAP, NONE, 0);
|
|
|
|
_(PIO_FONT, READ, 8192);
|
|
|
|
_(PIO_SCRNMAP, READ, e_tabsz);
|
|
|
|
_(PIO_UNIMAP, READ, struct_unimapdesc_sz);
|
|
|
|
_(PIO_UNIMAPCLR, READ, struct_unimapinit_sz);
|
|
|
|
_(PIO_UNISCRNMAP, READ, sizeof(short) * e_tabsz);
|
|
|
|
_(SCSI_IOCTL_PROBE_HOST, READ, sizeof(int));
|
|
|
|
_(SCSI_IOCTL_TAGGED_DISABLE, NONE, 0);
|
|
|
|
_(SCSI_IOCTL_TAGGED_ENABLE, NONE, 0);
|
|
|
|
_(SNDCTL_DSP_GETISPACE, WRITE, struct_audio_buf_info_sz);
|
|
|
|
_(SNDCTL_DSP_GETOSPACE, WRITE, struct_audio_buf_info_sz);
|
|
|
|
_(TIOCGSERIAL, WRITE, struct_serial_struct_sz);
|
|
|
|
_(TIOCSERGETMULTI, WRITE, struct_serial_multiport_struct_sz);
|
|
|
|
_(TIOCSERSETMULTI, READ, struct_serial_multiport_struct_sz);
|
|
|
|
_(TIOCSSERIAL, READ, struct_serial_struct_sz);
|
2013-06-07 21:00:47 +08:00
|
|
|
|
|
|
|
// The following ioctl requests are shared between AX25, IPX, netrom and
|
|
|
|
// mrouted.
|
2013-06-18 17:22:24 +08:00
|
|
|
// _(SIOCAIPXITFCRT, READ, sizeof(char));
|
|
|
|
// _(SIOCAX25GETUID, READ, struct_sockaddr_ax25_sz);
|
|
|
|
// _(SIOCNRGETPARMS, WRITE, struct_nr_parms_struct_sz);
|
|
|
|
// _(SIOCAIPXPRISLT, READ, sizeof(char));
|
|
|
|
// _(SIOCNRSETPARMS, READ, struct_nr_parms_struct_sz);
|
|
|
|
// _(SIOCAX25ADDUID, READ, struct_sockaddr_ax25_sz);
|
|
|
|
// _(SIOCNRDECOBS, NONE, 0);
|
|
|
|
// _(SIOCAX25DELUID, READ, struct_sockaddr_ax25_sz);
|
|
|
|
// _(SIOCIPXCFGDATA, WRITE, struct_ipx_config_data_sz);
|
|
|
|
// _(SIOCAX25NOUID, READ, sizeof(int));
|
|
|
|
// _(SIOCNRRTCTL, READ, sizeof(int));
|
|
|
|
// _(SIOCAX25DIGCTL, READ, sizeof(int));
|
|
|
|
// _(SIOCAX25GETPARMS, WRITE, struct_ax25_parms_struct_sz);
|
|
|
|
// _(SIOCAX25SETPARMS, READ, struct_ax25_parms_struct_sz);
|
2013-06-07 21:00:47 +08:00
|
|
|
#endif
|
|
|
|
#undef _
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ioctl_initialized = false;
|
|
|
|
|
|
|
|
struct ioctl_desc_compare {
|
|
|
|
bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {
|
|
|
|
return left.req < right.req;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ioctl_init() {
|
|
|
|
ioctl_table_fill();
|
|
|
|
InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare());
|
|
|
|
|
2013-06-18 17:22:24 +08:00
|
|
|
bool bad = false;
|
2013-06-07 21:00:47 +08:00
|
|
|
for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {
|
|
|
|
if (ioctl_table[i].req >= ioctl_table[i + 1].req) {
|
2013-06-18 17:22:24 +08:00
|
|
|
Printf("Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\n",
|
|
|
|
ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,
|
|
|
|
ioctl_table[i + 1].name);
|
|
|
|
bad = true;
|
2013-06-07 21:00:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 17:22:24 +08:00
|
|
|
if (bad) Die();
|
|
|
|
|
2013-06-07 21:00:47 +08:00
|
|
|
ioctl_initialized = true;
|
|
|
|
}
|
|
|
|
|
2013-06-20 17:19:28 +08:00
|
|
|
// Handle the most evil ioctls that encode argument value as part of request id.
|
|
|
|
static unsigned ioctl_request_fixup(unsigned req) {
|
2013-06-20 17:39:34 +08:00
|
|
|
#if SANITIZER_LINUX
|
2014-02-06 03:35:24 +08:00
|
|
|
// Strip size and event number.
|
|
|
|
const unsigned kEviocgbitMask =
|
|
|
|
(IOC_SIZEMASK << IOC_SIZESHIFT) | EVIOC_EV_MAX;
|
|
|
|
if ((req & ~kEviocgbitMask) == IOCTL_EVIOCGBIT)
|
2013-06-20 17:19:28 +08:00
|
|
|
return IOCTL_EVIOCGBIT;
|
2014-02-06 03:35:24 +08:00
|
|
|
// Strip absolute axis number.
|
|
|
|
if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCGABS)
|
2013-06-20 17:19:28 +08:00
|
|
|
return IOCTL_EVIOCGABS;
|
2014-02-06 03:35:24 +08:00
|
|
|
if ((req & ~EVIOC_ABS_MAX) == IOCTL_EVIOCSABS)
|
2013-06-20 17:19:28 +08:00
|
|
|
return IOCTL_EVIOCSABS;
|
2013-06-20 17:39:34 +08:00
|
|
|
#endif
|
2013-06-20 17:19:28 +08:00
|
|
|
return req;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const ioctl_desc *ioctl_table_lookup(unsigned req) {
|
2013-06-07 21:00:47 +08:00
|
|
|
int left = 0;
|
2013-06-18 17:22:24 +08:00
|
|
|
int right = ioctl_table_size;
|
2013-06-07 21:00:47 +08:00
|
|
|
while (left < right) {
|
|
|
|
int mid = (left + right) / 2;
|
|
|
|
if (ioctl_table[mid].req < req)
|
|
|
|
left = mid + 1;
|
|
|
|
else
|
|
|
|
right = mid;
|
|
|
|
}
|
|
|
|
if (left == right && ioctl_table[left].req == req)
|
|
|
|
return ioctl_table + left;
|
|
|
|
else
|
2015-09-30 02:23:36 +08:00
|
|
|
return nullptr;
|
2013-06-07 21:00:47 +08:00
|
|
|
}
|
|
|
|
|
2014-02-06 03:35:24 +08:00
|
|
|
static bool ioctl_decode(unsigned req, ioctl_desc *desc) {
|
|
|
|
CHECK(desc);
|
|
|
|
desc->req = req;
|
|
|
|
desc->name = "<DECODED_IOCTL>";
|
|
|
|
desc->size = IOC_SIZE(req);
|
|
|
|
// Sanity check.
|
2014-06-10 21:54:15 +08:00
|
|
|
if (desc->size > 0xFFFF) return false;
|
2014-02-06 03:35:24 +08:00
|
|
|
unsigned dir = IOC_DIR(req);
|
|
|
|
switch (dir) {
|
|
|
|
case IOC_NONE:
|
|
|
|
desc->type = ioctl_desc::NONE;
|
|
|
|
break;
|
|
|
|
case IOC_READ | IOC_WRITE:
|
|
|
|
desc->type = ioctl_desc::READWRITE;
|
|
|
|
break;
|
|
|
|
case IOC_READ:
|
|
|
|
desc->type = ioctl_desc::WRITE;
|
|
|
|
break;
|
|
|
|
case IOC_WRITE:
|
|
|
|
desc->type = ioctl_desc::READ;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-10 21:54:15 +08:00
|
|
|
// Size can be 0 iff type is NONE.
|
|
|
|
if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;
|
2014-02-06 03:35:24 +08:00
|
|
|
// Sanity check.
|
2014-06-10 21:54:15 +08:00
|
|
|
if (IOC_TYPE(req) == 0) return false;
|
2014-02-06 03:35:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-20 17:19:28 +08:00
|
|
|
static const ioctl_desc *ioctl_lookup(unsigned req) {
|
|
|
|
req = ioctl_request_fixup(req);
|
|
|
|
const ioctl_desc *desc = ioctl_table_lookup(req);
|
|
|
|
if (desc) return desc;
|
|
|
|
|
|
|
|
// Try stripping access size from the request id.
|
2014-02-06 03:35:24 +08:00
|
|
|
desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));
|
2013-06-20 17:19:28 +08:00
|
|
|
// Sanity check: requests that encode access size are either read or write and
|
|
|
|
// have size of 0 in the table.
|
|
|
|
if (desc && desc->size == 0 &&
|
2014-01-31 22:02:21 +08:00
|
|
|
(desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||
|
|
|
|
desc->type == ioctl_desc::READ))
|
2013-06-20 17:19:28 +08:00
|
|
|
return desc;
|
2015-09-30 02:23:36 +08:00
|
|
|
return nullptr;
|
2013-06-20 17:19:28 +08:00
|
|
|
}
|
|
|
|
|
2013-06-07 21:00:47 +08:00
|
|
|
static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,
|
|
|
|
unsigned request, void *arg) {
|
2014-01-31 22:02:21 +08:00
|
|
|
if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {
|
2013-06-20 17:19:28 +08:00
|
|
|
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);
|
|
|
|
}
|
2013-06-07 21:00:47 +08:00
|
|
|
if (desc->type != ioctl_desc::CUSTOM)
|
|
|
|
return;
|
2015-05-06 17:28:48 +08:00
|
|
|
if (request == IOCTL_SIOCGIFCONF) {
|
|
|
|
struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
|
2016-08-17 02:28:55 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,
|
|
|
|
sizeof(ifc->ifc_len));
|
2013-06-07 23:49:38 +08:00
|
|
|
}
|
2013-06-07 21:00:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,
|
|
|
|
unsigned request, void *arg) {
|
2014-01-31 22:02:21 +08:00
|
|
|
if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {
|
2013-06-07 21:00:47 +08:00
|
|
|
// FIXME: add verbose output
|
2013-06-20 17:19:28 +08:00
|
|
|
unsigned size = desc->size ? desc->size : IOC_SIZE(request);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);
|
2013-06-07 21:00:47 +08:00
|
|
|
}
|
|
|
|
if (desc->type != ioctl_desc::CUSTOM)
|
|
|
|
return;
|
2015-05-06 17:28:48 +08:00
|
|
|
if (request == IOCTL_SIOCGIFCONF) {
|
|
|
|
struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);
|
2013-06-07 23:49:38 +08:00
|
|
|
}
|
2013-06-07 21:00:47 +08:00
|
|
|
}
|
2018-02-15 11:36:16 +08:00
|
|
|
|
|
|
|
#endif
|