linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: rtm@csail.mit.edu
To: linux-usb@vger.kernel.org
Subject: USB hub code can dereference NULL hub and hub->ports
Date: Mon, 20 Jan 2025 12:27:19 -0500	[thread overview]
Message-ID: <95564.1737394039@localhost> (raw)

[-- Attachment #1: Type: text/plain, Size: 4176 bytes --]

The attached program, which acts via usbip as a USB device or hub,
causes my linux machines to dereference some NULL pointers in
drivers/usb/core/hub.c. These are places where udev->maxchild > 0, but
either usb_hub_to_struct_hub(udev) returns NULL, or the returned hub
has hub->ports == NULL.

This is one such place:

static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
        struct usb_hub *hub = usb_hub_to_struct_hub(udev);
        int i;

        for (i = 0; i < udev->maxchild; ++i) {
                if (hub->ports[i]->child)

And this:

static void hub_disconnect_children(struct usb_device *udev)
{
        struct usb_hub *hub = usb_hub_to_struct_hub(udev);
        int i;

        /* Free up all the children before we remove this device */
        for (i = 0; i < udev->maxchild; i++) {
                if (hub->ports[i]->child)

This can see NULL hub->ports:

void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
                struct usb_hub_descriptor *desc)
{
        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
        enum usb_port_connect_type connect_type;
        int i;

        if (!hub)
                return;

        if (!hub_is_superspeed(hdev)) {
                for (i = 1; i <= hdev->maxchild; i++) {
                        struct usb_port *port_dev = hub->ports[i - 1];

This can see a NULL hub:

static int hub_set_address(struct usb_device *udev, int devnum)
{
        int retval;
        unsigned int timeout_ms = USB_CTRL_SET_TIMEOUT;
        struct usb_hcd *hcd = bus_to_hcd(udev->bus);
        struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);

        if (hub->hdev->quirks & USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT)

I've attached a demo that runs into some of these NULL dereferences.
It depends on being able to run usbip (and modeprobe vhci-hcd).

# uname -a
Linux xxx 6.13.0-rc3-00017-gf44d154d6e3d #14 SMP Mon Jan 20 04:52:59 EST 2025 x86_64 x86_64 x86_64 GNU/Linux
# cc usbhub11b.c
# ./a.out
...
hub 1-1:1.16: bad descriptor, ignoring hub
hub 1-1:1.16: probe with driver hub failed with error -5
BUG: kernel NULL pointer dereference, address: 0000000000000250
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: Oops: 0000 [#1] SMP DEBUG_PAGEALLOC PTI
CPU: 8 UID: 0 PID: 302 Comm: kworker/8:1 Not tainted 6.13.0-rc3-00017-gf44d154d6
e3d #14
Hardware name: FreeBSD BHYVE/BHYVE, BIOS 14.0 10/17/2021
Workqueue: usb_hub_wq hub_event
RIP: 0010:recursively_mark_NOTATTACHED+0x37/0x90
Code: 48 85 ff 74 71 4c 8b a7 18 04 00 00 4d 85 e4 74 13 85 c0 74 3a 49 8b 94 24
 98 00 00 00 4c 8b a2 c8 00 00 00 85 c0 7e 27 31 db <49> 8b 84 24 50 02 00 00 48
 8b 04 d8 48 8b 38 48 85 ff 74 05 e8 b0
RSP: 0018:ffffc9000096bd28 EFLAGS: 00010046
RAX: 0000000000000001 RBX: 0000000000000000 RCX: ffff888106224c00
RDX: ffff8881037bc000 RSI: 0000000000000007 RDI: ffff88810a502000
RBP: ffff88810a502000 R08: 000000000000005a R09: 0000000000000000
R10: ffff88810a502000 R11: ffff88810a502000 R12: 0000000000000000
R13: ffff88810a502000 R14: ffff8881062241f0 R15: 0000000000000001
FS:  0000000000000000(0000) GS:ffff88842dc00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000250 CR3: 0000000003636001 CR4: 00000000003706f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 <TASK>
 ? __die+0x1e/0x60
 ? page_fault_oops+0x157/0x450
 ? set_track_prepare+0x3b/0x60
 ? usb_control_msg+0xfd/0x150
 ? check_bytes_and_report.isra.0+0x48/0x120
 ? exc_page_fault+0x66/0x140
 ? asm_exc_page_fault+0x26/0x30
 ? recursively_mark_NOTATTACHED+0x37/0x90
 ? usb_control_msg+0xfd/0x150
 usb_disconnect+0x37/0x2c0
 hub_event+0xc8f/0x1870
 usb_disconnect+0x37/0x2c0
 hub_event+0xc8f/0x1870
 ? trace_event_raw_event_sched_switch+0x51/0x150
 process_one_work+0x13f/0x330
 worker_thread+0x25a/0x370
 ? _raw_spin_unlock_irqrestore+0xd/0x20
 ? __pfx_worker_thread+0x10/0x10
 kthread+0xdc/0x110
 ? __pfx_kthread+0x10/0x10
 ret_from_fork+0x2f/0x50
 ? __pfx_kthread+0x10/0x10
 ret_from_fork_asm+0x1a/0x30
 </TASK>

Robert Morris
rtm@mit.edu



[-- Attachment #2: usbhub11b.c --]
[-- Type: application/octet-stream, Size: 18361 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <assert.h>

int symcmd = 5;
int symcmd2 = -1;
int sym_all_scsi = 0;
int sym_scsi_cmd = -1;

unsigned long aa[] = {
0x1000000000ull,
0x10000000ull,
0x25000000ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
0x0ull,
};
int aai;

static inline unsigned long real_symx() {
  return aa[aai++];
}

static int started = 0;
static unsigned long symx() {
#define NSYM 64
  static unsigned long sa[NSYM];
  static int sai = 0;
  if(started == 0){
    started = 1;
    usleep(200000);
    for(int i = 0; i < NSYM; i++){
      sa[i] = real_symx();
    }
  }
  if(sai >= NSYM){
    printf("!!! ran out of SYM\n");
    return 0;
  }
  return sa[sai++];
}

struct op_common {
  unsigned short version;
  unsigned short code;
  unsigned int status;
};

struct usbip_usb_device {
	char path[256];
	char busid[32];

	uint32_t busnum;
	uint32_t devnum;
	uint32_t speed;

	uint16_t idVendor;
	uint16_t idProduct;
	uint16_t bcdDevice;

	uint8_t bDeviceClass;
	uint8_t bDeviceSubClass;
	uint8_t bDeviceProtocol;
	uint8_t bConfigurationValue;
	uint8_t bNumConfigurations;
	uint8_t bNumInterfaces;
} __attribute__((packed));

struct usbip_header_basic {
  unsigned int command;
  unsigned int seqnum;
  unsigned int devid;
  unsigned int direction;
  unsigned int ep;
};

struct usbip_header_cmd_submit {
  unsigned int transfer_flags;
  int transfer_buffer_length;
  int start_frame;
  int number_of_packets;
  int interval;
  unsigned char setup[8];
};

struct usbip_header_ret_submit {
  int status;
  int actual_length;
  int start_frame;
  int number_of_packets;
  int error_count;
};

int
readable(int fd)
{
  fd_set readfds;
  FD_ZERO(&readfds);
  FD_SET(fd, &readfds);
  struct timeval tv;
  tv.tv_sec = 4;
  tv.tv_usec = 0;
  int ss = select(fd + 1, &readfds, (fd_set*)0, (fd_set*)0, &tv);
  return FD_ISSET(fd, &readfds);
}

int
readn(int fd, void *xbuf, int n)
{
  char *buf = xbuf;
  int got = 0;
  while(got < n){
    if(readable(fd) == 0){
      printf("usbip0: timeout\n");
      return -1;
    }
    int cc = read(fd, buf+got, n-got);
    if(cc <= 0){
      perror("usbip0: read");
      return -1;
    }
    got += cc;
  }
  return got;
}

void
mkif(char **xp, int num, int alt, int eps, int cl, int subcl, int proto, int iff)
{
  char *p = *xp;

  // usb_interface_descriptor
  *p++ = 9; // bLength
  *p++ = 4; // bDescriptorType USB_DT_INTERFACE
  *p++ = num; // bInterfaceNumber
  *p++ = alt; // bAlternateSetting
  *p++ = eps; // bNumEndpoints
  *p++ = cl; // bInterfaceClass
  *p++ = subcl; // bInterfaceSubClass
  *p++ = proto; // bInterfaceProtocol
  *p++ = iff; // iInterface

  *xp = p;
}

void
mkad(char **xp, int type, int subtype)
{
  char *p = *xp;

  // Additional Descriptor

  *p++ = 0; // bLength (filled in later)
  *p++ = type; // bDescriptorType
  *p++ = subtype; // bDescriptorSubtype
  
  if(type == 36 && subtype == 1){
    // AS_GENERAL
    *p++ = 1; // bTerminalLink
    *p++ = 1; // bDelay
    *p++ = 1; // wFormatTag PCM
    p++;
  } else if(type == 36 && subtype == 2){
    // FORMAT_TYPE
    *p++ = 1; // bFormatType
    *p++ = 2; // bNrChannels
    *p++ = 3; // bSubframeSize
    *p++ = 24; // bBitResolution
    *p++ = 2; // bSamFreqType 
    *p++ = 2; // bSamFreqType 
    p += 5;
  } else {
    *p++ = 0; // bcdADC
    *p++ = 1;
    *(short*)p = 0x5f; // wTotalLength
    p += 2;
    *p++ = 2; // bInCollection
    *p++ = 1; // baInterfaceNr(0)
    *p++ = 2; // baInterfaceNr(1)
  }

  *(*xp) = p - (*xp); // bLength

  *xp = p;
}

void
mkadx(char **xp, int type, int subtype, int len, int a[])
{
  char *p = *xp;

  // Additional Descriptor

  *p++ = 0; // bLength (filled in later)
  *p++ = type; // bDescriptorType
  *p++ = subtype; // bDescriptorSubtype

  for(int i = 0; i < len - 3; i++)
    *p++ = a[i];

  *(*xp) = p - (*xp); // bLength
  *xp = p;
}

void
mkep(char **xp, int epa, int attr, int maxp)
{
  char *p = *xp;

  // usb_endpoint_descriptor
  *p++ = 9;
  *p++ = 5; // bDescriptorType USB_DT_ENDPOINT
  *p++ = epa; // bEndpointAddress
  *p++ = attr; // bmAttributes
  *(short*)p = maxp; // wMaxPacketSize
  p += 2;
  *p++ = 7; // bInterval
  p += 2; // ???

  *xp = p;
}

int
main(int argc, char *argv[])
{
  struct rlimit r;
  r.rlim_cur = r.rlim_max = 0;
  setrlimit(RLIMIT_CORE, &r);

  int port = 3240;
  int s, yes = 1;
  struct sockaddr_in sin;

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(port);

  s = socket(AF_INET, SOCK_STREAM, 0);
  if(s < 0){
    perror("socket");
    exit(1);
  }

  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));

  if(bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0){
    perror("fastfingerd: bind");
    exit(1);
  }

  if(listen(s, 3000) < 0){
    perror("fastfingerd: listen");
    exit(1);
  }

  system("modprobe vhci-hcd");

  // system("usbip/src/usbip attach -r 127.0.0.1 -b 1-1 &");
  system("usbip attach -r 127.0.0.1 -b 1-1 &");
  sleep(2);
  sync();
  sleep(1);

  int s1;
  unsigned sinlen = sizeof(sin);
  s1 = accept(s, (struct sockaddr *) &sin, &sinlen);
  if(s1 < 0){
    perror("accept");
    exit(1);
  }
  close(s);
  
  struct op_common op;
  
  // OP_REQ_IMPORT
  readn(s1, &op, sizeof(op));
  //printf("version 0x%x code 0x%x status 0x%x\n", 
  //       op.version, op.code, op.status);
  
  char busid[32];
  readn(s1, busid, sizeof(busid));
  
  op.code = htons(0x03); // OP_REP_IMPORT
  op.status = htonl(0); // ST_OK
  
  write(s1, &op, sizeof(op));
  
  struct usbip_usb_device uud;
  memset(&uud, 0, sizeof(uud));
  strcpy(uud.busid, busid);
  //uud.speed = htonl(2); // USB_SPEED_FULL
  uud.speed = htonl(3); // USB_SPEED_HIGH
  //uud.speed = htonl(5); // USB_SPEED_SUPER
  
  write(s1, &uud, sizeof(uud));
  
  // now talking to the kernel

  int cmdno = 0;
  int lastTag = 0; // usb_stor_BulkTransport line 1255
  unsigned char CDB[16]; // SCSI command
  memset(CDB, 0, sizeof(CDB));

  while(1){
    struct usbip_header_basic ibh;
    //sync(); // don't sync() -- deadlock.
    if(readn(s1, &ibh, sizeof(ibh)) < 0)
      break;

#if 1
    printf("%d: command 0x%x seqnum %d devid 0x%x direction 0x%x ep 0x%x\n",
           cmdno,
           ntohl(ibh.command),
           ntohl(ibh.seqnum),
           ntohl(ibh.devid),
           ntohl(ibh.direction),
           ntohl(ibh.ep));
#endif
  
    if(ntohl(ibh.command) == 1){
      // USBIP_CMD_SUBMIT
      struct usbip_header_cmd_submit cs;
      memset(&cs, 0, sizeof(cs));
      if(readn(s1, &cs, sizeof(cs)) < 0)
        break;
#if 1
      printf("  flags 0x%x buflen %d np %d, ",
             ntohl(cs.transfer_flags),
             ntohl(cs.transfer_buffer_length),
             ntohl(cs.number_of_packets));
      for(int i = 0; i < 8; i++)
        printf("%02x ", cs.setup[i] & 0xff);
      printf("\n");
#endif
      
      int translen = ntohl(cs.transfer_buffer_length);
      
      if(ibh.direction == 0){
        char ibuf[4096];
        assert(translen <= sizeof(ibuf));
        if(readn(s1, ibuf, translen) < 0)
          break;
        if(translen >= 16 && memcmp(ibuf, "USBC", 4) == 0){
          // struct bulk_cb_wrap
          lastTag = ibuf[4];
          printf("  USBC tag=%d dtl=%d fl=0x%02x lun=%d len=%d\n",
                 *(int*)(ibuf+4),
                 *(int*)(ibuf+8),
                 ibuf[12] & 0xff,
                 ibuf[13] & 0xff,
                 ibuf[14] & 0xff);
          printf("  ");
          for(int i = 0; i < 16; i++)
            printf("%02x ", ibuf[15+i] & 0xff);
          printf("\n");
          memcpy(CDB, ibuf+15, sizeof(CDB));
        } else if(translen > 0){
          for(int i = 0; i < translen && i < 16; i++)
            printf("%02x ", ibuf[i] & 0xff);
          printf("\n");
        }
      }
      
      struct usbip_header_basic obh;
      memset(&obh, 0, sizeof(obh));
      obh.command = htonl(3); // USBIP_RET_SUBMIT
      obh.seqnum = ibh.seqnum;
      obh.devid = ibh.devid;
      obh.direction = htonl(!ntohl(ibh.direction));
      obh.ep = ibh.ep;
      write(s1, &obh, sizeof(obh));
      
      char rsbuf[sizeof(cs)];
      memset(rsbuf, 0, sizeof(rsbuf));
      struct usbip_header_ret_submit *rs = (void*)rsbuf;
      if(ibh.direction){
        rs->actual_length = htonl(translen);
      } else {
        rs->actual_length = htonl(31);
      }
      write(s1, rs, sizeof(rsbuf));
      
      if(ibh.direction){
        char buf64[4096];
        if(translen > sizeof(buf64)){
          printf("huge translen\n");
          break;
        }
        memset(buf64, 0, sizeof(buf64));
        if(cs.setup[1] == 0x06){
          // USB_REQ_GET_DESCRIPTOR
          if(cs.setup[0] == 0x80 && cs.setup[3] == 1){
            // USB_DT_DEVICE
            // struct usb_device_descriptor
            buf64[0] = 18; // bLength
            buf64[1] = 1; // bDescriptorType = USB_DT_DEVICE
            buf64[2] = 0x10; // bcdUSB
            buf64[3] = 0x02; // bcdUSB
            buf64[4] = 9; // bDeviceClass
            buf64[5] = 0; // bDeviceSubClass
            buf64[6] = 2; // bDeviceProtocol
            buf64[7] = 64; // bMaxPacketSize0
            *(short*)(buf64+8) = 0x2109; // idVendor VIA Labs
            *(short*)(buf64+10) = 0x2822; // idProduct Hub
            //*(short*)(buf64+8) = 0x1a40; // idVendor Terminus Technology
            //*(short*)(buf64+10) = 0x0101; // idProduct Hub
            buf64[12] = 0xa3; // bcdDevice
            buf64[13] = 1; // bcdDevice
            buf64[14] = 1; // iManufacturer
            buf64[15] = 2; // iProduct
            buf64[16] = 0; // iSerial
            buf64[17] = 1; // bNumConfigurations
          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 2){
            // USB_DT_CONFIG
            // struct usb_config_descriptor
            char *p = buf64;
            *p++ = 9; // bLength
            *p++ = 2; // USB_DT_CONFIG
            short *lenp = (short*) p;
            *(short*)p = 9 + 4*9 + 15*10 + 2*7; // wTotalLength
            p += 2;
            *p++ = 1; // bNumInterfaces
            *p++ = 1; // bConfigurationValue
            *p++ = 0; // iConfiguration
            *p++ = 0xe0; // bmAttributes
            *p++ = 1; // bMaxPower

            // interface 0
            mkif(&p, 0, 0, 1, 9, 0, 1, 0);
            mkep(&p, 0x81, 3, 1);

            // interface 0 alt 1
            mkif(&p, 0, 1, 1, 9, 0, 2, 0);
            mkep(&p, 0x81, 3, 1);

            // Binary Object Store Descriptor
            *p++ = 5; // bLength
            *p++ = 15; // bDescriptorType
            *(short*)p = 0x49; // wTotalLength
            p += 2;
            *p++ = 3; // bNumDeviceCaps

            // USB 2.0 Extension Device Capability
            *p++ = 7;
            *p++ = 16;
            *p++ = 2; // bDevCapabilityType
            *(int*)p = 6; // bmAttributes
            p += 4;

            // SuperSpeed USB Device Capability
            *p++ = 10;
            *p++ = 16;
            *p++ = 3; // bDevCapabilityType
            *p++ = 0; // bmAttributes
            *(short*)p = 0x000e; // wSpeedsSupported
            p += 2;
            *p++ = 1; // bFunctionalitySupport
            *p++ = 4;
            *p++ = 231;
            *p++ = 0; // ???
            
            // Container ID Device Capability
            *p++ = 20;
            *p++ = 16;
            *p++ = 4;
            *p++ = 0;
            p += 16;

            // SuperSpeedPlus USB Device Capability
            *p++ = 28;
            *p++ = 16;
            *p++ = 10;
            *(int*)p = 0x23;
            p += 4;
            *(short*)p = 0x1100;
            p += 2;
            *(int*)p = 0x50030;
            p += 4;
            *(int*)p = 0x500b0;
            p += 4;
            *(int*)p = 0xa4031;
            p += 4;
            *(int*)p = 0xa40b1;
            p += 4;
            p += 3; // ???

            // Hub Descriptor
            *p++ = 9; // bLength
            *p++ = 41; // bDescriptorType
            *p++ = 4; // nNbrPorts
            *(short*)p = 0xe9; // wHubCharacteristic
            p += 2;
            *p++ = 50; // bPwrOn2PwrGood
            *p++ = 1; // bHubContrCurrent
            *p++ = 0; // DeviceRemovable
            *p++ = 0xff; // PortPwrCtrlMask

            // Device Qualifier
            *p++ = 10; // bLength
            *p++ = 6; // bDescriptorType
            *p++ = 0; // bcdUSB 
            *p++ = 2;
            *p++ = 9; // bDeviceClass
            *p++ = 0; // bDeviceSubClass
            *p++ = 0; // bDeviceProtocol
            *p++ = 64; // bMaxPacketSize0
            *p++ = 1; // bNumConfigurations
            *p++ = 1; // ???

            assert(p - buf64 <= sizeof(buf64));
            *lenp = p - buf64;
          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 0x0f){
            // USB_DT_BOS
            // struct usb_bos_descriptor
            char *p = buf64;
            *p++ = 5; // bLength
            *p++ = 15;
            *(short*)p = 0x002a; // wTotalLength
            p += 2;
            *p++ = 3; // bNumDeviceCaps
            // usb_ext_cap_descriptor
            *p++ = 7; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 2; // bDevCapabilityType
            *(int*)p = 0x0000f41e; // bmAttributes
            p += 4;
            // usb_ss_cap_descriptor
            *p++ = 10; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 3; // bDevCapabilityType
            *p++ = 0; // bmAttributes
            *(short*)p = 0xe; // wSpeedsSupported
            p += 2;
            *p++ = 1; // bFunctionalitySupport
            *p++ = 10; // bU1devExitLat
            *(short*)p = 2047; // bU2DevExitLat
            p += 2;
            // usb_ssp_cap_descriptor
            *p++ = 20; // bLength
            *p++ = 16; // bDescriptorType
            *p++ = 10; // bDevCapabilityType
            *p++ = 0; // bReserved
            *(int*)p = 0; // bmAttributes
            p += 4;
            *(short*)p = 1; // bFunctionalitySupport
            p += 2;
            p += 2; // wReserved
            *(int*)p = 0x000a4030;
            p += 4;
            *(int*)p = 0x000a40b0;
            p += 4;
          } else if(cs.setup[0] == 0x80 && cs.setup[3] == 3){
            // USB_DT_STRING
            char *p = buf64;
            *p++ = 6; // length
            *p++ = 3; // descriptor type
            *p++ = 'a';
            *p++ = 'b';
            *p++ = 'c';
            *p++ = 'd';
          } else if(cs.setup[0] == 0xa0){
            // usb_hub_descriptor
            memset(buf64, 0xff, 32);
            buf64[0] = 15; // bDescLength
            buf64[1] = 42; // bDescriptorType
            buf64[2] = 1; // bNbrPorts
            buf64[6] = 8; // bHubContrCurrent
          }
        } else if(cs.setup[1] == 0 && cs.setup[0] == 0x80){
          // USB_REQ_GET_STATUS USB_RT_PORT
          // usb_port_status
          *(short*)(buf64+0) = 3; // wPortStatus
        } else if(cs.setup[1] == 0 && cs.setup[0] == 0xa0){
          // USB_REQ_GET_STATUS USB_RT_HUB
          // usb_hub_status
          memset(buf64, 0xff, 4);
        } else if(cs.setup[1] == 0 && cs.setup[0] == 0xa3){
          // USB_REQ_GET_STATUS USB_RT_PORT ???
          // usb_port_status ???
          memset(buf64, 0xff, 8);
        } else if(cs.setup[1] == 0 && cs.setup[0] == 0){
          // ???
          memset(buf64, 0xff, 8);
        } else if(cs.setup[1] == 0xfe){
          if(ntohl(ibh.ep) == 0){
            // US_BULK_GET_MAX_LUN
            buf64[0] = 0; // maybe max unit #?
          } else {
            memcpy(buf64, "USBS", 4);
            buf64[4] = lastTag; // make transport.c:1255 happy: bulk_cs_wrap.Tag
          }
        } else if(ntohl(cs.transfer_flags) == 0x40201 &&
                  cs.setup[0] == 0 && cs.setup[1] == 0){
          // usb_stor_Bulk_transport reading SCSI cmd result
          if(CDB[0] == 0x12){
            // INQUIRY
            buf64[4] = 36 - 5; // response_len
            buf64[2] = 14; // scsi_level?
            buf64[8] = 0xff; // flags?
            buf64[16] = 0xff; // flags?
          } else if(CDB[0] == 0x25){
            // READ_CAPACITY
            *(int*)(buf64+0) = htonl(1024); // lba? capacity?
            *(int*)(buf64+4) = htonl(512); // sector size
          }
          if(sym_all_scsi > 0 || sym_scsi_cmd == CDB[0]){
            for(int i = 0; i < 64 && i < translen; i += 8){
              *(long*)(buf64 + i) ^= symx();
            }
            if(CDB[0] == 0x12){
              // INQUIRY
              buf64[4] = 36 - 5; // response_len
            }
          }
        }
        if(cmdno == symcmd || cmdno == symcmd2){
          for(int i = 0; i < 64 && i+8 <= sizeof(buf64); i += 8){
            *(long*)(buf64 + i) ^= symx();
          }
        }
        write(s1, buf64, translen);
      }
    } else if(ntohl(ibh.command) == 2){
      // USBIP_CMD_UNLINK
      // struct usbip_header_cmd_unlink uh;
      char buf[sizeof(struct usbip_header_cmd_submit)];
      memset(buf, 0, sizeof(buf));
      if(readn(s1, buf, sizeof(buf)) < 0)
        break;
      unsigned int uh = *(int*)buf;;
      printf("unlink seq %d\n", ntohl(uh));
      
      struct usbip_header_basic obh;
      memset(&obh, 0, sizeof(obh));
      obh.command = htonl(4); // USBIP_RET_UNLINK
      // obh.seqnum = ibh.seqnum;
      obh.seqnum = uh;
      obh.devid = ibh.devid;
      obh.direction = htonl(!ntohl(ibh.direction));
      obh.ep = ibh.ep;
      write(s1, &obh, sizeof(obh));

      char rsbuf[sizeof(struct usbip_header_cmd_submit)];
      memset(rsbuf, 0, sizeof(rsbuf));
      write(s1, rsbuf, sizeof(rsbuf));
    }

    if(cmdno >= 25)
      break;
      
    cmdno += 1;
  }
    
  usleep(500000);
  close(s1);
  usleep(500000);
}

             reply	other threads:[~2025-01-20 18:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-20 17:27 rtm [this message]
2025-01-21  7:01 ` USB hub code can dereference NULL hub and hub->ports Greg KH
2025-01-22 11:37   ` rtm
2025-01-22 15:55     ` Alan Stern
2025-01-22 19:21       ` rtm
2025-01-22 19:26         ` [PATCH] USB: hub: Ignore non-compliant devices with too many configs or interfaces Alan Stern
2025-02-03 15:35           ` Alan Stern
2025-02-03 15:49             ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=95564.1737394039@localhost \
    --to=rtm@csail.mit.edu \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).