etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

fuzz_usbfs_shim.c (3966B)

      1 /*
      2  * Extraction of parse_config_descriptors() + seek_to_next_config() from
      3  * linux_usbfs.c. Verbatim logic, local type definitions, fuzz-visible entry point.
      4  */
      5 
      6 #include "fuzz-include/libusb_fuzz.h"
      7 #include "libusb-src/libusb/libusbi.h"
      8 
      9 struct config_descriptor {
     10     struct usbi_configuration_descriptor *desc;
     11     size_t actual_len;
     12 };
     13 
     14 struct linux_device_priv {
     15     char   *sysfs_dir;
     16     void   *descriptors;
     17     size_t  descriptors_len;
     18     struct config_descriptor *config_descriptors;
     19     int     active_config;
     20 };
     21 
     22 static int seek_to_next_config(struct libusb_context *ctx,
     23     uint8_t *buffer, size_t len)
     24 {
     25     struct usbi_descriptor_header *header;
     26     int offset = LIBUSB_DT_CONFIG_SIZE;
     27 
     28     buffer += LIBUSB_DT_CONFIG_SIZE;
     29     len    -= LIBUSB_DT_CONFIG_SIZE;
     30 
     31     while (len > 0) {
     32         if (len < 2) {
     33             usbi_err(ctx, "remaining descriptor length too small %zu/2", len);
     34             return LIBUSB_ERROR_IO;
     35         }
     36         header = (struct usbi_descriptor_header *)buffer;
     37         if (header->bDescriptorType == LIBUSB_DT_CONFIG)
     38             return offset;
     39         if (header->bLength < 2) {
     40             usbi_err(ctx, "invalid descriptor bLength %hhu", header->bLength);
     41             return LIBUSB_ERROR_IO;
     42         }
     43         if (len < header->bLength) {
     44             usbi_err(ctx, "bLength overflow by %zu bytes",
     45                 (size_t)header->bLength - len);
     46             return LIBUSB_ERROR_IO;
     47         }
     48         offset += header->bLength;
     49         buffer += header->bLength;
     50         len    -= header->bLength;
     51     }
     52 
     53     usbi_err(ctx, "config descriptor not found");
     54     return LIBUSB_ERROR_IO;
     55 }
     56 
     57 int fuzz_parse_config_descriptors(struct libusb_device *dev)
     58 {
     59     struct libusb_context *ctx = DEVICE_CTX(dev);
     60     struct linux_device_priv *priv = usbi_get_device_priv(dev);
     61     struct usbi_device_descriptor *device_desc;
     62     uint8_t idx, num_configs;
     63     uint8_t *buffer;
     64     size_t remaining;
     65 
     66     device_desc = priv->descriptors;
     67     num_configs = device_desc->bNumConfigurations;
     68     if (num_configs == 0)
     69         return 0;
     70 
     71     priv->config_descriptors = malloc(
     72         num_configs * sizeof(priv->config_descriptors[0]));
     73     if (!priv->config_descriptors)
     74         return LIBUSB_ERROR_NO_MEM;
     75 
     76     buffer    = (uint8_t *)priv->descriptors + LIBUSB_DT_DEVICE_SIZE;
     77     remaining = priv->descriptors_len - LIBUSB_DT_DEVICE_SIZE;
     78 
     79     for (idx = 0; idx < num_configs; idx++) {
     80         struct usbi_configuration_descriptor *config_desc;
     81         uint16_t config_len;
     82 
     83         if (remaining < LIBUSB_DT_CONFIG_SIZE) {
     84             usbi_err(ctx, "short descriptor read %zu/%d",
     85                 remaining, LIBUSB_DT_CONFIG_SIZE);
     86             return LIBUSB_ERROR_IO;
     87         }
     88 
     89         config_desc = (struct usbi_configuration_descriptor *)buffer;
     90         if (config_desc->bDescriptorType != LIBUSB_DT_CONFIG) {
     91             usbi_err(ctx, "not a config descriptor (type 0x%02x)",
     92                 config_desc->bDescriptorType);
     93             return LIBUSB_ERROR_IO;
     94         } else if (config_desc->bLength < LIBUSB_DT_CONFIG_SIZE) {
     95             usbi_err(ctx, "invalid descriptor bLength %u", config_desc->bLength);
     96             return LIBUSB_ERROR_IO;
     97         }
     98 
     99         config_len = libusb_le16_to_cpu(config_desc->wTotalLength);
    100         if (config_len < LIBUSB_DT_CONFIG_SIZE) {
    101             usbi_err(ctx, "invalid wTotalLength %u", config_len);
    102             return LIBUSB_ERROR_IO;
    103         }
    104 
    105         /* sysfs_dir == NULL → usbfs path: wTotalLength used directly */
    106         if (!priv->sysfs_dir) {
    107             if (config_len > remaining) {
    108                 usbi_warn(ctx, "short descriptor read %zu/%u", remaining, config_len);
    109                 config_len = (uint16_t)remaining;
    110             }
    111         }
    112 
    113         priv->config_descriptors[idx].desc       = config_desc;
    114         priv->config_descriptors[idx].actual_len = config_len;
    115         buffer    += config_len;
    116         remaining -= config_len;
    117     }
    118 
    119     return LIBUSB_SUCCESS;
    120 }