From patchwork Thu Mar 26 14:44:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460265 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9A3A092A for ; Thu, 26 Mar 2020 14:44:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 730612077D for ; Thu, 26 Mar 2020 14:44:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Of70chDF" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727941AbgCZOoT (ORCPT ); Thu, 26 Mar 2020 10:44:19 -0400 Received: from mail-wm1-f73.google.com ([209.85.128.73]:43977 "EHLO mail-wm1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727931AbgCZOoS (ORCPT ); Thu, 26 Mar 2020 10:44:18 -0400 Received: by mail-wm1-f73.google.com with SMTP id r19so2532605wmg.8 for ; Thu, 26 Mar 2020 07:44:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=GbETiUgT64s7N54cDqIoGj6dWJrQUmDSafvr3l6+BU4=; b=Of70chDFsS+raLmZssCv6MBdjh8AvQ812eLg3x6wFZR10hHFOAyVzxG5YidgWquT4E I0kGyd+LisxCbY8SBLcQmdG5D1hCXHCnNGT6HlrC0remGw2MZdpGAfDCAOuhQ36s1lW6 9bPXk8T7KjwruWTjLrM3qWvP4iuzWX6qN2FHRf46bwfqGhy4AOFedaOb7C9993F2Z+B/ 0LrJC/0WnOTbxVufOcpTmidG7T4DGxwtAzAGXyhkgwDGbtxQoCufUajx4SzaGEKIxxFi Hg7SskpwC/pISxApikn5yt9VOjwBDhClDsYcjzfTnncFx6aR5r/fZnVZwNF1sQy+0WRR pemQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=GbETiUgT64s7N54cDqIoGj6dWJrQUmDSafvr3l6+BU4=; b=fPa3WADBXmzxcQ4NQTtFUu0kz6e2L044gvJd2WJUI4INbnGG75/xINERAGw15b4jPa hpUnnoymkGiIzy5EPozBsj3J6McPII4syIzH9EXHrTosSlNqyYYAkO9YPEYVbEUyY1y5 9OGzZFbiCpmRWp0pc9imcCo15Php+n6ofN9OglpmCHboVf32xce17pNvafshs1joAjwv PfD3gV1SbY/Q3bgpd+W5Uo8JcaPW2g3d3rHZk/pZcUD1afjjLMaooyeKvc8OJe/JWW5K jkXmcdIaDRAIAtLvU0O/0wKrUSjBz2881WSJlwW6d3Yyzxi0t/g0KfeSHbEE6LFcKYTc 7IaQ== X-Gm-Message-State: ANhLgQ27ukId3LdNa1vJWzL++7m1cYMrRONro0P3TmsW50lG48QYhOtq UnNyfKuoZAMz37/P6zktbqMFrMSz0rDsmOVU X-Google-Smtp-Source: ADFU+vt4V9MvjgmktXXnFFA0QdyXgAfatYdSBrYl1qMecxvvVZBEVlPA1HaDXmYHCa1p/V6wmmEnOQASWyRdFjmo X-Received: by 2002:adf:df04:: with SMTP id y4mr9596663wrl.318.1585233856669; Thu, 26 Mar 2020 07:44:16 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:00 +0100 In-Reply-To: Message-Id: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 1/7] kcov: cleanup debug messages From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Previous commit left a lot of excessive debug messages, clean them up. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- kernel/kcov.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index f50354202dbe..f6bd119c9419 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -98,6 +98,7 @@ static struct kcov_remote *kcov_remote_find(u64 handle) return NULL; } +/* Must be called with kcov_remote_lock locked. */ static struct kcov_remote *kcov_remote_add(struct kcov *kcov, u64 handle) { struct kcov_remote *remote; @@ -119,16 +120,13 @@ static struct kcov_remote_area *kcov_remote_area_get(unsigned int size) struct kcov_remote_area *area; struct list_head *pos; - kcov_debug("size = %u\n", size); list_for_each(pos, &kcov_remote_areas) { area = list_entry(pos, struct kcov_remote_area, list); if (area->size == size) { list_del(&area->list); - kcov_debug("rv = %px\n", area); return area; } } - kcov_debug("rv = NULL\n"); return NULL; } @@ -136,7 +134,6 @@ static struct kcov_remote_area *kcov_remote_area_get(unsigned int size) static void kcov_remote_area_put(struct kcov_remote_area *area, unsigned int size) { - kcov_debug("area = %px, size = %u\n", area, size); INIT_LIST_HEAD(&area->list); area->size = size; list_add(&area->list, &kcov_remote_areas); @@ -366,7 +363,6 @@ static void kcov_remote_reset(struct kcov *kcov) hash_for_each_safe(kcov_remote_map, bkt, tmp, remote, hnode) { if (remote->kcov != kcov) continue; - kcov_debug("removing handle %llx\n", remote->handle); hash_del(&remote->hnode); kfree(remote); } @@ -553,7 +549,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, switch (cmd) { case KCOV_INIT_TRACE: - kcov_debug("KCOV_INIT_TRACE\n"); /* * Enable kcov in trace mode and setup buffer size. * Must happen before anything else. @@ -572,7 +567,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, kcov->mode = KCOV_MODE_INIT; return 0; case KCOV_ENABLE: - kcov_debug("KCOV_ENABLE\n"); /* * Enable coverage for the current task. * At this point user must have been enabled trace mode, @@ -598,7 +592,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, kcov_get(kcov); return 0; case KCOV_DISABLE: - kcov_debug("KCOV_DISABLE\n"); /* Disable coverage for the current task. */ unused = arg; if (unused != 0 || current->kcov != kcov) @@ -610,7 +603,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, kcov_put(kcov); return 0; case KCOV_REMOTE_ENABLE: - kcov_debug("KCOV_REMOTE_ENABLE\n"); if (kcov->mode != KCOV_MODE_INIT || !kcov->area) return -EINVAL; t = current; @@ -629,7 +621,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, kcov->remote_size = remote_arg->area_size; spin_lock(&kcov_remote_lock); for (i = 0; i < remote_arg->num_handles; i++) { - kcov_debug("handle %llx\n", remote_arg->handles[i]); if (!kcov_check_handle(remote_arg->handles[i], false, true, false)) { spin_unlock(&kcov_remote_lock); @@ -644,8 +635,6 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, } } if (remote_arg->common_handle) { - kcov_debug("common handle %llx\n", - remote_arg->common_handle); if (!kcov_check_handle(remote_arg->common_handle, true, false, false)) { spin_unlock(&kcov_remote_lock); @@ -782,7 +771,6 @@ void kcov_remote_start(u64 handle) spin_lock(&kcov_remote_lock); remote = kcov_remote_find(handle); if (!remote) { - kcov_debug("no remote found"); spin_unlock(&kcov_remote_lock); return; } @@ -810,8 +798,6 @@ void kcov_remote_start(u64 handle) /* Reset coverage size. */ *(u64 *)area = 0; - kcov_debug("area = %px, size = %u", area, size); - kcov_start(t, size, area, mode, sequence); } @@ -881,10 +867,8 @@ void kcov_remote_stop(void) unsigned int size = t->kcov_size; int sequence = t->kcov_sequence; - if (!kcov) { - kcov_debug("no kcov found\n"); + if (!kcov) return; - } kcov_stop(t); t->kcov = NULL; @@ -894,8 +878,6 @@ void kcov_remote_stop(void) * KCOV_DISABLE could have been called between kcov_remote_start() * and kcov_remote_stop(), hence the check. */ - kcov_debug("move if: %d == %d && %d\n", - sequence, kcov->sequence, (int)kcov->remote); if (sequence == kcov->sequence && kcov->remote) kcov_move_area(kcov->mode, kcov->area, kcov->size, area); spin_unlock(&kcov->lock); From patchwork Thu Mar 26 14:44:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460277 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E9050161F for ; Thu, 26 Mar 2020 14:44:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CA7AA20775 for ; Thu, 26 Mar 2020 14:44:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FhIoyUmr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728322AbgCZOow (ORCPT ); Thu, 26 Mar 2020 10:44:52 -0400 Received: from mail-wm1-f74.google.com ([209.85.128.74]:41910 "EHLO mail-wm1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727982AbgCZOoX (ORCPT ); Thu, 26 Mar 2020 10:44:23 -0400 Received: by mail-wm1-f74.google.com with SMTP id f207so2538054wme.6 for ; Thu, 26 Mar 2020 07:44:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=pUHuESTKj8oX3rFdN5fYGgzuMeb9qfGw8IwhPoMTDMA=; b=FhIoyUmrn4ShByWsJAyife9npYZwAwtImGROiYB3g54hnYVqJHuVPKFwiLyFVD2JjF 4hH1g2oXBbrKMrLg45cPPblaUO8K5EKVM53f49H9ca8i6t3BfL7OfI1PAYb6Y6VMND9M sqGui/aWUV+7roKV6oKPGulSLk3qzR1qMb3We2uY1F16QGAYN0KjbFnZxuyO6p4pywi+ 532T1vUIQRpkS1a7CCJ0moHhsFP1WuN06DKLupDZQ/RoADiJUGpfMTUthW/b7VHoZ1nu /wCHuS57uOKExIDF+B1o8DHWja5DUTEy06HKQPs4LFR3+AEr0o1tFXhqigq2DiMhtNMA 2f2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=pUHuESTKj8oX3rFdN5fYGgzuMeb9qfGw8IwhPoMTDMA=; b=W/Br5WQjnAgINGX/594IrwgjcG2oQ5oDZvRgwvefKM3hl/ZlMb7twRl3m4JEiHX+v1 bQ0jpZmekHPAY7nQRqV1N2IRZTpUk5GWv/FROAofBPeas7qgBEgIUUKc/9mXlUFCgBgr NpRP+x4PyKtf7u+YAzHoX9YKCIG/c1YbcNBfXL2k5SiEs0RW+eyezPErSnsvksLy395p zoa57sPkC6SkYK9EodNioqwajZhYBaPGAHQfUPgZE6CcrIDfqp0fxELcI+3kYKfcYa9Q IequZFYGbM//lh8vYBad7MsmCV/ehNmLqpGqCAkQCFA8xn8ktN8VQp3EjhqVwSG39x+e x8Yg== X-Gm-Message-State: ANhLgQ1XEkg5+6CiTlCDXZKt17qmxkehP+dD6/LuZK9A2dpY8qdtM9Uf zOeC7j78yGvocfjmTermmq+zjA/XxaUOYckE X-Google-Smtp-Source: ADFU+vs0KXaxlxADpXExCJIuRumete/6F3eTe5emAyvJp6l9dhGeqpsgqwUVVX03+S11UXk7EkQ4taSnSeGcmyij X-Received: by 2002:a5d:4003:: with SMTP id n3mr9356095wrp.176.1585233859680; Thu, 26 Mar 2020 07:44:19 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:01 +0100 In-Reply-To: Message-Id: <9d9134359725a965627b7e8f2652069f86f1d1fa.1585233617.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 2/7] kcov: fix potential use-after-free in kcov_remote_start From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org If vmalloc() fails in kcov_remote_start() we'll access remote->kcov without holding kcov_remote_lock, so remote might potentially be freed at that point. Cache kcov pointer in a local variable. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- kernel/kcov.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index f6bd119c9419..cc5900ac2467 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -748,6 +748,7 @@ static const struct file_operations kcov_fops = { void kcov_remote_start(u64 handle) { struct kcov_remote *remote; + struct kcov *kcov; void *area; struct task_struct *t; unsigned int size; @@ -774,16 +775,17 @@ void kcov_remote_start(u64 handle) spin_unlock(&kcov_remote_lock); return; } + kcov = remote->kcov; /* Put in kcov_remote_stop(). */ - kcov_get(remote->kcov); - t->kcov = remote->kcov; + kcov_get(kcov); + t->kcov = kcov; /* * Read kcov fields before unlock to prevent races with * KCOV_DISABLE / kcov_remote_reset(). */ - size = remote->kcov->remote_size; - mode = remote->kcov->mode; - sequence = remote->kcov->sequence; + size = kcov->remote_size; + mode = kcov->mode; + sequence = kcov->sequence; area = kcov_remote_area_get(size); spin_unlock(&kcov_remote_lock); @@ -791,7 +793,7 @@ void kcov_remote_start(u64 handle) area = vmalloc(size * sizeof(unsigned long)); if (!area) { t->kcov = NULL; - kcov_put(remote->kcov); + kcov_put(kcov); return; } } From patchwork Thu Mar 26 14:44:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460269 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1D9BF17EF for ; Thu, 26 Mar 2020 14:44:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EB261206F6 for ; Thu, 26 Mar 2020 14:44:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="aw0P04YP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728078AbgCZOo0 (ORCPT ); Thu, 26 Mar 2020 10:44:26 -0400 Received: from mail-qt1-f202.google.com ([209.85.160.202]:50377 "EHLO mail-qt1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728061AbgCZOoZ (ORCPT ); Thu, 26 Mar 2020 10:44:25 -0400 Received: by mail-qt1-f202.google.com with SMTP id v3so5247218qte.17 for ; Thu, 26 Mar 2020 07:44:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=uADEPLEkmZYfl7wsDudGbWabefvMuQ72zIel8QzC/WU=; b=aw0P04YP4yvA8GnGIM0IcXnPvtJDys1Gity150L+KCmm0IC/T5fGbPj9kC4kCEVNJ4 9z8syQlUrww+G4voblWJf75Z6KRzu3d24JGR6TiMNBqStsOdio+mylrao3e92CrcY7LK QzGJpMPFaY45X6JLhgAw7rhDD+F0Jz0PwZW4ROIJm1pbACbd03E6sTciNdO6Xb2xvYY6 IZSF2/47CDqMxYpMpTRNU0RubDpO+/S7+m5G//Uh2q+GRU58O9NWqPvP4lH4TsxRICYL ggJg3t9A9DyAAdsoXV3c1yfF6ts0TtxS3q+Q5j0mxGcUldYz06whBc5d1uUs/TmcGMxB GeZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=uADEPLEkmZYfl7wsDudGbWabefvMuQ72zIel8QzC/WU=; b=pVuqpKs8nGxsElHLdKS9jiQCJVqKezWGrnvBrOouArEXEQTjXXQBNYyM92puLRSTu/ MehF6WByugoMsBEy4TW2YcMGwiWa3UeVMaSf6rhOCIRzq/m25OLc9v3yvJTFsb8/I4Z5 E1+OO59D5nhJvoUnp9AwPINryHQWiLL5ex7oMvUj9ypMCuNo8PE+GCQ5jw/sGu0bD1aW kQ/kxPYCazsyX/qQ++T/x5rjm73uhlJK+tjPyfIP446spld62yweJs8CHn2NySkf6lb+ bEYFIUCZTGC9UMVqF2Rj43szH/9ZDR45Fwoyl1BIBwo+VWm6BEXzHCpM6z4elkhL0HUi j2Xw== X-Gm-Message-State: ANhLgQ2l7EheZ0EeiUgHyBnRgHqA7G0Sl11xyUpGxUkCkBeMhOn8wZxK aqBesNmNE4BOQ+LimzR7ZLysf2Ia5iH1Dcc1 X-Google-Smtp-Source: ADFU+vs4gqRNBmQXkP6I3fFSrAC8BH3/Wz+XULZj0Pml6O/pA3hyTV2hkInmZiNHUchejwlpgz8UdPROVbbRnL5U X-Received: by 2002:ac8:3565:: with SMTP id z34mr8683029qtb.168.1585233862532; Thu, 26 Mar 2020 07:44:22 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:02 +0100 In-Reply-To: Message-Id: <6644839d3567df61ade3c4b246a46cacbe4f9e11.1585233617.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 3/7] kcov: move t->kcov assignments into kcov_start/stop From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Every time kcov_start/stop() is called, t->kcov is also assigned, so move the assignment into the functions. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- kernel/kcov.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index cc5900ac2467..888d0a236b04 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -309,10 +309,12 @@ void notrace __sanitizer_cov_trace_switch(u64 val, u64 *cases) EXPORT_SYMBOL(__sanitizer_cov_trace_switch); #endif /* ifdef CONFIG_KCOV_ENABLE_COMPARISONS */ -static void kcov_start(struct task_struct *t, unsigned int size, - void *area, enum kcov_mode mode, int sequence) +static void kcov_start(struct task_struct *t, struct kcov *kcov, + unsigned int size, void *area, enum kcov_mode mode, + int sequence) { kcov_debug("t = %px, size = %u, area = %px\n", t, size, area); + t->kcov = kcov; /* Cache in task struct for performance. */ t->kcov_size = size; t->kcov_area = area; @@ -326,6 +328,7 @@ static void kcov_stop(struct task_struct *t) { WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED); barrier(); + t->kcov = NULL; t->kcov_size = 0; t->kcov_area = NULL; } @@ -333,7 +336,6 @@ static void kcov_stop(struct task_struct *t) static void kcov_task_reset(struct task_struct *t) { kcov_stop(t); - t->kcov = NULL; t->kcov_sequence = 0; t->kcov_handle = 0; } @@ -584,9 +586,8 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, return mode; kcov_fault_in_area(kcov); kcov->mode = mode; - kcov_start(t, kcov->size, kcov->area, kcov->mode, + kcov_start(t, kcov, kcov->size, kcov->area, kcov->mode, kcov->sequence); - t->kcov = kcov; kcov->t = t; /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); @@ -778,7 +779,6 @@ void kcov_remote_start(u64 handle) kcov = remote->kcov; /* Put in kcov_remote_stop(). */ kcov_get(kcov); - t->kcov = kcov; /* * Read kcov fields before unlock to prevent races with * KCOV_DISABLE / kcov_remote_reset(). @@ -792,7 +792,6 @@ void kcov_remote_start(u64 handle) if (!area) { area = vmalloc(size * sizeof(unsigned long)); if (!area) { - t->kcov = NULL; kcov_put(kcov); return; } @@ -800,7 +799,7 @@ void kcov_remote_start(u64 handle) /* Reset coverage size. */ *(u64 *)area = 0; - kcov_start(t, size, area, mode, sequence); + kcov_start(t, kcov, size, area, mode, sequence); } EXPORT_SYMBOL(kcov_remote_start); @@ -873,7 +872,6 @@ void kcov_remote_stop(void) return; kcov_stop(t); - t->kcov = NULL; spin_lock(&kcov->lock); /* From patchwork Thu Mar 26 14:44:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460267 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ACFAB6CA for ; Thu, 26 Mar 2020 14:44:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 86A6B206F6 for ; Thu, 26 Mar 2020 14:44:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KEoRpVSk" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728123AbgCZOo2 (ORCPT ); Thu, 26 Mar 2020 10:44:28 -0400 Received: from mail-wm1-f73.google.com ([209.85.128.73]:59092 "EHLO mail-wm1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728076AbgCZOo1 (ORCPT ); Thu, 26 Mar 2020 10:44:27 -0400 Received: by mail-wm1-f73.google.com with SMTP id f185so2243192wmf.8 for ; Thu, 26 Mar 2020 07:44:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=54OrhN2UqwV2UhsoJvUHxfQ1kDDVGkOr4MVVzi//0Tk=; b=KEoRpVSkWQ4Obk49T2NiJnX5YvJMnj3y3LgQFqwTA1oA/83D5qT2cj2EfHEHsE9J9N TGuPaMZhafTcNM2K42DypQ9gbY6yTkkybsVnR7xLkhU9pHHROVFcwmDaPTza1GJSb0Ge jIBdCY+tA7V4j/NBfsV7OiyhebX2WU7ix8oHpnagMsExk9Xz2MSTQMmejmAXrN46h4ou 2MCeDPUyX+0nufKlwrQHFC/N9N5EMdo+taW4rpwKj4eqVQN8gBpULoizs44b8hyuubVq N0f3TwMFhuPbRKhHGF92OZfLfthHUhlLrD2vyPHVBft52EyJiVRYcAaCdmFbyHz8NxP2 KJaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=54OrhN2UqwV2UhsoJvUHxfQ1kDDVGkOr4MVVzi//0Tk=; b=aUnCXNue9di7tZ65flLi0pL0W1gsX1vE88PfDlTC9puRSv9W+tvX2tK8aGqsmRyk7U mCXFUSPtrSiTLCdbeciLknPy9H88k6yYwJqRD/9yqwmaJVXXPaqdOZc192vYjDmScciC oLV5y9tUV+NuLfkNeznU9NjnPNw0LE662oueeXz1MifedToltLIxP1m+YeAXSThyXGvr j7KtXHS9YTV1EgAdZd+bZe1BXCYPkkygO0e7SmpMPrIvhgQw16LqsRpIp00AdOd+Qz1D EwpkMZj9nCIvZRGCTnMSAFA6V/TDb0upgKY45zF6KO4XN3NY+Yy4IjWS3HyMwf4cExJM mqRQ== X-Gm-Message-State: ANhLgQ0e5uyEKQzQXrrnhMAzmXZJMyZLrcIQM3agbT/nckiO9dCdwXO5 PtkDMnpTk1jfgnF3havGTmPqOg1sjf6Pur2F X-Google-Smtp-Source: ADFU+vvlT13Jzs850JgMlpxi2djO8UDTtjaMsAWeLvetR7iUup932A5Lrxp2uoQCpabpVD2nkeGM/35wY/4GBFEl X-Received: by 2002:adf:bc4a:: with SMTP id a10mr9594715wrh.7.1585233865501; Thu, 26 Mar 2020 07:44:25 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:03 +0100 In-Reply-To: Message-Id: <5889efe35e0b300e69dba97216b1288d9c2428a8.1585233617.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 4/7] kcov: move t->kcov_sequence assignment From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Move t->kcov_sequence assignment before assigning t->kcov_mode for consistency. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- kernel/kcov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index 888d0a236b04..b985b7a72870 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -318,10 +318,10 @@ static void kcov_start(struct task_struct *t, struct kcov *kcov, /* Cache in task struct for performance. */ t->kcov_size = size; t->kcov_area = area; + t->kcov_sequence = sequence; /* See comment in check_kcov_mode(). */ barrier(); WRITE_ONCE(t->kcov_mode, mode); - t->kcov_sequence = sequence; } static void kcov_stop(struct task_struct *t) From patchwork Thu Mar 26 14:44:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460271 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 82FCC6CA for ; Thu, 26 Mar 2020 14:44:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 60B842076A for ; Thu, 26 Mar 2020 14:44:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="c+ZoYPXG" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727665AbgCZOod (ORCPT ); Thu, 26 Mar 2020 10:44:33 -0400 Received: from mail-wr1-f74.google.com ([209.85.221.74]:52244 "EHLO mail-wr1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728060AbgCZOoa (ORCPT ); Thu, 26 Mar 2020 10:44:30 -0400 Received: by mail-wr1-f74.google.com with SMTP id d17so3140798wrw.19 for ; Thu, 26 Mar 2020 07:44:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=oIpcXbs7HMCH2rBdnqz+HP+vStesLvB5cyCR3m0rGWo=; b=c+ZoYPXGUoJs2G/uhQEnUj77jkFvWpTLdmamQD3MFPVB+Nyp1lAOyNuUnkqGWydMmL JEXdgJz2J5z6gJX9UXQc8YCtsYAlAjK7Rc7rnUrRpn2cewG+nI9vSf6ICvIzne7/xjnn 3i0HXX0N3RzFw76sJh65Jo7hxW/ZgaOUoNqQG54kuyWQKDSlsAfh4lQjv7qwtTptSE2v 0AeEGs3c/EbHErb+uqqFf6ZL50ELe0IXS504Gf1x3Y7wipHS4p4HCYR8U/5TY15M3Xp3 /6ZOMckWYP2cn9jw89fGsDMXP6uPCmTf+Af6Zno2subsLnKKVjEh9WfuL+scknGp+ujF 1RXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=oIpcXbs7HMCH2rBdnqz+HP+vStesLvB5cyCR3m0rGWo=; b=UEpukUsBWrkGBp0u/25DJC1mTjqk4YUPXthpgyeK2dUaF63gSg9fQle0cyljMtCSmK hClIWFBsG+vPq7/zrf6JIONQYc9P1ULx8gj+nwoyatuWIdVotpkyVvzUikj5aSbqxaPu faKiobmcEXDRsO1xMd6BOU69JePI387nJiuAw4tpuNKqt91By02zeVpmhkQHo9GozRF7 BpgRl2kN+ZTk5yN7cusVWFGx1kFmKDNRH64MGl63/2veEPJloE98eUinsUiXUGlc4RjN 92xDEtFNbqV3Q2qYgBCfQFdI1TcVeyhj9gbwhPnTSbO0fsDKi4lDxGMk+bEWMJtNUIyN X+Ng== X-Gm-Message-State: ANhLgQ3HJuBKuiCPg31FqQmlzyBl4h/cKIbzA9+l6GZsbf2QKMW31uwP lvLd7MX9FfRQRSnjrLUPEhYbZM9vOYwS+8JN X-Google-Smtp-Source: ADFU+vvDk8YRsGM5M4gwKzl2NX7plDCaSAsdBkDdkcig7hV0LfODIkqeS2n63I7L68P82vgp9GsW1K9wbg6Gp0wl X-Received: by 2002:adf:a490:: with SMTP id g16mr9721097wrb.42.1585233868532; Thu, 26 Mar 2020 07:44:28 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:04 +0100 In-Reply-To: Message-Id: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 5/7] kcov: use t->kcov_mode as enabled indicator From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Currently kcov_remote_start() and kcov_remote_stop() check t->kcov to find out whether the coverage is already being collected by the current task. Use t->kcov_mode for that instead. This doesn't change the overall behavior in any way, but serves as a preparation for the following softirq coverage collection support patch. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- kernel/kcov.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index b985b7a72870..e43f06b5b2e4 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -746,26 +746,33 @@ static const struct file_operations kcov_fops = { * In turns kcov_remote_stop() clears those pointers from task_struct to stop * collecting coverage and copies all collected coverage into the kcov area. */ + +static inline bool kcov_mode_enabled(unsigned int mode) +{ + return (mode & ~KCOV_IN_CTXSW) != KCOV_MODE_DISABLED; +} + void kcov_remote_start(u64 handle) { + struct task_struct *t = current; struct kcov_remote *remote; struct kcov *kcov; + unsigned int mode; void *area; - struct task_struct *t; unsigned int size; - enum kcov_mode mode; int sequence; if (WARN_ON(!kcov_check_handle(handle, true, true, true))) return; if (WARN_ON(!in_task())) return; - t = current; + /* * Check that kcov_remote_start is not called twice * nor called by user tasks (with enabled kcov). */ - if (WARN_ON(t->kcov)) + mode = READ_ONCE(t->kcov_mode); + if (WARN_ON(kcov_mode_enabled(mode))) return; kcov_debug("handle = %llx\n", handle); @@ -863,13 +870,20 @@ static void kcov_move_area(enum kcov_mode mode, void *dst_area, void kcov_remote_stop(void) { struct task_struct *t = current; - struct kcov *kcov = t->kcov; - void *area = t->kcov_area; - unsigned int size = t->kcov_size; - int sequence = t->kcov_sequence; + struct kcov *kcov; + unsigned int mode; + void *area; + unsigned int size; + int sequence; - if (!kcov) + mode = READ_ONCE(t->kcov_mode); + barrier(); + if (!kcov_mode_enabled(mode)) return; + kcov = t->kcov; + area = t->kcov_area; + size = t->kcov_size; + sequence = t->kcov_sequence; kcov_stop(t); From patchwork Thu Mar 26 14:44:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460275 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1FB036CA for ; Thu, 26 Mar 2020 14:44:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DA44820848 for ; Thu, 26 Mar 2020 14:44:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="QTqlxnne" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728327AbgCZOop (ORCPT ); Thu, 26 Mar 2020 10:44:45 -0400 Received: from mail-wm1-f73.google.com ([209.85.128.73]:40484 "EHLO mail-wm1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728180AbgCZOoe (ORCPT ); Thu, 26 Mar 2020 10:44:34 -0400 Received: by mail-wm1-f73.google.com with SMTP id m4so2537733wmi.5 for ; Thu, 26 Mar 2020 07:44:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=i+TXEoie2sTBr2dnThQR+9htRpeLnA73TSoHcGw8MPE=; b=QTqlxnneD1JtsuDlN8eDoEAKkHFFXYPRdAu5eZVMmXl3tjL/upzcJN9xNeTxhd4Ulx d+U1JteBOR1GUCB3w8KNcS1pg7i9RxNrIMwQHyEvZ4eYXWHdlEPfXBGOdeDlkCDSJJmi YjmB4XMv7EC7Ndm/pJZB7ecIyDmDhdhyiRF6oUB0Uxv/FGC+cosiJAdELrxsl9CjG2ot 2rrPaTZYl0pgm41D9bni1qWaqHrMyTIPu+HROs6o2G6pVSI0Z+C7nBwV4an9S4SvGf90 Iokvlq8D2FGpTPBx95pQ3SsFkKSMjOleSjFX/fp1CPuu5qSxd3C8HmFVQDd4yomZEytp S/gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=i+TXEoie2sTBr2dnThQR+9htRpeLnA73TSoHcGw8MPE=; b=rY035FZ55hdaql3IWigiLv3KHOLXeMIwq3lb07LCk2LpqkKydlLFA+mpVnysYaM4mc vU09RhGudfhNg8fxjf/YO3NxpCzk4YLgn66rlxuX7NUnUrlzQFUWzDuXaKFFjTIut0F9 7ZvRPdYr8WOW2BGD6GEsXy5QgdtiC351OHkoxWGJ9H3Hu972n6ebqK9nkjL3viIm3DSD 9X9ulabG7VNS+YGFLcLP9Bfr9ttqJTQnAz28il/FNCHBFO/fQNjmeMuxytUUIgm8IMHT Q1e+9K3yH394T0P2WgrNG0x4CdFdzWQcIGIN4m4YhgrHZP4n7omRGAsJquJrg/jmtrYN 2V7A== X-Gm-Message-State: ANhLgQ29Xv3Htq1nIcDnoKP8Pqp5kquo66SH4LDRM/55v6Hq4l/19sY6 AfQQY2YdjNfBnSK6UCppWFUDqFPn8y1ktKal X-Google-Smtp-Source: ADFU+vtmTInyZOZRa7pn/TcnV57AE0ROuXy7Gjs+SGS6QlJpw0UwnoNllVFVvE0WFiHYylkMDSun21h5FHP7eBKf X-Received: by 2002:adf:f452:: with SMTP id f18mr7421858wrp.222.1585233871499; Thu, 26 Mar 2020 07:44:31 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:05 +0100 In-Reply-To: Message-Id: <841c778aa3849c5cb8c3761f56b87ce653a88671.1585233617.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 6/7] kcov: collect coverage from interrupts From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This change extends kcov remote coverage support to allow collecting coverage from soft interrupts in addition to kernel background threads. To collect coverage from code that is executed in softirq context, a part of that code has to be annotated with kcov_remote_start/stop() in a similar way as how it is done for global kernel background threads. Then the handle used for the annotations has to be passed to the KCOV_REMOTE_ENABLE ioctl. Internally this patch adjusts the __sanitizer_cov_trace_pc() compiler inserted callback to not bail out when called from softirq context. kcov_remote_start/stop() are updated to save/restore the current per task kcov state in a per-cpu area (in case the softirq came when the kernel was already collecting coverage in task context). Coverage from softirqs is collected into pre-allocated per-cpu areas, whose size is controlled by the new CONFIG_KCOV_IRQ_AREA_SIZE. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- Documentation/dev-tools/kcov.rst | 17 +-- include/linux/sched.h | 3 + kernel/kcov.c | 194 ++++++++++++++++++++++++------- lib/Kconfig.debug | 9 ++ 4 files changed, 176 insertions(+), 47 deletions(-) diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst index 1c4e1825d769..8548b0b04e43 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst @@ -217,14 +217,15 @@ This allows to collect coverage from two types of kernel background threads: the global ones, that are spawned during kernel boot in a limited number of instances (e.g. one USB hub_event() worker thread is spawned per USB HCD); and the local ones, that are spawned when a user interacts with -some kernel interface (e.g. vhost workers). +some kernel interface (e.g. vhost workers); as well as from soft +interrupts. -To enable collecting coverage from a global background thread, a unique -global handle must be assigned and passed to the corresponding -kcov_remote_start() call. Then a userspace process can pass a list of such -handles to the KCOV_REMOTE_ENABLE ioctl in the handles array field of the -kcov_remote_arg struct. This will attach the used kcov device to the code -sections, that are referenced by those handles. +To enable collecting coverage from a global background thread or from a +softirq, a unique global handle must be assigned and passed to the +corresponding kcov_remote_start() call. Then a userspace process can pass +a list of such handles to the KCOV_REMOTE_ENABLE ioctl in the handles +array field of the kcov_remote_arg struct. This will attach the used kcov +device to the code sections, that are referenced by those handles. Since there might be many local background threads spawned from different userspace processes, we can't use a single global handle per annotation. @@ -242,7 +243,7 @@ handles as they don't belong to a particular subsystem. The bytes 4-7 are currently reserved and must be zero. In the future the number of bytes used for the subsystem or handle ids might be increased. -When a particular userspace proccess collects coverage by via a common +When a particular userspace proccess collects coverage via a common handle, kcov will collect coverage for each code section that is annotated to use the common handle obtained as kcov_handle from the current task_struct. However non common handles allow to collect coverage diff --git a/include/linux/sched.h b/include/linux/sched.h index 04278493bf15..e4e0f80143c8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1229,6 +1229,9 @@ struct task_struct { /* KCOV sequence number: */ int kcov_sequence; + + /* Collect coverage from softirq context: */ + unsigned int kcov_softirq; #endif #ifdef CONFIG_MEMCG diff --git a/kernel/kcov.c b/kernel/kcov.c index e43f06b5b2e4..0980fc608770 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -86,6 +86,18 @@ static DEFINE_SPINLOCK(kcov_remote_lock); static DEFINE_HASHTABLE(kcov_remote_map, 4); static struct list_head kcov_remote_areas = LIST_HEAD_INIT(kcov_remote_areas); +struct kcov_percpu_data { + void *irq_area; + + unsigned int saved_mode; + unsigned int saved_size; + void *saved_area; + struct kcov *saved_kcov; + int saved_sequence; +}; + +DEFINE_PER_CPU(struct kcov_percpu_data, kcov_percpu_data); + /* Must be called with kcov_remote_lock locked. */ static struct kcov_remote *kcov_remote_find(u64 handle) { @@ -145,9 +157,10 @@ static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_stru /* * We are interested in code coverage as a function of a syscall inputs, - * so we ignore code executed in interrupts. + * so we ignore code executed in interrupts, unless we are in a remote + * coverage collection section in a softirq. */ - if (!in_task()) + if (!in_task() && !(in_serving_softirq() && t->kcov_softirq)) return false; mode = READ_ONCE(t->kcov_mode); /* @@ -360,8 +373,9 @@ static void kcov_remote_reset(struct kcov *kcov) int bkt; struct kcov_remote *remote; struct hlist_node *tmp; + unsigned long flags; - spin_lock(&kcov_remote_lock); + spin_lock_irqsave(&kcov_remote_lock, flags); hash_for_each_safe(kcov_remote_map, bkt, tmp, remote, hnode) { if (remote->kcov != kcov) continue; @@ -370,7 +384,7 @@ static void kcov_remote_reset(struct kcov *kcov) } /* Do reset before unlock to prevent races with kcov_remote_start(). */ kcov_reset(kcov); - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); } static void kcov_disable(struct task_struct *t, struct kcov *kcov) @@ -399,12 +413,13 @@ static void kcov_put(struct kcov *kcov) void kcov_task_exit(struct task_struct *t) { struct kcov *kcov; + unsigned long flags; kcov = t->kcov; if (kcov == NULL) return; - spin_lock(&kcov->lock); + spin_lock_irqsave(&kcov->lock, flags); kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t); /* * For KCOV_ENABLE devices we want to make sure that t->kcov->t == t, @@ -428,12 +443,12 @@ void kcov_task_exit(struct task_struct *t) * By combining all three checks into one we get: */ if (WARN_ON(kcov->t != t)) { - spin_unlock(&kcov->lock); + spin_unlock_irqrestore(&kcov->lock, flags); return; } /* Just to not leave dangling references behind. */ kcov_disable(t, kcov); - spin_unlock(&kcov->lock); + spin_unlock_irqrestore(&kcov->lock, flags); kcov_put(kcov); } @@ -444,12 +459,13 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma) struct kcov *kcov = vma->vm_file->private_data; unsigned long size, off; struct page *page; + unsigned long flags; area = vmalloc_user(vma->vm_end - vma->vm_start); if (!area) return -ENOMEM; - spin_lock(&kcov->lock); + spin_lock_irqsave(&kcov->lock, flags); size = kcov->size * sizeof(unsigned long); if (kcov->mode != KCOV_MODE_INIT || vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != size) { @@ -459,7 +475,7 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma) if (!kcov->area) { kcov->area = area; vma->vm_flags |= VM_DONTEXPAND; - spin_unlock(&kcov->lock); + spin_unlock_irqrestore(&kcov->lock, flags); for (off = 0; off < size; off += PAGE_SIZE) { page = vmalloc_to_page(kcov->area + off); if (vm_insert_page(vma, vma->vm_start + off, page)) @@ -468,7 +484,7 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma) return 0; } exit: - spin_unlock(&kcov->lock); + spin_unlock_irqrestore(&kcov->lock, flags); vfree(area); return res; } @@ -548,6 +564,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, int mode, i; struct kcov_remote_arg *remote_arg; struct kcov_remote *remote; + unsigned long flags; switch (cmd) { case KCOV_INIT_TRACE: @@ -620,17 +637,19 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, kcov->t = t; kcov->remote = true; kcov->remote_size = remote_arg->area_size; - spin_lock(&kcov_remote_lock); + spin_lock_irqsave(&kcov_remote_lock, flags); for (i = 0; i < remote_arg->num_handles; i++) { if (!kcov_check_handle(remote_arg->handles[i], false, true, false)) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, + flags); kcov_disable(t, kcov); return -EINVAL; } remote = kcov_remote_add(kcov, remote_arg->handles[i]); if (IS_ERR(remote)) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, + flags); kcov_disable(t, kcov); return PTR_ERR(remote); } @@ -638,20 +657,22 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, if (remote_arg->common_handle) { if (!kcov_check_handle(remote_arg->common_handle, true, false, false)) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, + flags); kcov_disable(t, kcov); return -EINVAL; } remote = kcov_remote_add(kcov, remote_arg->common_handle); if (IS_ERR(remote)) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, + flags); kcov_disable(t, kcov); return PTR_ERR(remote); } t->kcov_handle = remote_arg->common_handle; } - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); return 0; @@ -667,6 +688,7 @@ static long kcov_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) struct kcov_remote_arg *remote_arg = NULL; unsigned int remote_num_handles; unsigned long remote_arg_size; + unsigned long flags; if (cmd == KCOV_REMOTE_ENABLE) { if (get_user(remote_num_handles, (unsigned __user *)(arg + @@ -687,9 +709,9 @@ static long kcov_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) } kcov = filep->private_data; - spin_lock(&kcov->lock); + spin_lock_irqsave(&kcov->lock, flags); res = kcov_ioctl_locked(kcov, cmd, arg); - spin_unlock(&kcov->lock); + spin_unlock_irqrestore(&kcov->lock, flags); kfree(remote_arg); @@ -706,8 +728,8 @@ static const struct file_operations kcov_fops = { /* * kcov_remote_start() and kcov_remote_stop() can be used to annotate a section - * of code in a kernel background thread to allow kcov to be used to collect - * coverage from that part of code. + * of code in a kernel background thread or in a softirq to allow kcov to be + * used to collect coverage from that part of code. * * The handle argument of kcov_remote_start() identifies a code section that is * used for coverage collection. A userspace process passes this handle to @@ -718,9 +740,9 @@ static const struct file_operations kcov_fops = { * the type of the kernel thread whose code is being annotated. * * For global kernel threads that are spawned in a limited number of instances - * (e.g. one USB hub_event() worker thread is spawned per USB HCD), each - * instance must be assigned a unique 4-byte instance id. The instance id is - * then combined with a 1-byte subsystem id to get a handle via + * (e.g. one USB hub_event() worker thread is spawned per USB HCD) and for + * softirqs, each instance must be assigned a unique 4-byte instance id. The + * instance id is then combined with a 1-byte subsystem id to get a handle via * kcov_remote_handle(subsystem_id, instance_id). * * For local kernel threads that are spawned from system calls handler when a @@ -739,7 +761,7 @@ static const struct file_operations kcov_fops = { * * See Documentation/dev-tools/kcov.rst for more details. * - * Internally, this function looks up the kcov device associated with the + * Internally, kcov_remote_start() looks up the kcov device associated with the * provided handle, allocates an area for coverage collection, and saves the * pointers to kcov and area into the current task_struct to allow coverage to * be collected via __sanitizer_cov_trace_pc() @@ -752,6 +774,39 @@ static inline bool kcov_mode_enabled(unsigned int mode) return (mode & ~KCOV_IN_CTXSW) != KCOV_MODE_DISABLED; } +void kcov_remote_softirq_start(struct task_struct *t) +{ + struct kcov_percpu_data *data = this_cpu_ptr(&kcov_percpu_data); + unsigned int mode; + + mode = READ_ONCE(t->kcov_mode); + barrier(); + if (kcov_mode_enabled(mode)) { + data->saved_mode = mode; + data->saved_size = t->kcov_size; + data->saved_area = t->kcov_area; + data->saved_sequence = t->kcov_sequence; + data->saved_kcov = t->kcov; + kcov_stop(t); + } +} + +void kcov_remote_softirq_stop(struct task_struct *t) +{ + struct kcov_percpu_data *data = this_cpu_ptr(&kcov_percpu_data); + + if (data->saved_kcov) { + kcov_start(t, data->saved_kcov, data->saved_size, + data->saved_area, data->saved_mode, + data->saved_sequence); + data->saved_mode = 0; + data->saved_size = 0; + data->saved_area = NULL; + data->saved_sequence = 0; + data->saved_kcov = NULL; + } +} + void kcov_remote_start(u64 handle) { struct task_struct *t = current; @@ -761,28 +816,42 @@ void kcov_remote_start(u64 handle) void *area; unsigned int size; int sequence; + unsigned long flags; if (WARN_ON(!kcov_check_handle(handle, true, true, true))) return; - if (WARN_ON(!in_task())) + if (!in_task() && !in_serving_softirq()) return; + local_irq_save(flags); + /* - * Check that kcov_remote_start is not called twice - * nor called by user tasks (with enabled kcov). + * Check that kcov_remote_start() is not called twice in background + * threads nor called by user tasks (with enabled kcov). */ mode = READ_ONCE(t->kcov_mode); - if (WARN_ON(kcov_mode_enabled(mode))) + if (WARN_ON(in_task() && kcov_mode_enabled(mode))) { + local_irq_restore(flags); return; - - kcov_debug("handle = %llx\n", handle); + } + /* + * Check that kcov_remote_start() is not called twice in softirqs. + * Note, that kcov_remote_start() can be called from a softirq that + * happened while collecting coverage from a background thread. + */ + if (WARN_ON(in_serving_softirq() && t->kcov_softirq)) { + local_irq_restore(flags); + return; + } spin_lock(&kcov_remote_lock); remote = kcov_remote_find(handle); if (!remote) { - spin_unlock(&kcov_remote_lock); + spin_unlock_irqrestore(&kcov_remote_lock, flags); return; } + kcov_debug("handle = %llx, context: %s\n", handle, + in_task() ? "task" : "softirq"); kcov = remote->kcov; /* Put in kcov_remote_stop(). */ kcov_get(kcov); @@ -790,12 +859,18 @@ void kcov_remote_start(u64 handle) * Read kcov fields before unlock to prevent races with * KCOV_DISABLE / kcov_remote_reset(). */ - size = kcov->remote_size; mode = kcov->mode; sequence = kcov->sequence; - area = kcov_remote_area_get(size); - spin_unlock(&kcov_remote_lock); + if (in_task()) { + size = kcov->remote_size; + area = kcov_remote_area_get(size); + } else { + size = CONFIG_KCOV_IRQ_AREA_SIZE; + area = this_cpu_ptr(&kcov_percpu_data)->irq_area; + } + spin_unlock_irqrestore(&kcov_remote_lock, flags); + /* Can only happen when in_task(). */ if (!area) { area = vmalloc(size * sizeof(unsigned long)); if (!area) { @@ -803,11 +878,20 @@ void kcov_remote_start(u64 handle) return; } } + + local_irq_save(flags); + /* Reset coverage size. */ *(u64 *)area = 0; + if (in_serving_softirq()) { + kcov_remote_softirq_start(t); + t->kcov_softirq = 1; + } kcov_start(t, kcov, size, area, mode, sequence); + local_irq_restore(flags); + } EXPORT_SYMBOL(kcov_remote_start); @@ -875,31 +959,53 @@ void kcov_remote_stop(void) void *area; unsigned int size; int sequence; + unsigned long flags; + + if (!in_task() && !in_serving_softirq()) + return; + + local_irq_save(flags); mode = READ_ONCE(t->kcov_mode); barrier(); - if (!kcov_mode_enabled(mode)) + if (!kcov_mode_enabled(mode)) { + local_irq_restore(flags); return; + } kcov = t->kcov; area = t->kcov_area; size = t->kcov_size; sequence = t->kcov_sequence; + if (WARN_ON(!in_serving_softirq() && t->kcov_softirq)) { + local_irq_restore(flags); + return; + } + kcov_stop(t); + if (in_serving_softirq()) { + t->kcov_softirq = 0; + kcov_remote_softirq_stop(t); + } spin_lock(&kcov->lock); /* * KCOV_DISABLE could have been called between kcov_remote_start() - * and kcov_remote_stop(), hence the check. + * and kcov_remote_stop(), hence the sequence check. */ if (sequence == kcov->sequence && kcov->remote) kcov_move_area(kcov->mode, kcov->area, kcov->size, area); spin_unlock(&kcov->lock); - spin_lock(&kcov_remote_lock); - kcov_remote_area_put(area, size); - spin_unlock(&kcov_remote_lock); + if (in_task()) { + spin_lock(&kcov_remote_lock); + kcov_remote_area_put(area, size); + spin_unlock(&kcov_remote_lock); + } + local_irq_restore(flags); + + /* Get in kcov_remote_start(). */ kcov_put(kcov); } EXPORT_SYMBOL(kcov_remote_stop); @@ -913,6 +1019,16 @@ EXPORT_SYMBOL(kcov_common_handle); static int __init kcov_init(void) { + int cpu; + + for_each_possible_cpu(cpu) { + void *area = vmalloc(CONFIG_KCOV_IRQ_AREA_SIZE * + sizeof(unsigned long)); + if (!area) + return -ENOMEM; + per_cpu_ptr(&kcov_percpu_data, cpu)->irq_area = area; + } + /* * The kcov debugfs file won't ever get removed and thus, * there is no need to protect it against removal races. The diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 69def4a9df00..a1f25b27d32d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1740,6 +1740,15 @@ config KCOV_INSTRUMENT_ALL filesystem fuzzing with AFL) then you will want to enable coverage for more specific subsets of files, and should say n here. +config KCOV_IRQ_AREA_SIZE + hex "Size of interrupt coverage collection area in words" + depends on KCOV + default 0x40000 + help + KCOV uses preallocated per-cpu areas to collect coverage from + soft interrupts. This specifies the size of those areas in the + number of unsigned long words. + menuconfig RUNTIME_TESTING_MENU bool "Runtime Testing" def_bool y From patchwork Thu Mar 26 14:44:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 11460273 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 680F66CA for ; Thu, 26 Mar 2020 14:44:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 48CEE2082E for ; Thu, 26 Mar 2020 14:44:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="T7rfAJNo" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728284AbgCZOoi (ORCPT ); Thu, 26 Mar 2020 10:44:38 -0400 Received: from mail-wr1-f73.google.com ([209.85.221.73]:48204 "EHLO mail-wr1-f73.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728232AbgCZOog (ORCPT ); Thu, 26 Mar 2020 10:44:36 -0400 Received: by mail-wr1-f73.google.com with SMTP id d1so3132240wru.15 for ; Thu, 26 Mar 2020 07:44:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=BlSTEEJDHJm2U/4O7K2LlSQNpyzxY2AHmNeqxBMGqLE=; b=T7rfAJNouLP3QFbM7TjP2jKWn6OXe65PojXJkkX0Qk8dDkngAXWRVnPYsr8VxL1ujL +c6h+Q2mhiAEGAZzGrjdL5kHYOFN3oHTyYRbTbzsD1HOOF9s1L3ZXQ5WQgk0ugjvhzoT RglWzWjx+LDQPZRsXCDn6CJBZD5VRg4q+irS+8ww6cO54kjukjRDPxQBtYWdF+LXxx6g Rr5R7U4IG8Z6F2v9gHuUdr/x+/7NDk0OpSI5FzKBZBkAKtIVzl2M4cGxT61BGgV1ILzd jxr1PH63vVfKFE1rWp6cPQ13CoQTvQqOIPdfbAwgWZN/xAZudV1B7iWOy9z+iQuGcsVH Kxjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=BlSTEEJDHJm2U/4O7K2LlSQNpyzxY2AHmNeqxBMGqLE=; b=Bh3M9vgvK/xPE/5lmJ4LTjhv3/c5d7ST4l5m+Yr5Ga8m90MAUeDLSg6cbLBKWcimjY k61QYIIgMTKSzEzJX7+wkQt2FsMpdHzazGU4upSY4I70V7AvxjdpRjfNH18vQgvCnpUV qLT08CHyweyTSD05FRYK247UCibkEsCSzH9ekE1blnAkhBPdjf+tMoUwg13Ya6/na0DJ yX0nvHfHX2wODFmtiNbqfBw64BL2CB3w0yUswB4H4PD2iv/vPnOYzF9GKLvtshkGae+Y 0zhI/cMAg6Q3weoUWXZwE1+mpRu4Mzkg3YuKvtFsdF/SYchVobA9JlEuQBS1SRfvgrlv 7NIA== X-Gm-Message-State: ANhLgQ3iGR6a+4njRwG3WGL0VdiEbIToP+gChAmCfBeNRi3qi5piOTIX XoK6TGmDOKpoypkPm0F97yCG2muu/c7bABfz X-Google-Smtp-Source: ADFU+vu4Wmk3bo0iTn0SCfakv1wwE8avBfBttA5grmmbe01DRbQuLXjTHB3LsyiFQwggR2UX3CWXHn0Kedt0netC X-Received: by 2002:adf:db0a:: with SMTP id s10mr6783005wri.361.1585233874611; Thu, 26 Mar 2020 07:44:34 -0700 (PDT) Date: Thu, 26 Mar 2020 15:44:06 +0100 In-Reply-To: Message-Id: <4520671eeb604adbc2432c248b0c07fbaa5519ef.1585233617.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.26.0.rc2.310.g2932bb562d-goog Subject: [PATCH v4 7/7] usb: core: kcov: collect coverage from usb complete callback From: Andrey Konovalov To: Dmitry Vyukov Cc: Greg Kroah-Hartman , Alan Stern , Andrew Morton , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Potapenko , Marco Elver , Andrey Konovalov Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org This patch adds kcov_remote_start/stop() callbacks around the urb complete() callback that is executed in softirq context when dummy_hcd is in use. As the result, kcov can be used to collect coverage from those callbacks, which is used to facilitate coverage-guided fuzzing with syzkaller. Signed-off-by: Andrey Konovalov Reviewed-by: Dmitry Vyukov --- drivers/usb/core/hcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index aa45840d8273..de624c47e190 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1645,7 +1646,9 @@ static void __usb_hcd_giveback_urb(struct urb *urb) /* pass ownership to the completion handler */ urb->status = status; + kcov_remote_start_usb((u64)urb->dev->bus->busnum); urb->complete(urb); + kcov_remote_stop(); usb_anchor_resume_wakeups(anchor); atomic_dec(&urb->use_count);