[RFC,2/2] HID: usbhid: kcov: add annotations for coverage collection
diff mbox series

Message ID 6b4b598d012d981c0c45fcc9f121ba210bd222f9.1576170740.git.andreyknvl@google.com
State New
Delegated to: Jiri Kosina
Headers show
Series
  • kcov: collect coverage from usbhid interrupts
Related show

Commit Message

Andrey Konovalov Dec. 12, 2019, 5:15 p.m. UTC
This patch adds kcov_remote_start/stop() callbacks into usbhid code that
is executed in interrupt context. As the result, kcov can be used to
collect coverage from those parts of the code, which is used to facilitate
coverage-guided fuzzing with syzkaller.

Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
---
 drivers/hid/usbhid/hid-core.c | 25 ++++++++++++++++++++-----
 drivers/hid/usbhid/usbkbd.c   | 15 ++++++++++++---
 drivers/hid/usbhid/usbmouse.c |  7 ++++++-
 3 files changed, 38 insertions(+), 9 deletions(-)

Comments

Jiri Kosina Dec. 13, 2019, 8:31 a.m. UTC | #1
On Thu, 12 Dec 2019, Andrey Konovalov wrote:

> This patch adds kcov_remote_start/stop() callbacks into usbhid code that
> is executed in interrupt context. As the result, kcov can be used to
> collect coverage from those parts of the code, which is used to facilitate
> coverage-guided fuzzing with syzkaller.
> 
> Signed-off-by: Andrey Konovalov <andreyknvl@google.com>

Acked-by: Jiri Kosina <jkosina@suse.cz>

Patch
diff mbox series

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index c7bc9db5b192..3e825f27d882 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -274,6 +274,8 @@  static void hid_irq_in(struct urb *urb)
 	struct usbhid_device	*usbhid = hid->driver_data;
 	int			status;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	switch (urb->status) {
 	case 0:			/* success */
 		usbhid->retry_delay = 0;
@@ -300,12 +302,12 @@  static void hid_irq_in(struct urb *urb)
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		set_bit(HID_CLEAR_HALT, &usbhid->iofl);
 		schedule_work(&usbhid->reset_work);
-		return;
+		goto out;
 	case -ECONNRESET:	/* unlink */
 	case -ENOENT:
 	case -ESHUTDOWN:	/* unplug */
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
-		return;
+		goto out;
 	case -EILSEQ:		/* protocol error or unplug */
 	case -EPROTO:		/* protocol error or unplug */
 	case -ETIME:		/* protocol error or unplug */
@@ -313,7 +315,7 @@  static void hid_irq_in(struct urb *urb)
 		usbhid_mark_busy(usbhid);
 		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
 		hid_io_error(hid);
-		return;
+		goto out;
 	default:		/* error */
 		hid_warn(urb->dev, "input irq status %d received\n",
 			 urb->status);
@@ -330,6 +332,9 @@  static void hid_irq_in(struct urb *urb)
 			hid_io_error(hid);
 		}
 	}
+
+out:
+	kcov_remote_stop();
 }
 
 static int hid_submit_out(struct hid_device *hid)
@@ -433,6 +438,8 @@  static void hid_irq_out(struct urb *urb)
 	unsigned long flags;
 	int unplug = 0;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	switch (urb->status) {
 	case 0:			/* success */
 		break;
@@ -459,7 +466,7 @@  static void hid_irq_out(struct urb *urb)
 				hid_submit_out(hid) == 0) {
 			/* Successfully submitted next urb in queue */
 			spin_unlock_irqrestore(&usbhid->lock, flags);
-			return;
+			goto out;
 		}
 	}
 
@@ -467,6 +474,9 @@  static void hid_irq_out(struct urb *urb)
 	spin_unlock_irqrestore(&usbhid->lock, flags);
 	usb_autopm_put_interface_async(usbhid->intf);
 	wake_up(&usbhid->wait);
+
+out:
+	kcov_remote_stop();
 }
 
 /*
@@ -480,6 +490,8 @@  static void hid_ctrl(struct urb *urb)
 	unsigned long flags;
 	int unplug = 0, status = urb->status;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	switch (status) {
 	case 0:			/* success */
 		if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
@@ -510,7 +522,7 @@  static void hid_ctrl(struct urb *urb)
 				hid_submit_ctrl(hid) == 0) {
 			/* Successfully submitted next urb in queue */
 			spin_unlock_irqrestore(&usbhid->lock, flags);
-			return;
+			goto out;
 		}
 	}
 
@@ -518,6 +530,9 @@  static void hid_ctrl(struct urb *urb)
 	spin_unlock_irqrestore(&usbhid->lock, flags);
 	usb_autopm_put_interface_async(usbhid->intf);
 	wake_up(&usbhid->wait);
+
+out:
+	kcov_remote_stop();
 }
 
 static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report,
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index d5b7a696a68c..eae46e51ca6a 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -102,13 +102,15 @@  static void usb_kbd_irq(struct urb *urb)
 	struct usb_kbd *kbd = urb->context;
 	int i;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	switch (urb->status) {
 	case 0:			/* success */
 		break;
 	case -ECONNRESET:	/* unlink */
 	case -ENOENT:
 	case -ESHUTDOWN:
-		return;
+		goto out;
 	/* -EPIPE:  should clear the halt */
 	default:		/* error */
 		goto resubmit;
@@ -148,6 +150,9 @@  static void usb_kbd_irq(struct urb *urb)
 		hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d",
 			kbd->usbdev->bus->bus_name,
 			kbd->usbdev->devpath, i);
+
+out:
+	kcov_remote_stop();
 }
 
 static int usb_kbd_event(struct input_dev *dev, unsigned int type,
@@ -192,6 +197,8 @@  static void usb_kbd_led(struct urb *urb)
 	unsigned long flags;
 	struct usb_kbd *kbd = urb->context;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	if (urb->status)
 		hid_warn(urb->dev, "led urb status %d received\n",
 			 urb->status);
@@ -201,7 +208,7 @@  static void usb_kbd_led(struct urb *urb)
 	if (*(kbd->leds) == kbd->newleds){
 		kbd->led_urb_submitted = false;
 		spin_unlock_irqrestore(&kbd->leds_lock, flags);
-		return;
+		goto out;
 	}
 
 	*(kbd->leds) = kbd->newleds;
@@ -212,7 +219,9 @@  static void usb_kbd_led(struct urb *urb)
 		kbd->led_urb_submitted = false;
 	}
 	spin_unlock_irqrestore(&kbd->leds_lock, flags);
-	
+
+out:
+	kcov_remote_stop();
 }
 
 static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 073127e65ac1..f470ffa8fa87 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -53,13 +53,15 @@  static void usb_mouse_irq(struct urb *urb)
 	struct input_dev *dev = mouse->dev;
 	int status;
 
+	kcov_remote_start_usb((u64)urb->dev->bus->busnum);
+
 	switch (urb->status) {
 	case 0:			/* success */
 		break;
 	case -ECONNRESET:	/* unlink */
 	case -ENOENT:
 	case -ESHUTDOWN:
-		return;
+		goto out;
 	/* -EPIPE:  should clear the halt */
 	default:		/* error */
 		goto resubmit;
@@ -83,6 +85,9 @@  static void usb_mouse_irq(struct urb *urb)
 			"can't resubmit intr, %s-%s/input0, status %d\n",
 			mouse->usbdev->bus->bus_name,
 			mouse->usbdev->devpath, status);
+
+out:
+	kcov_remote_stop();
 }
 
 static int usb_mouse_open(struct input_dev *dev)