github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/sys/linux/dev_comedi.txt (about)

     1  # Copyright 2025 syzkaller project authors. All rights reserved.
     2  # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  include <uapi/asm/ioctl.h>
     5  include <uapi/linux/fcntl.h>
     6  include <uapi/linux/comedi.h>
     7  
     8  # Descriptions for fuzzing COMEDI drivers.
     9  
    10  # Currently, there is little hope to fuzz most comedi drivers as that requires special qemu setup with emulated pci capabilities,
    11  # while some usb drivers (like vmk80xx) are accessible via vusb approach.
    12  # For now, focus instead on manually configurable legacy drivers: create static devices via module option comedi.comedi_num_legacy_minors,
    13  # and attempt to configure them via COMEDI_DEVCONFIG ioctl. This leads to marginally deeper exploration of this driver stack.
    14  
    15  # TODO: Expand coverage properly by emulating required pci hardware.
    16  
    17  resource fd_comedi[fd]
    18  
    19  openat$comedi(fd const[AT_FDCWD], file ptr[in, string[comedi_devices]], flags flags[open_flags], mode const[0]) fd_comedi
    20  
    21  # Account for both configurable and dynamically allocated comedi devices. Depending on what value is passed
    22  # to config option 'comedi.comedi_num_legacy_minors=N', the first N devices will be static. No reason to set N
    23  # higher than 4.
    24  # TODO: Come up with a more elegant way to list devices to open. Maybe a modified syz_open_dev() is in order?
    25  comedi_devices = "/dev/comedi0", "/dev/comedi1", "/dev/comedi2", "/dev/comedi3", "/dev/comedi4", "/dev/comedi5"
    26  
    27  ioctl$COMEDI_DEVCONFIG(fd fd_comedi, cmd const[COMEDI_DEVCONFIG], arg ptr[in, comedi_devconfig])
    28  ioctl$COMEDI_DEVINFO(fd fd_comedi, cmd const[COMEDI_DEVINFO], arg ptr[out, comedi_devinfo])
    29  ioctl$COMEDI_SUBDINFO(fd fd_comedi, cmd const[COMEDI_SUBDINFO], arg ptr[out, comedi_subdinfo])
    30  ioctl$COMEDI_CHANINFO(fd fd_comedi, cmd const[COMEDI_CHANINFO], arg ptr[inout, comedi_chaninfo])
    31  ioctl$COMEDI_LOCK(fd fd_comedi, cmd const[COMEDI_LOCK])
    32  ioctl$COMEDI_UNLOCK(fd fd_comedi, cmd const[COMEDI_UNLOCK])
    33  ioctl$COMEDI_CANCEL(fd fd_comedi, cmd const[COMEDI_CANCEL])
    34  ioctl$COMEDI_RANGEINFO(fd fd_comedi, cmd const[COMEDI_RANGEINFO], arg ptr[inout, comedi_rangeinfo])
    35  ioctl$COMEDI_CMD(fd fd_comedi, cmd const[COMEDI_CMD], arg ptr[inout, comedi_cmd])
    36  ioctl$COMEDI_CMDTEST(fd fd_comedi, cmd const[COMEDI_CMDTEST], arg ptr[inout, comedi_cmd])
    37  ioctl$COMEDI_INSNLIST(fd fd_comedi, cmd const[COMEDI_INSNLIST], arg ptr[inout, comedi_insnlist])
    38  ioctl$COMEDI_INSN(fd fd_comedi, cmd const[COMEDI_INSN], arg ptr[inout, comedi_insn])
    39  ioctl$COMEDI_BUFCONFIG(fd fd_comedi, cmd const[COMEDI_BUFCONFIG], arg ptr[inout, comedi_bufconfig])
    40  ioctl$COMEDI_BUFINFO(fd fd_comedi, cmd const[COMEDI_BUFINFO], arg ptr[inout, comedi_bufinfo])
    41  ioctl$COMEDI_POLL(fd fd_comedi, cmd const[COMEDI_POLL])
    42  ioctl$COMEDI_SETRSUBD(fd fd_comedi, cmd const[COMEDI_SETRSUBD])
    43  ioctl$COMEDI_SETWSUBD(fd fd_comedi, cmd const[COMEDI_SETWSUBD])
    44  
    45  comedi_devconfig {
    46  # TODO: For now, use driver names to try to configure devices. Maybe add all related board names to these strings as well?
    47  	board_name	string[comedi_drivers, COMEDI_NAMELEN]
    48  	options		array[int32, COMEDI_NDEVCONFOPTS]
    49  }
    50  
    51  # List of all drivers that support "manual" configuration via comedi_config utility or COMEDI_DEVCONFIG ioctl. Only driver names for now.
    52  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"
    53  
    54  comedi_devinfo {
    55  	version		int32
    56  	n_subdevs	int32
    57  	driver_name	array[int8, COMEDI_NAMELEN]
    58  	board_name	array[int8, COMEDI_NAMELEN]
    59  	read_subd	int32
    60  	write_subd	int32
    61  	unused		array[const[0, int32], 30]
    62  }
    63  
    64  comedi_subdinfo {
    65  	type		flags[comedi_subd_type, int32]
    66  	n_chan		int32
    67  	subd_flags	flags[comedi_sdf, int32]
    68  	timer_type	int32
    69  	len_chanlist	int32
    70  	maxdata		int32
    71  	flags		int32
    72  	range_type	int32
    73  	sett_time_0	int32
    74  	insn_bits_supp	flags[comedi_insn_bits_supp, int32]
    75  	unused		array[const[0, int32], 8]
    76  }
    77  
    78  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
    79  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
    80  comedi_insn_bits_supp = COMEDI_UNKNOWN_SUPPORT, COMEDI_SUPPORTED, COMEDI_UNSUPPORTED
    81  
    82  # Some data used in comedi_chaninfo depends on what COMEDI_SUBDINFO ioctl obtains. Keep it simple for now.
    83  # Use semi-arbitrary limits on list sizes as they may differ depending on the driver.
    84  comedi_chaninfo {
    85  	subdev		int32
    86  	maxd_list	ptr[out, array[int32, 0:COMEDI_CHANINFO_MAX_LIST_SIZE]]
    87  	flaglist	ptr[out, int32]
    88  	rangelist	ptr[out, array[int32, 0:COMEDI_CHANINFO_MAX_LIST_SIZE]]
    89  	unused		array[const[0, int32], 4]
    90  }
    91  
    92  comedi_rangeinfo {
    93  	range_type	int32
    94  	range_ptr	ptr[out, array[comedi_krange]]
    95  }
    96  
    97  comedi_krange {
    98  	min	int32
    99  	max	int32
   100  	flags	flags[comedi_krange_flags, int32]
   101  }
   102  
   103  comedi_krange_flags = RF_EXTERNAL, 0
   104  
   105  comedi_bufconfig {
   106  	subd		int32
   107  	flags		int32
   108  	max_size	int32
   109  	size		int32
   110  	unused		array[const[0, int32], 4]
   111  }
   112  
   113  comedi_bufinfo {
   114  	subd		int32
   115  	bytes_read	int32
   116  
   117  # These are indexes, not proper pointers.
   118  	buf_write_ptr	int32
   119  	buf_read_ptr	int32
   120  
   121  	buf_write_count	int32
   122  	buf_read_count	int32
   123  	bytes_written	int32
   124  	unused		array[const[0, int32], 4]
   125  }
   126  
   127  # TODO: COMEDI_INSN[LIST] ioctls reliably trigger a WARNING stemming from attempts to kmalloc too much.
   128  # While the error is real, descriptions may be flawed as well. Should we restrict sizes here to trigger the warning less often?
   129  comedi_insn {
   130  	insn		flags[comedi_insn_type, int32]
   131  	n		len[data, int32]
   132  # Use semi-arbitrary limits on data as COMEDI expects it to be.
   133  	data		ptr[inout, array[int32, COMEDI_INSN_MIN_DATA_SIZE:COMEDI_INSN_MAX_DATA_SIZE]]
   134  	subdev		int32
   135  	chanspec	int32
   136  	unused		array[const[0, int32], 3]
   137  }
   138  
   139  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
   140  
   141  comedi_insnlist {
   142  	n_insns	len[insns, int32]
   143  # Restrict somewhat the number of COMEDI instructions otherwise same kmalloc warning slows down the fuzzing process.
   144  	insns	ptr[inout, array[comedi_insn, 0:COMEDI_INSNLIST_SIZE]]
   145  }
   146  
   147  comedi_cmd {
   148  	subdev		int32
   149  	flags		flags[comedi_cmdf, int32]
   150  	start_src	flags[comedi_trig, int32]
   151  	start_arg	int32
   152  	scan_begin_src	flags[comedi_trig, int32]
   153  	scan_begin_arg	int32
   154  	convert_src	flags[comedi_trig, int32]
   155  	convert_arg	int32
   156  	scan_end_src	flags[comedi_trig, int32]
   157  	scan_end_arg	int32
   158  	stop_src	flags[comedi_trig, int32]
   159  	stop_arg	int32
   160  	chanlist	ptr[inout, array[int32]]
   161  	chanlist_len	len[chanlist, int32]
   162  	data		ptr[inout, array[int8]]
   163  	data_len	len[data, int32]
   164  }
   165  
   166  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
   167  comedi_trig = TRIG_ANY, TRIG_INVALID, TRIG_NONE, TRIG_NOW, TRIG_FOLLOW, TRIG_TIMER, TRIG_COUNT, TRIG_EXT, TRIG_INT, TRIG_OTHER
   168  
   169  define COMEDI_CHANINFO_MAX_LIST_SIZE	65536
   170  define COMEDI_INSN_MIN_DATA_SIZE	15
   171  define COMEDI_INSN_MAX_DATA_SIZE	65537
   172  define COMEDI_INSNLIST_SIZE	16