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  }