diff options
| author | fellair <tesladead43@gmail.com> | 2025-07-02 19:58:36 +0300 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-07-03 16:23:58 +0000 |
| commit | cf8b8b8b8e8f09b27400e9142344371d01f5e423 (patch) | |
| tree | 1e3412845e9730d92eb2dade69493559e156076b /sys | |
| parent | bc0864f30bea915b77f6850a384665e2cd0c417f (diff) | |
sys/linux: add descriptions for COMEDI devices
Currently, only usb COMEDI drivers are covered thanks to external usb
fuzzing approach. However, that still leaves /dev/comedi# devices
untested, thus this change.
There are 2 ways to make kernel spawn comedi devices. First, it seems
that one is created once driver identifies available hardware. Second,
provided a kernel paramater comedi.comedi_num_legacy_minors=N is set,
the same number of manually configurable devices are created,
allowing for configuration using one of the IOCTLs. Both scenarios do
not allow for particularly deep fuzzing as lack of necessary hardware
will inevitably stop any exploration short. Still, it is a start.
What is added:
- Descriptions for all COMEDI-related IOCTLs and structures.
Some arbitrary limits were set on array and list sizes, otherwise
numerous, overly greedy kmallocs slow down fuzzing with constant
warnings.
- List COMEDI devices to open.
A hardcoded list of device names is the best we can do at this point.
First few devs are for manual configuration (see
comedi_num_legacy_minors=N), others - for dynamic ones (N+1, N+2 etc).
- List manually configurable drivers.
COMEDI_DEVCONFIG ioctl takes a driver name from a list of those that
supposedly can be set up that way. No reason to try others.
Tested on a local x86_64 syzkaller instance with enabled_syscalls[].
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/linux/dev_comedi.txt | 172 | ||||
| -rw-r--r-- | sys/linux/dev_comedi.txt.const | 103 |
2 files changed, 275 insertions, 0 deletions
diff --git a/sys/linux/dev_comedi.txt b/sys/linux/dev_comedi.txt new file mode 100644 index 000000000..05c1607d3 --- /dev/null +++ b/sys/linux/dev_comedi.txt @@ -0,0 +1,172 @@ +# Copyright 2025 syzkaller project authors. All rights reserved. +# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +include <uapi/asm/ioctl.h> +include <uapi/linux/fcntl.h> +include <uapi/linux/comedi.h> + +# Descriptions for fuzzing COMEDI drivers. + +# Currently, there is little hope to fuzz most comedi drivers as that requires special qemu setup with emulated pci capabilities, +# while some usb drivers (like vmk80xx) are accessible via vusb approach. +# For now, focus instead on manually configurable legacy drivers: create static devices via module option comedi.comedi_num_legacy_minors, +# and attempt to configure them via COMEDI_DEVCONFIG ioctl. This leads to marginally deeper exploration of this driver stack. + +# TODO: Expand coverage properly by emulating required pci hardware. + +resource fd_comedi[fd] + +openat$comedi(fd const[AT_FDCWD], file ptr[in, string[comedi_devices]], flags flags[open_flags], mode const[0]) fd_comedi + +# Account for both configurable and dynamically allocated comedi devices. Depending on what value is passed +# to config option 'comedi.comedi_num_legacy_minors=N', the first N devices will be static. No reason to set N +# higher than 4. +# TODO: Come up with a more elegant way to list devices to open. Maybe a modified syz_open_dev() is in order? +comedi_devices = "/dev/comedi0", "/dev/comedi1", "/dev/comedi2", "/dev/comedi3", "/dev/comedi4", "/dev/comedi5" + +ioctl$COMEDI_DEVCONFIG(fd fd_comedi, cmd const[COMEDI_DEVCONFIG], arg ptr[in, comedi_devconfig]) +ioctl$COMEDI_DEVINFO(fd fd_comedi, cmd const[COMEDI_DEVINFO], arg ptr[out, comedi_devinfo]) +ioctl$COMEDI_SUBDINFO(fd fd_comedi, cmd const[COMEDI_SUBDINFO], arg ptr[out, comedi_subdinfo]) +ioctl$COMEDI_CHANINFO(fd fd_comedi, cmd const[COMEDI_CHANINFO], arg ptr[inout, comedi_chaninfo]) +ioctl$COMEDI_LOCK(fd fd_comedi, cmd const[COMEDI_LOCK]) +ioctl$COMEDI_UNLOCK(fd fd_comedi, cmd const[COMEDI_UNLOCK]) +ioctl$COMEDI_CANCEL(fd fd_comedi, cmd const[COMEDI_CANCEL]) +ioctl$COMEDI_RANGEINFO(fd fd_comedi, cmd const[COMEDI_RANGEINFO], arg ptr[inout, comedi_rangeinfo]) +ioctl$COMEDI_CMD(fd fd_comedi, cmd const[COMEDI_CMD], arg ptr[inout, comedi_cmd]) +ioctl$COMEDI_CMDTEST(fd fd_comedi, cmd const[COMEDI_CMDTEST], arg ptr[inout, comedi_cmd]) +ioctl$COMEDI_INSNLIST(fd fd_comedi, cmd const[COMEDI_INSNLIST], arg ptr[inout, comedi_insnlist]) +ioctl$COMEDI_INSN(fd fd_comedi, cmd const[COMEDI_INSN], arg ptr[inout, comedi_insn]) +ioctl$COMEDI_BUFCONFIG(fd fd_comedi, cmd const[COMEDI_BUFCONFIG], arg ptr[inout, comedi_bufconfig]) +ioctl$COMEDI_BUFINFO(fd fd_comedi, cmd const[COMEDI_BUFINFO], arg ptr[inout, comedi_bufinfo]) +ioctl$COMEDI_POLL(fd fd_comedi, cmd const[COMEDI_POLL]) +ioctl$COMEDI_SETRSUBD(fd fd_comedi, cmd const[COMEDI_SETRSUBD]) +ioctl$COMEDI_SETWSUBD(fd fd_comedi, cmd const[COMEDI_SETWSUBD]) + +comedi_devconfig { +# TODO: For now, use driver names to try to configure devices. Maybe add all related board names to these strings as well? + board_name string[comedi_drivers, COMEDI_NAMELEN] + options array[int32, COMEDI_NDEVCONFOPTS] +} + +# List of all drivers that support "manual" configuration via comedi_config utility or COMEDI_DEVCONFIG ioctl. Only driver names for now. +comedi_drivers = "8255", "adl_pci9118", "adq12b", "aio_aio12_8", "aio_iiro_16", "amplc_dio200", "amplc_pc236", "amplc_pc263", "c6xdigio", "comedi_bond", "comedi_parport", "comedi_test", "dac02", "das08_isa", "das16m1", "das1800", "das6402", "das800", "dmm32at", "dt2801", "dt2811", "dt2814", "dt2815", "dt2817", "dt282x", "fl512", "mpc624", "multiq3", "ni_at_a2150", "ni_at_ao", "ni_atmio16d", "ni_daq_700", "ni_labpc", "pcl711", "pcl724", "pcl726", "pcl730", "pcl812", "pcl816", "pcl818", "pcm3724", "pcmad", "pcmda12", "pcmmio", "pcmuio", "rti800", "rti802", "s526" + +comedi_devinfo { + version int32 + n_subdevs int32 + driver_name array[int8, COMEDI_NAMELEN] + board_name array[int8, COMEDI_NAMELEN] + read_subd int32 + write_subd int32 + unused array[const[0, int32], 30] +} + +comedi_subdinfo { + type flags[comedi_subd_type, int32] + n_chan int32 + subd_flags flags[comedi_sdf, int32] + timer_type int32 + len_chanlist int32 + maxdata int32 + flags int32 + range_type int32 + sett_time_0 int32 + insn_bits_supp flags[comedi_insn_bits_supp, int32] + unused array[const[0, int32], 8] +} + +comedi_subd_type = COMEDI_SUBD_UNUSED, COMEDI_SUBD_AI, COMEDI_SUBD_AO, COMEDI_SUBD_DI, COMEDI_SUBD_DO, COMEDI_SUBD_DIO, COMEDI_SUBD_COUNTER, COMEDI_SUBD_TIMER, COMEDI_SUBD_MEMORY, COMEDI_SUBD_CALIB, COMEDI_SUBD_PROC, COMEDI_SUBD_SERIAL, COMEDI_SUBD_PWM +comedi_sdf = SDF_BUSY, SDF_BUSY_OWNER, SDF_LOCKED, SDF_LOCK_OWNER, SDF_MAXDATA, SDF_FLAGS, SDF_RANGETYPE, SDF_PWM_COUNTER, SDF_PWM_HBRIDGE, SDF_CMD, SDF_SOFT_CALIBRATED, SDF_CMD_WRITE, SDF_CMD_READ, SDF_READABLE, SDF_WRITABLE, SDF_WRITEABLE, SDF_INTERNAL, SDF_GROUND, SDF_COMMON, SDF_DIFF, SDF_OTHER, SDF_DITHER, SDF_DEGLITCH, SDF_MMAP, SDF_RUNNING, SDF_LSAMPL, SDF_PACKED +comedi_insn_bits_supp = COMEDI_UNKNOWN_SUPPORT, COMEDI_SUPPORTED, COMEDI_UNSUPPORTED + +# Some data used in comedi_chaninfo depends on what COMEDI_SUBDINFO ioctl obtains. Keep it simple for now. +# Use semi-arbitrary limits on list sizes as they may differ depending on the driver. +comedi_chaninfo { + subdev int32 + maxd_list ptr[out, array[int32, 0:COMEDI_CHANINFO_MAX_LIST_SIZE]] + flaglist ptr[out, int32] + rangelist ptr[out, array[int32, 0:COMEDI_CHANINFO_MAX_LIST_SIZE]] + unused array[const[0, int32], 4] +} + +comedi_rangeinfo { + range_type int32 + range_ptr ptr[out, array[comedi_krange]] +} + +comedi_krange { + min int32 + max int32 + flags flags[comedi_krange_flags, int32] +} + +comedi_krange_flags = RF_EXTERNAL, 0 + +comedi_bufconfig { + subd int32 + flags int32 + max_size int32 + size int32 + unused array[const[0, int32], 4] +} + +comedi_bufinfo { + subd int32 + bytes_read int32 + +# These are indexes, not proper pointers. + buf_write_ptr int32 + buf_read_ptr int32 + + buf_write_count int32 + buf_read_count int32 + bytes_written int32 + unused array[const[0, int32], 4] +} + +# TODO: COMEDI_INSN[LIST] ioctls reliably trigger a WARNING stemming from attempts to kmalloc too much. +# While the error is real, descriptions may be flawed as well. Should we restrict sizes here to trigger the warning less often? +comedi_insn { + insn flags[comedi_insn_type, int32] + n len[data, int32] +# Use semi-arbitrary limits on data as COMEDI expects it to be. + data ptr[inout, array[int32, COMEDI_INSN_MIN_DATA_SIZE:COMEDI_INSN_MAX_DATA_SIZE]] + subdev int32 + chanspec int32 + unused array[const[0, int32], 3] +} + +comedi_insn_type = INSN_MASK_WRITE, INSN_MASK_READ, INSN_MASK_SPECIAL, INSN_READ, INSN_WRITE, INSN_BITS, INSN_CONFIG, INSN_DEVICE_CONFIG, INSN_GTOD, INSN_WAIT, INSN_INTTRIG + +comedi_insnlist { + n_insns len[insns, int32] +# Restrict somewhat the number of COMEDI instructions otherwise same kmalloc warning slows down the fuzzing process. + insns ptr[inout, array[comedi_insn, 0:COMEDI_INSNLIST_SIZE]] +} + +comedi_cmd { + subdev int32 + flags flags[comedi_cmdf, int32] + start_src flags[comedi_trig, int32] + start_arg int32 + scan_begin_src flags[comedi_trig, int32] + scan_begin_arg int32 + convert_src flags[comedi_trig, int32] + convert_arg int32 + scan_end_src flags[comedi_trig, int32] + scan_end_arg int32 + stop_src flags[comedi_trig, int32] + stop_arg int32 + chanlist ptr[inout, array[int32]] + chanlist_len len[chanlist, int32] + data ptr[inout, array[int8]] + data_len len[data, int32] +} + +comedi_cmdf = CMDF_BOGUS, CMDF_PRIORITY, CMDF_WAKE_EOS, CMDF_WRITE, CMDF_RAWDATA, CMDF_ROUND_MASK, CMDF_ROUND_NEAREST, CMDF_ROUND_DOWN, CMDF_ROUND_UP, CMDF_ROUND_UP_NEXT +comedi_trig = TRIG_ANY, TRIG_INVALID, TRIG_NONE, TRIG_NOW, TRIG_FOLLOW, TRIG_TIMER, TRIG_COUNT, TRIG_EXT, TRIG_INT, TRIG_OTHER + +define COMEDI_CHANINFO_MAX_LIST_SIZE 65536 +define COMEDI_INSN_MIN_DATA_SIZE 15 +define COMEDI_INSN_MAX_DATA_SIZE 65537 +define COMEDI_INSNLIST_SIZE 16 diff --git a/sys/linux/dev_comedi.txt.const b/sys/linux/dev_comedi.txt.const new file mode 100644 index 000000000..bf1047455 --- /dev/null +++ b/sys/linux/dev_comedi.txt.const @@ -0,0 +1,103 @@ +# Code generated by syz-sysgen. DO NOT EDIT. +arches = 386, amd64, arm, arm64, mips64le, ppc64le, riscv64, s390x +AT_FDCWD = 18446744073709551516 +CMDF_BOGUS = 1 +CMDF_PRIORITY = 8 +CMDF_RAWDATA = 128 +CMDF_ROUND_DOWN = 65536 +CMDF_ROUND_MASK = 196608 +CMDF_ROUND_NEAREST = 0 +CMDF_ROUND_UP = 131072 +CMDF_ROUND_UP_NEXT = 196608 +CMDF_WAKE_EOS = 32 +CMDF_WRITE = 64 +COMEDI_BUFCONFIG = 2149606413, mips64le:ppc64le:1075864589 +COMEDI_BUFINFO = 3224134670 +COMEDI_CANCEL = 25607, mips64le:ppc64le:536896519 +COMEDI_CHANINFO = 2150654979, 386:arm:2149606403, mips64le:ppc64le:1076913155 +COMEDI_CHANINFO_MAX_LIST_SIZE = 65536 +COMEDI_CMD = 2152752137, 386:arm:2151703561, mips64le:ppc64le:1079010313 +COMEDI_CMDTEST = 2152752138, 386:arm:2151703562, mips64le:ppc64le:1079010314 +COMEDI_DEVCONFIG = 1083466752, mips64le:ppc64le:2157208576 +COMEDI_DEVINFO = 2159043585, mips64le:ppc64le:1085301761 +COMEDI_INSN = 2150130700, 386:arm:2149606412, mips64le:ppc64le:1076388876 +COMEDI_INSNLIST = 2148557835, 386:arm:2148033547, mips64le:ppc64le:1074816011 +COMEDI_INSNLIST_SIZE = 16 +COMEDI_INSN_MAX_DATA_SIZE = 65537 +COMEDI_INSN_MIN_DATA_SIZE = 15 +COMEDI_LOCK = 25605, mips64le:ppc64le:536896517 +COMEDI_NAMELEN = 20 +COMEDI_NDEVCONFOPTS = 32 +COMEDI_POLL = 25615, mips64le:ppc64le:536896527 +COMEDI_RANGEINFO = 2148557832, 386:arm:2148033544, mips64le:ppc64le:1074816008 +COMEDI_SETRSUBD = 25616, mips64le:ppc64le:536896528 +COMEDI_SETWSUBD = 25617, mips64le:ppc64le:536896529 +COMEDI_SUBDINFO = 2152227842, mips64le:ppc64le:1078486018 +COMEDI_SUBD_AI = 1 +COMEDI_SUBD_AO = 2 +COMEDI_SUBD_CALIB = 9 +COMEDI_SUBD_COUNTER = 6 +COMEDI_SUBD_DI = 3 +COMEDI_SUBD_DIO = 5 +COMEDI_SUBD_DO = 4 +COMEDI_SUBD_MEMORY = 8 +COMEDI_SUBD_PROC = 10 +COMEDI_SUBD_PWM = 12 +COMEDI_SUBD_SERIAL = 11 +COMEDI_SUBD_TIMER = 7 +COMEDI_SUBD_UNUSED = 0 +COMEDI_SUPPORTED = 1 +COMEDI_UNKNOWN_SUPPORT = 0 +COMEDI_UNLOCK = 25606, mips64le:ppc64le:536896518 +COMEDI_UNSUPPORTED = 2 +INSN_BITS = 201326594 +INSN_CONFIG = 201326595 +INSN_DEVICE_CONFIG = 234881027 +INSN_GTOD = 100663300 +INSN_INTTRIG = 167772166 +INSN_MASK_READ = 67108864 +INSN_MASK_SPECIAL = 33554432 +INSN_MASK_WRITE = 134217728 +INSN_READ = 67108864 +INSN_WAIT = 167772165 +INSN_WRITE = 134217729 +RF_EXTERNAL = 256 +SDF_BUSY = 1 +SDF_BUSY_OWNER = 2 +SDF_CMD = 4096 +SDF_CMD_READ = 32768 +SDF_CMD_WRITE = 16384 +SDF_COMMON = 2097152 +SDF_DEGLITCH = 33554432 +SDF_DIFF = 4194304 +SDF_DITHER = 16777216 +SDF_FLAGS = 32 +SDF_GROUND = 1048576 +SDF_INTERNAL = 262144 +SDF_LOCKED = 4 +SDF_LOCK_OWNER = 8 +SDF_LSAMPL = 268435456 +SDF_MAXDATA = 16 +SDF_MMAP = 67108864 +SDF_OTHER = 8388608 +SDF_PACKED = 536870912 +SDF_PWM_COUNTER = 128 +SDF_PWM_HBRIDGE = 256 +SDF_RANGETYPE = 64 +SDF_READABLE = 65536 +SDF_RUNNING = 134217728 +SDF_SOFT_CALIBRATED = 8192 +SDF_WRITABLE = 131072 +SDF_WRITEABLE = 131072 +TRIG_ANY = 4294967295 +TRIG_COUNT = 32 +TRIG_EXT = 64 +TRIG_FOLLOW = 4 +TRIG_INT = 128 +TRIG_INVALID = 0 +TRIG_NONE = 1 +TRIG_NOW = 2 +TRIG_OTHER = 256 +TRIG_TIMER = 16 +__NR_ioctl = 54, amd64:16, arm64:riscv64:29, mips64le:5015 +__NR_openat = 56, 386:295, amd64:257, arm:322, mips64le:5247, ppc64le:286, s390x:288 |
