Re: External USB fuzzing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 4, 2018 at 9:37 PM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> On Mon, 4 Jun 2018, Andrey Konovalov wrote:

Hi, Alan!

[...]

>> The perfect solution would be to have something like /dev/tun for USB,
>> where you can write USB packets and the kernel would synchronously
>> process them. I'm not sure whether this is possible (highly
>> asynchronous USB core subsystem architecture + all communication is
>> initiated by the host).
>
> gadgetfs is a little like that already, except of course that the
> processing is not synchronous.

Yes, I started with GadgetFS initially, but actually ended up writing
my own interface that provides userspace interface to the gadget API
instead. Once I figure out what exactly I need from it, it might be a
good idea to merge it with GadgetFS as some special mode. Or not, not
sure yet.

>
> Another aspect of this would be fuzzing USB host controller drivers.
> In theory you could start doing this now, although you would have to
> use a real UDC instead of dummy-hcd.  However, this may create more
> complications that you want to deal with at the moment.

Could you elaborate on this? AFAIU the dummy device contains both a
virtual UDC and a virtual HCD that are connected to each other and
allow to plug a gadget device into usb core within the kernel. How do
you test a driver for an actual host controller? Is there a way to
connect a dummy UDC with an actual HCD?

>
>> Another thing we could do is to teach kcov to collect coverage from
>> arbitrary kernel threads. In this case we could collect coverage from
>> the thread that processes the USB events.
>
> That seems like a more general solution, something which could be
> applied to other settings too.  One difficulty you would face is
> telling the tool which threads to work on.  This is particularly tricky
> when dealing with work queues, since a single work-queue thread can run
> code for many different drivers and purposes.
>
> Perhaps it would be better to collect coverage information based on the
> location of the code being executed rather than the thread ID.

Yes, that is what I was thinking about. I have a prototype patch for
kcov that allows to annotate a block of the kernel code and collect
coverage from that block. I think this is the way I'll try to move
forward with.

>
>>  However we would still need
>> some signal to understand whether the device finished initialization,
>> etc. (with the first approach we could tell that some stage of device
>> initialization is finished by seeing that hub_event() returned).
>
> Why initialization particularly?  A device goes through a number of
> stages in its life cycle.
>
> I get the impression you would like to have a mechanism whereby you can
> send messages from arbitrary places in the kernel to your testing
> process.  A little like the function tracer or perf, perhaps.

Yes, we need to see all the stages, initialization was just an example.

The main question is: suppose we started a test program that emulates
a virtual USB device. How do we know that the test is over? Once all
the hub events are processed we can tell that the device is probably
either connected successfully or failed to connect. But then the
device driver can start it's own thread for example or register a
timer that does more work with the device. There are probably some
ways to tell what the device driver does at this moment for some
standard USB classes.

I guess I'll start with a timeout for now, until I figure out how to
properly collect coverage.

[...]

>> 2. A way to isolate independent test programs.
>>
>> Right now CONFIG_USB_DUMMY_HCD creates one global hub to which all
>> emulated USB devices connect. Would it be possible to create one
>> virtual hub per test (or at least one per test process) by say calling
>> some ioctl? What changes would that require?
>
> Are you planning to run multiple test processes concurrently?  If you
> aren't then this isn't an issue.

Yes, I believe that would increase fuzzing speed.

>
> In fact, dummy-hcd is capable of creating more than one virtual root
> hub (see the "num" module parameter), so in theory you could run
> multiple tests at the same time.  I don't think this capability has
> been tested very much.

OK, that's nice. I just tried it and it kind of works, but there are two issues:

1. There's a hardcoded limit on the maximum number of virtual UDCs
(#define MAX_NUM_UDC 2). Increasing this parameters seems to work just
fine.

2. All the virtual UDCs get the same name "dummy_udc". And since the
process of UDC lookup to bind a gadget driver is based on the UDC name
(see usb_gadget_probe_driver()), we can't bind different gadget
drivers to different UDCs (and therefore connect to different hubs).

>
>> Basically we need a way to run a test program (that connects a USB
>> device and works with it from userspace for example) and then destroy
>> all the accumulated state before running the next test.
>
> You can do that with dummy-hcd simply by removing the USB gadget
> (closing the gadgetfs files, for example).

Do I understand correctly that calling usb_gadget_unregister_driver()
should get rid of all of the device state? (That's what gadgetfs seems
to do when you close the file).

> If you want to be extra
> thorough, unload the gadget driver and dummy-hcd modules after the end
> of the test, and then reload them before starting the next test.  That
> should get rid of any important state.

What state is kept if we don't reload the module?

Thanks for the reply!
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux