Example #1
0
static void
hub_connect_port (struct psfreedom_device *dev, unsigned int port)
{
  if (port == 0 || port > 6)
    return;

  switch_to_port (dev, 0);

  /* Here, we must enable the port directly, otherwise we might loose time
     with the host asking for the status a few more times, and waiting for it to
     be enabled, etc.. and we might miss the 5seconds window in which we need
     to connect the JIG */
  dev->hub_ports[port-1].status |= PORT_STAT_CONNECTION;
  dev->hub_ports[port-1].status |= PORT_STAT_ENABLE;

  /* If the speed flag set is not the same as what the device suports, it will
     not work */
  if (psfreedom_is_high_speed ())
    dev->hub_ports[port-1].status |= PORT_STAT_HIGH_SPEED;
  else if (psfreedom_is_low_speed ())
    dev->hub_ports[port-1].status |= PORT_STAT_HIGH_SPEED;

  dev->hub_ports[port-1].change |= PORT_STAT_C_CONNECTION;
  hub_port_changed (dev);
}
Example #2
0
static void
hub_disconnect_port (struct psfreedom_device *dev, unsigned int port)
{
  if (port == 0 || port > 6)
    return;

  switch_to_port (dev, 0);
  dev->hub_ports[port-1].status &= ~PORT_STAT_CONNECTION;
  dev->hub_ports[port-1].status &= ~PORT_STAT_ENABLE;
  dev->hub_ports[port-1].status &= ~PORT_STAT_HIGH_SPEED;
  dev->hub_ports[port-1].status &= ~PORT_STAT_LOW_SPEED;
  dev->hub_ports[port-1].change |= PORT_STAT_C_CONNECTION;
  hub_port_changed (dev);
}
Example #3
0
static void hub_disconnect_port (unsigned int port)
{
	if (port == 0 || port > 6) {
		return;
	}

	switch_to_port (0);
	
	// After jig send response ep2 needs behave as hub 
	if (machine_state==DEVICE3_WAIT_DISCONNECT) {
		ep2_reset();
	}

	port_status[port-1] &= ~PORT_STAT_CONNECTION;
	port_status[port-1] &= ~PORT_STAT_ENABLE;
	port_change[port-1] |= PORT_STAT_C_CONNECTION;
	hub_port_changed ();
}
Example #4
0
static void hub_connect_port (unsigned int port)
{
	if (port == 0 || port > 6) {
		return;
	}
	
	expected_port_reset = port;
	
	//PRINTKD( "[%lu]Hub: Connect port %d\n", (jiffies-start_time)*10, port );
	switch_to_port (0);

	/* Here, we must enable the port directly, otherwise we might loose time
	with the host asking for the status a few more times, and waiting for it to
	be enabled, etc.. and we might miss the 5seconds window in which we need
	to connect the JIG */
	port_status[port-1] |= PORT_STAT_CONNECTION;
	port_status[port-1] |= PORT_STAT_ENABLE;
	port_change[port-1] |= PORT_STAT_C_CONNECTION;

	hub_port_changed ();
}
Example #5
0
/*
 * The setup() callback implements all the ep0 functionality that's
 * not handled lower down, in hardware or the hardware driver (like
 * device and endpoint feature flags, and their status).  It's all
 * housekeeping for the gadget function we're implementing.  Most of
 * the work is in config-specific setup.
 */
static int psfreedom_setup(struct usb_gadget *gadget,
    const struct usb_ctrlrequest *ctrl)
{
  struct psfreedom_device *dev = get_gadget_data(gadget);
  struct usb_request *req = dev->req;
  int value = -EOPNOTSUPP;
  u16 w_index = le16_to_cpu(ctrl->wIndex);
  u16 w_value = le16_to_cpu(ctrl->wValue);
  u16 w_length = le16_to_cpu(ctrl->wLength);
  u8 address = psfreedom_get_address (dev->gadget);
  unsigned long flags;
  u16 request = (ctrl->bRequestType << 8) | ctrl->bRequest;

  spin_lock_irqsave (&dev->lock, flags);
  VDBG (dev, "Setup called %d (%d) -- %d -- %d. Myaddr :%d\n", ctrl->bRequest,
      ctrl->bRequestType, w_value, w_index, address);

  req->zero = 0;

  /* Enable the timer if it's not already enabled */
  if (timer_added == 0)
    add_timer (&psfreedom_state_machine_timer);
  timer_added = 1;

  /* Set the address of the port */
  if (address)
    dev->port_address[dev->current_port] = address;

  /* Setup the hub or the devices */
  if (dev->current_port == 0)
    value = hub_setup (gadget, ctrl, request, w_index, w_value, w_length);
  else
    value = devices_setup (gadget, ctrl, request, w_index, w_value, w_length);

#ifdef NO_DELAYED_PORT_SWITCHING
  if (dev->switch_to_port_delayed >= 0)
    switch_to_port (dev, dev->switch_to_port_delayed);
  dev->switch_to_port_delayed = -1;
#endif

  DBG (dev, "%s Setup called %s (%d - %d) -> %d (w_length=%d)\n",
      STATUS_STR (dev->status),  REQUEST_STR (request), w_value, w_index,
      value, w_length);

  /* respond with data transfer before status phase? */
  if (value >= 0) {
    req->length = value;
    req->zero = value < w_length;
    value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
    if (value < 0) {
      DBG(dev, "ep_queue --> %d\n", value);
      req->status = 0;
      spin_unlock_irqrestore (&dev->lock, flags);
      psfreedom_setup_complete(gadget->ep0, req);
      return value;
    }
  }

  spin_unlock_irqrestore (&dev->lock, flags);
  /* device either stalls (value < 0) or reports success */
  return value;
}
Example #6
0
static void psfreedom_state_machine_timeout(unsigned long data)
{
  struct usb_gadget *gadget = (struct usb_gadget *)data;
  struct psfreedom_device *dev = get_gadget_data (gadget);
  unsigned long flags;

  spin_lock_irqsave (&dev->lock, flags);
  DBG (dev, "Timer fired, status is %s\n", STATUS_STR (dev->status));

  /* We need to delay switching the address because otherwise we will respond
     to the request (that triggered the port switch) with address 0. So we need
     to reply with the hub's address, THEN switch to 0.
  */
  if (dev->switch_to_port_delayed >= 0)
    switch_to_port (dev, dev->switch_to_port_delayed);
  dev->switch_to_port_delayed = -1;

  switch (dev->status) {
    case HUB_READY:
      dev->status = DEVICE1_WAIT_READY;
      hub_connect_port (dev, 1);
      break;
    case DEVICE1_READY:
      dev->status = DEVICE2_WAIT_READY;
      hub_connect_port (dev, 2);
      break;
    case DEVICE2_READY:
      dev->status = DEVICE3_WAIT_READY;
      hub_connect_port (dev, 3);
      break;
    case DEVICE3_READY:
      dev->status = DEVICE2_WAIT_DISCONNECT;
      hub_disconnect_port (dev, 2);
      break;
    case DEVICE2_DISCONNECTED:
      dev->status = DEVICE4_WAIT_READY;
      hub_connect_port (dev, 4);
      break;
    case DEVICE4_READY:
      dev->status = DEVICE5_WAIT_READY;
      hub_connect_port (dev, 5);
      break;
    case DEVICE5_CHALLENGED:
      jig_response_send (dev, NULL);
      break;
    case DEVICE5_READY:
#ifdef NO_DELAYED_PORT_SWITCHING
      /* if we can't delay the port switching, then we at this point, we can't
         disconnect the device 3... so we just unregister the driver so that
         all the devices get virtually disconnected and the exploit works.
         Since we won't exist after that, let's unlock the spinlock and return.
      */
      spin_unlock_irqrestore (&dev->lock, flags);
      dev->status = DONE;
      psfreedom_cleanup ();
      return;
#else
      dev->status = DEVICE3_WAIT_DISCONNECT;
      hub_disconnect_port (dev, 3);
#endif
      break;
    case DEVICE3_DISCONNECTED:
      dev->status = DEVICE5_WAIT_DISCONNECT;
      /* If not using JIG mode, then no need to unplug the JIG, since we'll
         need to keep it in memory so we can find its address from an lv2 dump
       */
#ifdef USE_JIG
      hub_disconnect_port (dev, 5);
#endif
      break;
    case DEVICE5_DISCONNECTED:
      dev->status = DEVICE4_WAIT_DISCONNECT;
      hub_disconnect_port (dev, 4);
      break;
    case DEVICE4_DISCONNECTED:
      dev->status = DEVICE1_WAIT_DISCONNECT;
      hub_disconnect_port (dev, 1);
      break;
    case DEVICE1_DISCONNECTED:
      /* simple check to see if a stage2 is loaded */
      if (dev->stage2_payload) {
        dev->status = DEVICE6_WAIT_READY;
        hub_connect_port (dev, 6);
      } else {
        dev->status = DONE;
        INFO (dev, "JAILBROKEN!!! DONE!!!!!!!!!\n");
        INFO (dev, "Congratulations, worked!");
        del_timer (&psfreedom_state_machine_timer);
        timer_added = 0;
      }
      break;
    default:
      break;
  }
  spin_unlock_irqrestore (&dev->lock, flags);

}
Example #7
0
static void psfreedom_state_machine_timeout(unsigned long data)
{
    struct usb_gadget *gadget = (struct usb_gadget *)data;
    struct psfreedom_device *dev = get_gadget_data (gadget);
    unsigned long flags;

    spin_lock_irqsave (&dev->lock, flags);
    DBG (dev, "Timer fired, status is %s\n", STATUS_STR (dev->status));

    /* We need to delay switching the address because otherwise we will respond
       to the request (that triggered the port switch) with address 0. So we need
       to reply with the hub's address, THEN switch to 0.
    */
    if (dev->switch_to_port_delayed >= 0)
        switch_to_port (dev, dev->switch_to_port_delayed);
    dev->switch_to_port_delayed = -1;

    switch (dev->status) {
    case HUB_READY:
        dev->status = DEVICE1_WAIT_READY;
        hub_connect_port (dev, 1);
        break;
    case DEVICE1_READY:
        dev->status = DEVICE2_WAIT_READY;
        hub_connect_port (dev, 2);
        break;
    case DEVICE2_READY:
        dev->status = DEVICE3_WAIT_READY;
        hub_connect_port (dev, 3);
        break;
    case DEVICE3_READY:
        dev->status = DEVICE2_WAIT_DISCONNECT;
        hub_disconnect_port (dev, 2);
        break;
    case DEVICE2_DISCONNECTED:
        dev->status = DEVICE4_WAIT_READY;
        hub_connect_port (dev, 4);
        break;
    case DEVICE4_READY:
        dev->status = DEVICE5_WAIT_READY;
        hub_connect_port (dev, 5);
        break;
    case DEVICE5_CHALLENGED:
        jig_response_send (dev, NULL);
        break;
    case DEVICE5_READY:
        dev->status = DEVICE3_WAIT_DISCONNECT;
        hub_disconnect_port (dev, 3);
        break;
    case DEVICE3_DISCONNECTED:
        dev->status = DEVICE5_WAIT_DISCONNECT;
        hub_disconnect_port (dev, 5);
        break;
    case DEVICE5_DISCONNECTED:
        dev->status = DEVICE4_WAIT_DISCONNECT;
        hub_disconnect_port (dev, 4);
        break;
    case DEVICE4_DISCONNECTED:
        dev->status = DEVICE1_WAIT_DISCONNECT;
        hub_disconnect_port (dev, 1);
        break;
    case DEVICE1_DISCONNECTED:
        dev->status = DEVICE6_WAIT_READY;
        hub_connect_port (dev, 6);
        break;
    case DEVICE6_READY:
        dev->status = DONE;
        INFO (dev, "Congratulations, worked!");
        del_timer (&psfreedom_state_machine_timer);
        timer_added = 0;
        break;
    default:
        break;
    }
    spin_unlock_irqrestore (&dev->lock, flags);

}