Skip to content

Commit 364746b

Browse files
committed
sys/linux: add UAC2, UAC3, and MIDI USB audio class descriptions
This patch extends the USB audio fuzzing support by adding syzlang descriptions for: - UAC2 (USB Audio Class 2.0) devices with clock management units, interface association descriptors, and extended format types. - UAC3 (USB Audio Class 3.0) devices including power domain descriptors and cluster information segments. - USB MIDI devices with jack descriptors and streaming endpoints. A new generateAudioDeviceDescriptor function patches in both auto-extracted USB IDs from the kernel driver matching rules and hardcoded quirk IDs from the USB audio driver sources (sound/usb/). This approach follows the pattern established for the HID and printer classes, allowing exercising driver quirks that cannot be automatically extracted. The config descriptor template now includes an EXTRA field to support Interface Association Descriptors required by UAC2/UAC3. This also requires adjusting the interface field index in patchUsbDeviceID.
1 parent 31d0cb6 commit 364746b

File tree

9 files changed

+1500
-449
lines changed

9 files changed

+1500
-449
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ Elektrobit Automotive GmbH
5555
Rivos Inc.
5656
Jeongjun Park
5757
International Business Machines Corporation
58+
Berk Cem Goksel

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,4 @@ International Business Machines Corporation
147147
Andrew Donnellan
148148
Alexander Egorenkov
149149
Alexey Kardashevskiy
150+
Berk Cem Goksel

sys/linux/init.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ func InitTarget(target *prog.Target) {
6464
"usb_device_descriptor": arch.generateUsbDeviceDescriptor,
6565
"usb_device_descriptor_printer": arch.generateUsbPrinterDeviceDescriptor,
6666
"usb_device_descriptor_hid": arch.generateUsbHidDeviceDescriptor,
67+
"usb_device_descriptor_uac1": arch.generateAudioDeviceDescriptor,
68+
"usb_device_descriptor_uac2": arch.generateAudioDeviceDescriptor,
69+
"usb_device_descriptor_uac3": arch.generateAudioDeviceDescriptor,
70+
"usb_device_descriptor_midi": arch.generateAudioDeviceDescriptor,
6771
}
6872

6973
target.AuxResources = map[string]bool{

sys/linux/init_vusb.go

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,154 @@ func (arch *arch) generateUsbPrinterDeviceDescriptor(g *prog.Gen, typ0 prog.Type
112112
return
113113
}
114114

115+
func (arch *arch) generateAudioDeviceDescriptor(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) (
116+
arg prog.Arg, calls []*prog.Call) {
117+
if old == nil {
118+
arg = g.GenerateSpecialArg(typ0, dir, &calls)
119+
} else {
120+
arg = prog.CloneArg(old)
121+
calls = g.MutateArg(arg)
122+
}
123+
if g.Target().ArgContainsAny(arg) {
124+
return
125+
}
126+
// Roll the dice to decide if and how we want to patch audio device IDs.
127+
switch {
128+
case g.Rand().Intn(3) == 0:
129+
// Syzlang descriptions already contain passable IDs, leave them as is.
130+
return
131+
case g.Rand().Intn(2) == 0:
132+
// Patch in quirk IDs that are hardcoded in the USB audio class drivers
133+
// (and thus are not auto-extractable) to allow exercising driver quirks.
134+
var idVendor uint16
135+
var idProduct uint16
136+
quirksIDs := [][2]uint16{
137+
// sound/usb/quirks.c
138+
{0x041e, 0x3000},
139+
{0x041e, 0x3020},
140+
{0x10f5, 0x0200},
141+
{0x0d8c, 0x0102},
142+
{0x0ccd, 0x00b1},
143+
{0x1235, 0x0010},
144+
{0x1235, 0x0018},
145+
{0x0763, 0x2012},
146+
{0x047f, 0xc010},
147+
{0x2466, 0x8010},
148+
// sound/usb/stream.c ?
149+
{0x04fa, 0x4201},
150+
// sound/usb/midi.c
151+
{0x0a67, 0x5011},
152+
{0x0a92, 0x1020},
153+
{0x1430, 0x474b},
154+
{0x15ca, 0x0101},
155+
{0x15ca, 0x1806},
156+
{0x1a86, 0x752d},
157+
{0xfc08, 0x0101},
158+
{0x0644, 0x800e},
159+
{0x0644, 0x800f},
160+
{0x0763, 0x0150},
161+
// Test if this covers midi.c | grep USB_VID_VENDOR
162+
{0x0582, 0x0582},
163+
//sound/usb/card.c
164+
{0x18d1, 0x2d04},
165+
{0x18d1, 0x2d05},
166+
//sound/usb/format.c
167+
{0x0582, 0x0016},
168+
{0x0582, 0x000c},
169+
{0x0d8c, 0x0201},
170+
{0x0d8c, 0x0102},
171+
{0x0d8c, 0x0078},
172+
{0x0ccd, 0x00b1},
173+
{0x041e, 0x4064},
174+
{0x041e, 0x4068},
175+
{0x194f, 0x010c},
176+
{0x0e41, 0x4241},
177+
{0x0e41, 0x4241},
178+
{0x0e41, 0x4242},
179+
{0x0e41, 0x4244},
180+
{0x0e41, 0x4246},
181+
{0x0e41, 0x4247},
182+
{0x0e41, 0x4248},
183+
{0x0e41, 0x4249},
184+
{0x0e41, 0x424a},
185+
{0x19f7, 0x0011},
186+
{0x0e41, 0x3000},
187+
{0x0e41, 0x3020},
188+
{0x0e41, 0x3061},
189+
{0x0a67, 0x5011},
190+
//sound/usb/mixer_quirks.c
191+
{0x041e, 0x3000},
192+
{0x041e, 0x3020},
193+
{0x041e, 0x3040},
194+
{0x041e, 0x3042},
195+
{0x041e, 0x3048},
196+
{0x041e, 0x30df},
197+
{0x041e, 0x3237},
198+
{0x041e, 0x323b},
199+
{0x041e, 0x3263},
200+
{0x0644, 0x8047},
201+
{0x0b05, 0x1739},
202+
{0x0b05, 0x1743},
203+
{0x0b05, 0x17a0},
204+
{0x0bda, 0x4014},
205+
{0x0d8c, 0x000c},
206+
{0x0d8c, 0x0014},
207+
{0x0d8c, 0x0103},
208+
{0x1235, 0x8002},
209+
{0x1235, 0x8004},
210+
{0x1235, 0x800c},
211+
{0x1235, 0x8012},
212+
{0x1235, 0x8014},
213+
{0x1235, 0x8201},
214+
{0x1235, 0x8203},
215+
{0x1235, 0x8204},
216+
{0x1235, 0x8210},
217+
{0x1235, 0x8211},
218+
{0x1235, 0x8212},
219+
{0x1235, 0x8213},
220+
{0x1235, 0x8214},
221+
{0x1235, 0x8215},
222+
{0x17cc, 0x1011},
223+
{0x17cc, 0x1021},
224+
{0x194f, 0x010c},
225+
{0x200c, 0x1018},
226+
{0x21b4, 0x0081},
227+
{0x2a39, 0x3fb0},
228+
{0x2a39, 0x3fd2},
229+
{0x2a39, 0x3fd3},
230+
{0x2a39, 0x3fd4},
231+
// yamaha
232+
{0x0499, 0x0499},
233+
{0x0582, 0x0582},
234+
}
235+
idx := g.Rand().Intn(len(quirksIDs))
236+
idVendor = quirksIDs[idx][0]
237+
idProduct = quirksIDs[idx][1]
238+
devArg := arg.(*prog.GroupArg).Inner[0]
239+
patchGroupArg(devArg, 7, "idVendor", uint64(idVendor))
240+
patchGroupArg(devArg, 8, "idProduct", uint64(idProduct))
241+
default:
242+
// Patch in IDs auto-extracted from the matching rules for the USB audio class.
243+
// Do not patch IDs that are not used in the matching rules to avoid subverting
244+
// the kernel into matching the device to a different driver.
245+
// TODO: some of these strings might be missing is dict, check
246+
ids := usbIds["snd-bcd2000"] +
247+
usbIds["snd-ua101"] +
248+
usbIds["snd-usb-6fire"] +
249+
usbIds["snd-usb-audio"] +
250+
usbIds["snd-usb-caiaq"] +
251+
usbIds["snd-usb-hiface"] +
252+
usbIds["snd-usb-us122l"] +
253+
usbIds["snd-usb-usx2y"] +
254+
usbIds["snd_usb_pod"] +
255+
usbIds["snd_usb_podhd"] +
256+
usbIds["snd_usb_toneport"] +
257+
usbIds["snd_usb_variax"]
258+
patchUsbDeviceID(g, &arg, calls, ids, false)
259+
}
260+
return
261+
}
262+
115263
func patchUsbDeviceID(g *prog.Gen, arg *prog.Arg, calls []*prog.Call, ids string, patchNonMatching bool) {
116264
id := randUsbDeviceID(g, ids, patchNonMatching)
117265

@@ -138,7 +286,7 @@ func patchUsbDeviceID(g *prog.Gen, arg *prog.Arg, calls []*prog.Call, ids string
138286
}
139287

140288
configArg := devArg.(*prog.GroupArg).Inner[14].(*prog.GroupArg).Inner[0].(*prog.GroupArg).Inner[0]
141-
interfacesArg := configArg.(*prog.GroupArg).Inner[8]
289+
interfacesArg := configArg.(*prog.GroupArg).Inner[9]
142290

143291
for i, interfaceArg := range interfacesArg.(*prog.GroupArg).Inner {
144292
interfaceArg = interfaceArg.(*prog.GroupArg).Inner[0]

sys/linux/test/vusb_midi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# requires: -repeat
2+
3+
r0 = syz_usb_connect$midi(0x0, 0x0, &AUTO, &AUTO)
4+
syz_usb_control_io$midi(r0, 0x0, 0x0)

sys/linux/test/vusb_uac2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# requires: -repeat
2+
3+
r0 = syz_usb_connect$uac2(0x0, 0x0, &AUTO, &AUTO)
4+
syz_usb_control_io$uac2(r0, 0x0, 0x0)

sys/linux/test/vusb_uac3

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# requires: -repeat
2+
3+
r0 = syz_usb_connect$uac3(0x0, 0x0, &AUTO, &AUTO)
4+
syz_usb_control_io$uac3(r0, 0x0, 0x0)

0 commit comments

Comments
 (0)