1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
|