github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/sys/linux/init_vusb.go (about) 1 // Copyright 2019 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 package linux 5 6 import ( 7 "encoding/binary" 8 "fmt" 9 "strings" 10 11 "github.com/google/syzkaller/prog" 12 ) 13 14 const ( 15 USB_DEVICE_ID_MATCH_VENDOR = 1 << iota 16 USB_DEVICE_ID_MATCH_PRODUCT 17 USB_DEVICE_ID_MATCH_DEV_LO 18 USB_DEVICE_ID_MATCH_DEV_HI 19 USB_DEVICE_ID_MATCH_DEV_CLASS 20 USB_DEVICE_ID_MATCH_DEV_SUBCLASS 21 USB_DEVICE_ID_MATCH_DEV_PROTOCOL 22 USB_DEVICE_ID_MATCH_INT_CLASS 23 USB_DEVICE_ID_MATCH_INT_SUBCLASS 24 USB_DEVICE_ID_MATCH_INT_PROTOCOL 25 USB_DEVICE_ID_MATCH_INT_NUMBER 26 27 BytesPerUsbID = 17 28 BytesPerHidID = 12 29 ) 30 31 type UsbDeviceID struct { 32 MatchFlags uint16 33 IDVendor uint16 34 IDProduct uint16 35 BcdDeviceLo uint16 36 BcdDeviceHi uint16 37 BDeviceClass uint8 38 BDeviceSubClass uint8 39 BDeviceProtocol uint8 40 BInterfaceClass uint8 41 BInterfaceSubClass uint8 42 BInterfaceProtocol uint8 43 BInterfaceNumber uint8 44 } 45 46 type HidDeviceID struct { 47 Bus uint16 48 Group uint16 49 Vendor uint32 50 Product uint32 51 } 52 53 func (arch *arch) generateUsbDeviceDescriptor(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) ( 54 arg prog.Arg, calls []*prog.Call) { 55 if old == nil { 56 arg = g.GenerateSpecialArg(typ0, dir, &calls) 57 } else { 58 arg = prog.CloneArg(old) 59 calls = g.MutateArg(arg) 60 } 61 if g.Target().ArgContainsAny(arg) { 62 return 63 } 64 65 id := randUsbDeviceID(g) 66 bcdDevice := id.BcdDeviceLo + uint16(g.Rand().Intn(int(id.BcdDeviceHi-id.BcdDeviceLo)+1)) 67 68 devArg := arg.(*prog.GroupArg).Inner[0] 69 patchGroupArg(devArg, 7, "idVendor", uint64(id.IDVendor)) 70 patchGroupArg(devArg, 8, "idProduct", uint64(id.IDProduct)) 71 patchGroupArg(devArg, 9, "bcdDevice", uint64(bcdDevice)) 72 patchGroupArg(devArg, 3, "bDeviceClass", uint64(id.BDeviceClass)) 73 patchGroupArg(devArg, 4, "bDeviceSubClass", uint64(id.BDeviceSubClass)) 74 patchGroupArg(devArg, 5, "bDeviceProtocol", uint64(id.BDeviceProtocol)) 75 76 configArg := devArg.(*prog.GroupArg).Inner[14].(*prog.GroupArg).Inner[0].(*prog.GroupArg).Inner[0] 77 interfacesArg := configArg.(*prog.GroupArg).Inner[8] 78 79 for i, interfaceArg := range interfacesArg.(*prog.GroupArg).Inner { 80 interfaceArg = interfaceArg.(*prog.GroupArg).Inner[0] 81 if i > 0 { 82 // Generate new IDs for every interface after the first one. 83 id = randUsbDeviceID(g) 84 } 85 patchGroupArg(interfaceArg, 5, "bInterfaceClass", uint64(id.BInterfaceClass)) 86 patchGroupArg(interfaceArg, 6, "bInterfaceSubClass", uint64(id.BInterfaceSubClass)) 87 patchGroupArg(interfaceArg, 7, "bInterfaceProtocol", uint64(id.BInterfaceProtocol)) 88 patchGroupArg(interfaceArg, 2, "bInterfaceNumber", uint64(id.BInterfaceNumber)) 89 } 90 91 return 92 } 93 94 func randUsbDeviceID(g *prog.Gen) UsbDeviceID { 95 totalIds := len(usbIds) / BytesPerUsbID 96 idNum := g.Rand().Intn(totalIds) 97 base := usbIds[idNum*BytesPerUsbID : (idNum+1)*BytesPerUsbID] 98 99 p := strings.NewReader(base) 100 var id UsbDeviceID 101 if binary.Read(p, binary.LittleEndian, &id) != nil { 102 panic("not enough data to read") 103 } 104 105 if (id.MatchFlags & USB_DEVICE_ID_MATCH_VENDOR) == 0 { 106 id.IDVendor = uint16(g.Rand().Intn(0xffff + 1)) 107 } 108 if (id.MatchFlags & USB_DEVICE_ID_MATCH_PRODUCT) == 0 { 109 id.IDProduct = uint16(g.Rand().Intn(0xffff + 1)) 110 } 111 if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_LO) == 0 { 112 id.BcdDeviceLo = 0x0 113 } 114 if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_HI) == 0 { 115 id.BcdDeviceHi = 0xffff 116 } 117 if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_CLASS) == 0 { 118 id.BDeviceClass = uint8(g.Rand().Intn(0xff + 1)) 119 } 120 if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) == 0 { 121 id.BDeviceSubClass = uint8(g.Rand().Intn(0xff + 1)) 122 } 123 if (id.MatchFlags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) == 0 { 124 id.BDeviceProtocol = uint8(g.Rand().Intn(0xff + 1)) 125 } 126 if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_CLASS) == 0 { 127 id.BInterfaceClass = uint8(g.Rand().Intn(0xff + 1)) 128 } 129 if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) == 0 { 130 id.BInterfaceSubClass = uint8(g.Rand().Intn(0xff + 1)) 131 } 132 if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) == 0 { 133 id.BInterfaceProtocol = uint8(g.Rand().Intn(0xff + 1)) 134 } 135 if (id.MatchFlags & USB_DEVICE_ID_MATCH_INT_NUMBER) == 0 { 136 id.BInterfaceNumber = uint8(g.Rand().Intn(0xff + 1)) 137 } 138 139 return id 140 } 141 142 func (arch *arch) generateUsbHidDeviceDescriptor(g *prog.Gen, typ0 prog.Type, dir prog.Dir, old prog.Arg) ( 143 arg prog.Arg, calls []*prog.Call) { 144 if old == nil { 145 arg = g.GenerateSpecialArg(typ0, dir, &calls) 146 } else { 147 arg = prog.CloneArg(old) 148 calls = g.MutateArg(arg) 149 } 150 if g.Target().ArgContainsAny(arg) { 151 return 152 } 153 154 totalIds := len(hidIds) / BytesPerHidID 155 idNum := g.Rand().Intn(totalIds) 156 base := hidIds[idNum*BytesPerHidID : (idNum+1)*BytesPerHidID] 157 158 p := strings.NewReader(base) 159 var id HidDeviceID 160 if binary.Read(p, binary.LittleEndian, &id) != nil { 161 panic("not enough data to read") 162 } 163 164 devArg := arg.(*prog.GroupArg).Inner[0] 165 patchGroupArg(devArg, 7, "idVendor", uint64(id.Vendor)) 166 patchGroupArg(devArg, 8, "idProduct", uint64(id.Product)) 167 168 return 169 } 170 171 func patchGroupArg(arg prog.Arg, index int, field string, value uint64) { 172 a := arg.(*prog.GroupArg) 173 typ := a.Type().(*prog.StructType) 174 if field != typ.Fields[index].Name { 175 panic(fmt.Sprintf("bad field, expected %v, found %v", field, typ.Fields[index].Name)) 176 } 177 a.Inner[index].(*prog.ConstArg).Val = value 178 }