From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49F372E7187 for ; Thu, 26 Jun 2025 13:42:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945329; cv=none; b=H+0IZWN0h4xe+HWXERIFGL5xPkXEID9ven4OGTwE4hUyuLYWbunsb9px94cHg+NskE4bIo/OmP53DUz3ZZulftgsRa0rPo90Vqc27HMBKi8/kTTFcW5E0aej5iPzvSUOgImJkfhZEgG4wLMWKDni873ta4E0BQV4GLS7hphSiV0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945329; c=relaxed/simple; bh=nQL9qL18Vb2CXS7ndOrNIvZy9URifx39W6PpmGQvWJA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZBmTv/vzcSd8OJA7iJXW3IkdYqXPnw4yJIz1kzTnn2lftyc84Oa0RKvm3/hAFl3lYNNXViKG+tpvGLBImmy1Z0cQIHTQOPIWVXY8AcUfGu7xKIGe1xChA4DeXqa+p8ZlaVjjabEBWgDUqt1IS9WY+GL8a004LOZeTygRQ62e97o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=FBD6JQkv; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="FBD6JQkv" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-3a4f8192e2cso597841f8f.3 for ; Thu, 26 Jun 2025 06:42:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945326; x=1751550126; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=KgRyE+5ZFAr6FW9KaXMYIeYZG6lVPAbPaVY2rL2tJCY=; b=FBD6JQkvPpSWm9/p/41RH9lLravwqkc9DJ+g2VaZXBnoJwszZgpF82p6wJHxFnVIam dWIM6QrcgzPYpRdYLCMIK5pykrU36GrR/ZuZDx03RHbfZx5rWjOjuoVX+b+IMt54x6gi H0dcl42jn17/F7+QUMWMNyb6drq++FK2SnM/m67/fNoJGyq4fVu8oK+VqdGgiBInHSWr hTwSmo2x52aRRxgWJA8pJ1ImIchnYKzHNZ2EFS9QY0Jp4I4m8dVTKRPXzuWzyuGoRMWN xpuYYZiyJAEIlK0AgJU2k2Ym0ZLVoMUt8h+0UOW6YqqYJOswYUeme7LpXDmm4aaSSo+C HtyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945326; x=1751550126; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=KgRyE+5ZFAr6FW9KaXMYIeYZG6lVPAbPaVY2rL2tJCY=; b=B3iLyzXgQC+bEqHer0vizbPHfG+H9gzYjn5TR9zwVp2TZfORgKGP/gFTXZBzlvW3Jq yHju0rJf1tW0+iaWfS0jWfdW2PECpjaU8nwqqcNJKztymXM/XAm8P6V4NO+apiUYPMUs DqCraxjWMlpOPLEsp2oPsGCSl5YrToZ9/ZuWBK2d3axNqnQOwHFC+nVDCaKhfu0oht78 TZFMkpfR+MgC+h/4MQN23KLJqN9C5ig3HB81L2Grwa5i2FXIgdEQVtAUFkG+UyWVSLOa 2l0X0iqzhyx8a3CKE47uXtLKEywfz0P+lV/e2stbTPxXGRLO37lDsTFT8K6ttGN7a57E AAiA== X-Forwarded-Encrypted: i=1; AJvYcCXwFRd/9cnK6aKyyYqoaTf9GaIt5Q/NnEWQ8AuvXUdYOo8WNruRZFFRpbfmOUS3vRFLHDpsxo3xIgHGc7I=@vger.kernel.org X-Gm-Message-State: AOJu0YzVpIUo+lmeMAtfcv+XbBp7mjsOh80T1zqnVmyZTuG+pHLpVw33 6lMhcSONZj+dFLCYcohUW35uStnTCW+KFm8W+/bqiSYiebPzpzp7eOKu4LHYKZf7VHSdfqREBjL mw+STsQ== X-Google-Smtp-Source: AGHT+IFk9I2UFBPk4ooJjt86C1f4Vas4CeRth34J1XeNIpRrMluDFvYvas36eaZF9LEyQqYzdAYxPmqxpJ8= X-Received: from wmth13.prod.google.com ([2002:a05:600c:8b6d:b0:44f:f406:f4f2]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a5d:6f18:0:b0:3a5:8a68:b823 with SMTP id ffacd0b85a97d-3a6ed60755dmr5704580f8f.23.1750945326673; Thu, 26 Jun 2025 06:42:06 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:48 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-2-glider@google.com> Subject: [PATCH v2 01/11] x86: kcov: disable instrumentation of arch/x86/kernel/tsc.c From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sched_clock() appears to be called from interrupts, producing spurious coverage, as reported by CONFIG_KCOV_SELFTEST: RIP: 0010:__sanitizer_cov_trace_pc_guard+0x66/0xe0 kernel/kcov.c:288 ... fault_in_kernel_space+0x17/0x70 arch/x86/mm/fault.c:1119 handle_page_fault arch/x86/mm/fault.c:1477 exc_page_fault+0x56/0x110 arch/x86/mm/fault.c:1538 asm_exc_page_fault+0x26/0x30 ./arch/x86/include/asm/idtentry.h:623 RIP: 0010:__sanitizer_cov_trace_pc_guard+0x66/0xe0 kernel/kcov.c:288 ... sched_clock+0x12/0x70 arch/x86/kernel/tsc.c:284 __lock_pin_lock kernel/locking/lockdep.c:5628 lock_pin_lock+0xd7/0x180 kernel/locking/lockdep.c:5959 rq_pin_lock kernel/sched/sched.h:1761 rq_lock kernel/sched/sched.h:1838 __schedule+0x3a8/0x4b70 kernel/sched/core.c:6691 preempt_schedule_irq+0xbf/0x160 kernel/sched/core.c:7090 irqentry_exit+0x6f/0x90 kernel/entry/common.c:354 asm_sysvec_reschedule_ipi+0x1a/0x20 ./arch/x86/include/asm/idtentry.h:707 RIP: 0010:selftest+0x26/0x60 kernel/kcov.c:1223 ... kcov_init+0x81/0xa0 kernel/kcov.c:1252 do_one_initcall+0x2e1/0x910 do_initcall_level+0xff/0x160 init/main.c:1319 do_initcalls+0x4a/0xa0 init/main.c:1335 kernel_init_freeable+0x448/0x610 init/main.c:1567 kernel_init+0x24/0x230 init/main.c:1457 ret_from_fork+0x60/0x90 arch/x86/kernel/process.c:153 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 Signed-off-by: Alexander Potapenko --- arch/x86/kernel/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 84cfa179802c3..c08626d348c85 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -43,6 +43,8 @@ KCOV_INSTRUMENT_dumpstack_$(BITS).o :=3D n KCOV_INSTRUMENT_unwind_orc.o :=3D n KCOV_INSTRUMENT_unwind_frame.o :=3D n KCOV_INSTRUMENT_unwind_guess.o :=3D n +# Avoid instrumenting code that produces spurious coverage in interrupts. +KCOV_INSTRUMENT_tsc.o :=3D n =20 CFLAGS_head32.o :=3D -fno-stack-protector CFLAGS_head64.o :=3D -fno-stack-protector --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E21EB2E765B for ; Thu, 26 Jun 2025 13:42:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945334; cv=none; b=pvRQ9XE26xdkukWauT+O9biDk7IT6+t++Bj/h4B+38N95eqKCwHnuuvjTrtrUUfmS/yYyaaVdiDt5G7vSkNN5DkOj59u6dJJhslE6u0PsKtBGIAFY5RmGau2Uv+VcRklr0jlNKt2XgdeX2i1pzKW0NLNt62Dw7sku3zmJ6FmUaE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945334; c=relaxed/simple; bh=s9j5uH1RPS6ZE0s8gBoT8HhmU+i9Za/3OV8dFhL5BI4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=C6CBhxnoGi5uqy2Ud5HiuHfbVjKIDSvqGJewtotHHrCEcUb9COCZ3XzFIEZTfoKpGHVfnSkdi+vhQwW1U0/Bri8iOCYhdacN0qXDYdfZSs4JePTGzX2Lsk0ccMShcA2p1Sbr9HtH5ker3pX9LhPOG36wVo7Z48BVHVN1jiHnT2Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Jq3YleZk; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Jq3YleZk" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-451d3f03b74so5555915e9.3 for ; Thu, 26 Jun 2025 06:42:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945329; x=1751550129; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=FJiMSG3aUxEuiCh3YiYxcirsWMG54X+LrVgKBYabMpk=; b=Jq3YleZk1GfuCWoLC6nFWpsV/VWYbMU8NAvopbY8K7/CwysvvrigyRQG9zeuejZety drSc1oU4uNrWf0MKEjXDC4ccptExvGcRUeChrPzwNhElKPoAMAhCvaGWNVfvDeFRvuON qqsvfs6w3WycWde74u5vD6PpDd/m9FggErm51HOT9BAAylLPwPrqeT5pd5hakq49125o mOMJunszGENccH/dblyuf1LrtlUjhbd7GqJCPY/W1i0Fbm9nItuoi/1GNr4p6d8dUOI7 6H1HKsEBHnB59SJ9mfbdT3Btz45PFfUAFp1US7DWEQr4w8CEVV0Cjk2jz4vTjMckDVr9 Gdzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945329; x=1751550129; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=FJiMSG3aUxEuiCh3YiYxcirsWMG54X+LrVgKBYabMpk=; b=Kq9D8OOptbhGFvyGn6TWNhlrSD9Dssf4Q6l8rywJXHQLPJmNJf2RpE6aNP5C+AeSzg hqVEABnlwPEQ2XjyEIjGPiBBacuY+U3UZKHMfDgUEH8Tkuge849BwYrBbMgTlZvk3Jg6 iRthqoo+JXVSHyX55J7TKeANL5DlbCCoE+QCebv4OkVrNHAnlytYH+fzJBxvw3tL5q4y uwoNmcSHGI3i4qvr4LqjAIVqgcNHJSSWMB44A/9bTJBK1tMymJf1h/YIk7eZph1lV31J aHn+46pnEO7CL/BTf4Oe9o7yCbC4+2XD10hEcd+MOX6X5WoaCv6gWDiJ6TbyRyhVnmyS Zsqg== X-Forwarded-Encrypted: i=1; AJvYcCVWU2IB31K35Zxg66JuwK2wVHVat/J51DL6MHr1/YevPrYo/yH+Mu6IFp6BWZ9B7vxttGghQ0J1c9SDTrM=@vger.kernel.org X-Gm-Message-State: AOJu0Yw5S0GHuqil/ZprSt8hCaZqCi9BRlIoMqVXq7MgqJ4imUfCOTgs MHEEHOG4dJzvJGWvSkh+i+iVJfOII+FFBpYqIh6onEcfLrEcqzx7bHbx0HIMfPBfp/azGl23uLT oGdS+Xw== X-Google-Smtp-Source: AGHT+IG9mmxTSxxGU0VC3HuhJ6aj8RwHCW6SqPvStDoZe373+75rFbK28RVsaz7CE9N/fE9vOfu3DC3tMeo= X-Received: from wmbfs17.prod.google.com ([2002:a05:600c:3f91:b0:450:cfda:ece7]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:1914:b0:43d:172:50b1 with SMTP id 5b1f17b1804b1-45381af206cmr68815395e9.29.1750945329192; Thu, 26 Jun 2025 06:42:09 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:49 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-3-glider@google.com> Subject: [PATCH v2 02/11] kcov: apply clang-format to kcov code From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" kcov used to obey clang-format style, but somehow diverged over time. This patch applies clang-format to kernel/kcov.c and include/linux/kcov.h, no functional change. Signed-off-by: Alexander Potapenko --- Change-Id: I49c21babad831e5d134ad8a4d4adffd1f5abc1dd v2: - factor out handles_off in kcov_ioctl() for prettier formatting --- include/linux/kcov.h | 54 +++++++++++------ kernel/kcov.c | 134 ++++++++++++++++++++++--------------------- 2 files changed, 105 insertions(+), 83 deletions(-) diff --git a/include/linux/kcov.h b/include/linux/kcov.h index 75a2fb8b16c32..932b4face1005 100644 --- a/include/linux/kcov.h +++ b/include/linux/kcov.h @@ -25,20 +25,20 @@ enum kcov_mode { KCOV_MODE_REMOTE =3D 4, }; =20 -#define KCOV_IN_CTXSW (1 << 30) +#define KCOV_IN_CTXSW (1 << 30) =20 void kcov_task_init(struct task_struct *t); void kcov_task_exit(struct task_struct *t); =20 -#define kcov_prepare_switch(t) \ -do { \ - (t)->kcov_mode |=3D KCOV_IN_CTXSW; \ -} while (0) +#define kcov_prepare_switch(t) \ + do { \ + (t)->kcov_mode |=3D KCOV_IN_CTXSW; \ + } while (0) =20 -#define kcov_finish_switch(t) \ -do { \ - (t)->kcov_mode &=3D ~KCOV_IN_CTXSW; \ -} while (0) +#define kcov_finish_switch(t) \ + do { \ + (t)->kcov_mode &=3D ~KCOV_IN_CTXSW; \ + } while (0) =20 /* See Documentation/dev-tools/kcov.rst for usage details. */ void kcov_remote_start(u64 handle); @@ -119,23 +119,41 @@ void __sanitizer_cov_trace_switch(kcov_u64 val, void = *cases); =20 #else =20 -static inline void kcov_task_init(struct task_struct *t) {} -static inline void kcov_task_exit(struct task_struct *t) {} -static inline void kcov_prepare_switch(struct task_struct *t) {} -static inline void kcov_finish_switch(struct task_struct *t) {} -static inline void kcov_remote_start(u64 handle) {} -static inline void kcov_remote_stop(void) {} +static inline void kcov_task_init(struct task_struct *t) +{ +} +static inline void kcov_task_exit(struct task_struct *t) +{ +} +static inline void kcov_prepare_switch(struct task_struct *t) +{ +} +static inline void kcov_finish_switch(struct task_struct *t) +{ +} +static inline void kcov_remote_start(u64 handle) +{ +} +static inline void kcov_remote_stop(void) +{ +} static inline u64 kcov_common_handle(void) { return 0; } -static inline void kcov_remote_start_common(u64 id) {} -static inline void kcov_remote_start_usb(u64 id) {} +static inline void kcov_remote_start_common(u64 id) +{ +} +static inline void kcov_remote_start_usb(u64 id) +{ +} static inline unsigned long kcov_remote_start_usb_softirq(u64 id) { return 0; } -static inline void kcov_remote_stop_softirq(unsigned long flags) {} +static inline void kcov_remote_stop_softirq(unsigned long flags) +{ +} =20 #endif /* CONFIG_KCOV */ #endif /* _LINUX_KCOV_H */ diff --git a/kernel/kcov.c b/kernel/kcov.c index 187ba1b80bda1..0dd42b78694c9 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -4,27 +4,28 @@ #define DISABLE_BRANCH_PROFILING #include #include +#include #include #include -#include #include #include #include #include #include +#include #include +#include #include #include #include +#include #include #include #include -#include -#include +#include #include -#include -#include -#include +#include + #include =20 #define kcov_debug(fmt, ...) pr_debug("%s: " fmt, __func__, ##__VA_ARGS__) @@ -52,36 +53,36 @@ struct kcov { * - task with enabled coverage (we can't unwire it from another task) * - each code section for remote coverage collection */ - refcount_t refcount; + refcount_t refcount; /* The lock protects mode, size, area and t. */ - spinlock_t lock; - enum kcov_mode mode; + spinlock_t lock; + enum kcov_mode mode; /* Size of arena (in long's). */ - unsigned int size; + unsigned int size; /* Coverage buffer shared with user space. */ - void *area; + void *area; /* Task for which we collect coverage, or NULL. */ - struct task_struct *t; + struct task_struct *t; /* Collecting coverage from remote (background) threads. */ - bool remote; + bool remote; /* Size of remote area (in long's). */ - unsigned int remote_size; + unsigned int remote_size; /* * Sequence is incremented each time kcov is reenabled, used by * kcov_remote_stop(), see the comment there. */ - int sequence; + int sequence; }; =20 struct kcov_remote_area { - struct list_head list; - unsigned int size; + struct list_head list; + unsigned int size; }; =20 struct kcov_remote { - u64 handle; - struct kcov *kcov; - struct hlist_node hnode; + u64 handle; + struct kcov *kcov; + struct hlist_node hnode; }; =20 static DEFINE_SPINLOCK(kcov_remote_lock); @@ -89,14 +90,14 @@ static DEFINE_HASHTABLE(kcov_remote_map, 4); static struct list_head kcov_remote_areas =3D LIST_HEAD_INIT(kcov_remote_a= reas); =20 struct kcov_percpu_data { - void *irq_area; - local_lock_t lock; - - unsigned int saved_mode; - unsigned int saved_size; - void *saved_area; - struct kcov *saved_kcov; - int saved_sequence; + void *irq_area; + local_lock_t lock; + + unsigned int saved_mode; + unsigned int saved_size; + void *saved_area; + struct kcov *saved_kcov; + int saved_sequence; }; =20 static DEFINE_PER_CPU(struct kcov_percpu_data, kcov_percpu_data) =3D { @@ -149,7 +150,7 @@ static struct kcov_remote_area *kcov_remote_area_get(un= signed int size) =20 /* Must be called with kcov_remote_lock locked. */ static void kcov_remote_area_put(struct kcov_remote_area *area, - unsigned int size) + unsigned int size) { INIT_LIST_HEAD(&area->list); area->size =3D size; @@ -171,7 +172,8 @@ static __always_inline bool in_softirq_really(void) return in_serving_softirq() && !in_hardirq() && !in_nmi(); } =20 -static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct tas= k_struct *t) +static notrace bool check_kcov_mode(enum kcov_mode needed_mode, + struct task_struct *t) { unsigned int mode; =20 @@ -354,8 +356,8 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_switch); #endif /* ifdef CONFIG_KCOV_ENABLE_COMPARISONS */ =20 static void kcov_start(struct task_struct *t, struct kcov *kcov, - unsigned int size, void *area, enum kcov_mode mode, - int sequence) + unsigned int size, void *area, enum kcov_mode mode, + int sequence) { kcov_debug("t =3D %px, size =3D %u, area =3D %px\n", t, size, area); t->kcov =3D kcov; @@ -566,14 +568,14 @@ static void kcov_fault_in_area(struct kcov *kcov) } =20 static inline bool kcov_check_handle(u64 handle, bool common_valid, - bool uncommon_valid, bool zero_valid) + bool uncommon_valid, bool zero_valid) { if (handle & ~(KCOV_SUBSYSTEM_MASK | KCOV_INSTANCE_MASK)) return false; switch (handle & KCOV_SUBSYSTEM_MASK) { case KCOV_SUBSYSTEM_COMMON: - return (handle & KCOV_INSTANCE_MASK) ? - common_valid : zero_valid; + return (handle & KCOV_INSTANCE_MASK) ? common_valid : + zero_valid; case KCOV_SUBSYSTEM_USB: return uncommon_valid; default: @@ -611,7 +613,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, kcov_fault_in_area(kcov); kcov->mode =3D mode; kcov_start(t, kcov, kcov->size, kcov->area, kcov->mode, - kcov->sequence); + kcov->sequence); kcov->t =3D t; /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); @@ -642,40 +644,40 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsig= ned int cmd, return -EINVAL; kcov->mode =3D mode; t->kcov =3D kcov; - t->kcov_mode =3D KCOV_MODE_REMOTE; + t->kcov_mode =3D KCOV_MODE_REMOTE; kcov->t =3D t; kcov->remote =3D true; kcov->remote_size =3D remote_arg->area_size; spin_lock_irqsave(&kcov_remote_lock, flags); for (i =3D 0; i < remote_arg->num_handles; i++) { - if (!kcov_check_handle(remote_arg->handles[i], - false, true, false)) { + if (!kcov_check_handle(remote_arg->handles[i], false, + true, false)) { spin_unlock_irqrestore(&kcov_remote_lock, - flags); + flags); kcov_disable(t, kcov); return -EINVAL; } remote =3D kcov_remote_add(kcov, remote_arg->handles[i]); if (IS_ERR(remote)) { spin_unlock_irqrestore(&kcov_remote_lock, - flags); + flags); kcov_disable(t, kcov); return PTR_ERR(remote); } } if (remote_arg->common_handle) { - if (!kcov_check_handle(remote_arg->common_handle, - true, false, false)) { + if (!kcov_check_handle(remote_arg->common_handle, true, + false, false)) { spin_unlock_irqrestore(&kcov_remote_lock, - flags); + flags); kcov_disable(t, kcov); return -EINVAL; } remote =3D kcov_remote_add(kcov, - remote_arg->common_handle); + remote_arg->common_handle); if (IS_ERR(remote)) { spin_unlock_irqrestore(&kcov_remote_lock, - flags); + flags); kcov_disable(t, kcov); return PTR_ERR(remote); } @@ -698,6 +700,7 @@ static long kcov_ioctl(struct file *filep, unsigned int= cmd, unsigned long arg) unsigned int remote_num_handles; unsigned long remote_arg_size; unsigned long size, flags; + size_t handles_off; void *area; =20 kcov =3D filep->private_data; @@ -728,13 +731,14 @@ static long kcov_ioctl(struct file *filep, unsigned i= nt cmd, unsigned long arg) spin_unlock_irqrestore(&kcov->lock, flags); return 0; case KCOV_REMOTE_ENABLE: - if (get_user(remote_num_handles, (unsigned __user *)(arg + - offsetof(struct kcov_remote_arg, num_handles)))) + handles_off =3D offsetof(struct kcov_remote_arg, num_handles); + if (get_user(remote_num_handles, + (unsigned __user *)(arg + handles_off))) return -EFAULT; if (remote_num_handles > KCOV_REMOTE_MAX_HANDLES) return -EINVAL; - remote_arg_size =3D struct_size(remote_arg, handles, - remote_num_handles); + remote_arg_size =3D + struct_size(remote_arg, handles, remote_num_handles); remote_arg =3D memdup_user((void __user *)arg, remote_arg_size); if (IS_ERR(remote_arg)) return PTR_ERR(remote_arg); @@ -758,11 +762,11 @@ static long kcov_ioctl(struct file *filep, unsigned i= nt cmd, unsigned long arg) } =20 static const struct file_operations kcov_fops =3D { - .open =3D kcov_open, - .unlocked_ioctl =3D kcov_ioctl, - .compat_ioctl =3D kcov_ioctl, - .mmap =3D kcov_mmap, - .release =3D kcov_close, + .open =3D kcov_open, + .unlocked_ioctl =3D kcov_ioctl, + .compat_ioctl =3D kcov_ioctl, + .mmap =3D kcov_mmap, + .release =3D kcov_close, }; =20 /* @@ -836,8 +840,8 @@ static void kcov_remote_softirq_stop(struct task_struct= *t) =20 if (data->saved_kcov) { kcov_start(t, data->saved_kcov, data->saved_size, - data->saved_area, data->saved_mode, - data->saved_sequence); + data->saved_area, data->saved_mode, + data->saved_sequence); data->saved_mode =3D 0; data->saved_size =3D 0; data->saved_area =3D NULL; @@ -891,7 +895,7 @@ void kcov_remote_start(u64 handle) return; } kcov_debug("handle =3D %llx, context: %s\n", handle, - in_task() ? "task" : "softirq"); + in_task() ? "task" : "softirq"); kcov =3D remote->kcov; /* Put in kcov_remote_stop(). */ kcov_get(kcov); @@ -931,12 +935,11 @@ void kcov_remote_start(u64 handle) kcov_start(t, kcov, size, area, mode, sequence); =20 local_unlock_irqrestore(&kcov_percpu_data.lock, flags); - } EXPORT_SYMBOL(kcov_remote_start); =20 static void kcov_move_area(enum kcov_mode mode, void *dst_area, - unsigned int dst_area_size, void *src_area) + unsigned int dst_area_size, void *src_area) { u64 word_size =3D sizeof(unsigned long); u64 count_size, entry_size_log; @@ -944,8 +947,8 @@ static void kcov_move_area(enum kcov_mode mode, void *d= st_area, void *dst_entries, *src_entries; u64 dst_occupied, dst_free, bytes_to_move, entries_moved; =20 - kcov_debug("%px %u <=3D %px %lu\n", - dst_area, dst_area_size, src_area, *(unsigned long *)src_area); + kcov_debug("%px %u <=3D %px %lu\n", dst_area, dst_area_size, src_area, + *(unsigned long *)src_area); =20 switch (mode) { case KCOV_MODE_TRACE_PC: @@ -967,8 +970,8 @@ static void kcov_move_area(enum kcov_mode mode, void *d= st_area, } =20 /* As arm can't divide u64 integers use log of entry size. */ - if (dst_len > ((dst_area_size * word_size - count_size) >> - entry_size_log)) + if (dst_len > + ((dst_area_size * word_size - count_size) >> entry_size_log)) return; dst_occupied =3D count_size + (dst_len << entry_size_log); dst_free =3D dst_area_size * word_size - dst_occupied; @@ -1100,7 +1103,8 @@ static int __init kcov_init(void) =20 for_each_possible_cpu(cpu) { void *area =3D vmalloc_node(CONFIG_KCOV_IRQ_AREA_SIZE * - sizeof(unsigned long), cpu_to_node(cpu)); + sizeof(unsigned long), + cpu_to_node(cpu)); if (!area) return -ENOMEM; per_cpu_ptr(&kcov_percpu_data, cpu)->irq_area =3D area; --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8DD352E7187 for ; Thu, 26 Jun 2025 13:42:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945335; cv=none; b=deL3dQjOgH1jm0AbZinqmRcDiG66hy2n64rU0NMEIeESzU8/hDkX1bUNKpR72ZK93GrGNQOpgABioypYEEpAQxeo0mfyTPTclPBnFn/oCeMiwAmHwvwBSIxVY1kptzsJUsMgPoRPkfqit8Gsynv0P6jf9JED2fBgltM1DUTmrog= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945335; c=relaxed/simple; bh=PvyE1JdQBnLBc+VJ48KLaBuARDtzc9BomVMqIozi8gc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Z4IPAEyAMQooD695upjLA7KpcT6I5S9uj63WRTdBn3KAa4SqoIHjzUfwXWY23rKksSjRwaGONyYgOt891RXYEp62KvedQ8I54pK9WW1g7ejaak3ELiunV19HE0/g08b3kWcjrTNtT4/zuEcYE7RqI9DbHWLrsyDO+CeeqCrokDY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nONcUsTH; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nONcUsTH" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-3a4fabcafecso529783f8f.0 for ; Thu, 26 Jun 2025 06:42:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945332; x=1751550132; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=H2gpzKqZL1lxRtkvI/RoX8Rqd5NtVf1Q/oJAS1UNweg=; b=nONcUsTHX1RY9pQwBy2gOMwHaz0qIiWF1TkCmxGnUfk03W7YegS00UZmd6mloGfAnd vNdP537fhnEXOATfCjuUFCsaZAkWz7C2iynFye+K3Bgq5v4Xi+PqQv70uijzA/cCzBzo tBO9RUUdVeYB5ZBn5sCzWi22SjH3zPtjQJPGybmKnoOwCjcnY/J9PTbnAoUjAqxwSc7Y E6btl+DETGuTU4NT8bo4AogzpCYUdukIcmg7Lnn4A3S3/Yjt57EvS+VAuxIeQKeseRjt Txjg+PZfDD7tSNnY/molgcqOvJOuiKW3kP99mQ4HaPo7YFJ21eIKTMKL9AmFdelBFE+J eKhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945332; x=1751550132; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=H2gpzKqZL1lxRtkvI/RoX8Rqd5NtVf1Q/oJAS1UNweg=; b=q24B23aNLKDq6OYh2wsW5hEvzxaKsLBRNoobfS1+wLIuWz+rUYuJDbKqLvrDKeSVPy EqHuYZtsrM0U1J2UJkOSpmiboNXUYPOI2OSHiv/h83qHDq4LVciOeQ+mj+8yeXIKRzu7 hosLPZtaxyrvn/KyX4Yxjw8OVyIU9qxfJKPgSTNcZ/DDJw3N21fpQf18GrAjt/FrtG+J +fmi3fqD/3MK7WaNIsq3CUzcO6eNuCF93aLIDUhbb0IDS2aLyrGs1OzxwTM+omPSzw6J iqCxxHJ3a6MsNz6pIoHG0ERzWtn4+0cUgnKyNXtpqe9RTFTUTKOKHMR+g8vCAn5AtGtS lVng== X-Forwarded-Encrypted: i=1; AJvYcCVIz0WIgTeDsZ6wchPU+Je23auwGrbm73QNI+6p6fdbdBK8+6Cc0K/8GOU0trQ6iL/YgGk/lSnNby21UJw=@vger.kernel.org X-Gm-Message-State: AOJu0YwWU05OMxVHEGDXfxgGppSEdcvwYKAsJOnVIbDQdwiD69QEuTXt D7ZsjqEGsqEP6tN10NE42dwC3ZYUHA27ciiQ9W0Oa+cMs64fdB7+cqv0g96h/BTe7qJeomVQuUN dbncopw== X-Google-Smtp-Source: AGHT+IHOpP7+XElh9h0a7yzDlbl+mIW4gb/1D/GB9XeXT/yGolnUvCQhMsQ75cHNc2+ZUOdmZWmTT7Nff24= X-Received: from wrae8.prod.google.com ([2002:adf:a448:0:b0:3a5:7c42:1583]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:3103:b0:3a4:f7ae:77e8 with SMTP id ffacd0b85a97d-3a6f2e8e297mr3438599f8f.15.1750945331958; Thu, 26 Jun 2025 06:42:11 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:50 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-4-glider@google.com> Subject: [PATCH v2 03/11] kcov: elaborate on using the shared buffer From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a paragraph about the shared buffer usage to kcov.rst. Signed-off-by: Alexander Potapenko Reviewed-by: Dmitry Vyukov --- Change-Id: Ia47ef7c3fcc74789fe57a6e1d93e29a42dbc0a97 --- Documentation/dev-tools/kcov.rst | 55 ++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kco= v.rst index 6611434e2dd24..abf3ad2e784e8 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst @@ -137,6 +137,61 @@ mmaps coverage buffer, and then forks child processes = in a loop. The child processes only need to enable coverage (it gets disabled automatically when a thread exits). =20 +Shared buffer for coverage collection +------------------------------------- +KCOV employs a shared memory buffer as a central mechanism for efficient a= nd +direct transfer of code coverage information between the kernel and usersp= ace +applications. + +Calling ``ioctl(fd, KCOV_INIT_TRACE, size)`` initializes coverage collecti= on for +the current thread associated with the file descriptor ``fd``. The buffer +allocated will hold ``size`` unsigned long values, as interpreted by the k= ernel. +Notably, even in a 32-bit userspace program on a 64-bit kernel, each entry= will +occupy 64 bits. + +Following initialization, the actual shared memory buffer is created using= :: + + mmap(NULL, size * sizeof(unsigned long), PROT_READ | PROT_WRITE, MAP_S= HARED, fd, 0) + +The size of this memory mapping, calculated as ``size * sizeof(unsigned lo= ng)``, +must be a multiple of ``PAGE_SIZE``. + +This buffer is then shared between the kernel and the userspace. The first +element of the buffer contains the number of PCs stored in it. +Both the userspace and the kernel may write to the shared buffer, so to av= oid +race conditions each userspace thread should only update its own buffer. + +Normally the shared buffer is used as follows:: + + Userspace Kernel + -----------------------------------------+----------------------------= --------------- + ioctl(fd, KCOV_INIT_TRACE, size) | + | Initialize coverage for = current thread + mmap(..., MAP_SHARED, fd, 0) | + | Allocate the buffer, ini= tialize it + | with zeroes + ioctl(fd, KCOV_ENABLE, KCOV_TRACE_PC) | + | Enable PC collection for= current thread + | starting at buffer[1] (K= COV_ENABLE will + | already write some cover= age) + Atomically write 0 to buffer[0] to | + reset the coverage | + | + Execute some syscall(s) | + | Write new coverage start= ing at + | buffer[1] + Atomically read buffer[0] to get the | + total coverage size at this point in | + time | + | + ioctl(fd, KCOV_DISABLE, 0) | + | Write some more coverage= for ioctl(), + | then disable PC collecti= on for current + | thread + Safely read and process the coverage | + up to the buffer[0] value saved above | + + Comparison operands collection ------------------------------ =20 --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1623D2E7F24 for ; Thu, 26 Jun 2025 13:42:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945338; cv=none; b=jb/3s2dQ0ABv/IYAn1E9YMYJvQevWxfMkQW8jEkaG3QKCdgXGVNBS0Nsy4H77znMe1sdPJYfHLpenyDaLEkkCWDZ6lTDPDBe4u0Fhv89rN3VCLeCggcKxUYHGc+6C0xBq3dtcisDM3RCqjA3C5EowTXtzFGf7gpEmF6CSAWGX54= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945338; c=relaxed/simple; bh=IqRxoPSzc+OciRbcuYYGBNRHFEFkXus7obixCxTkDNY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oo7Zk4enwDmh6xYCu7WZUcP0YCf4MALBwonEGeLRBZofH//AL4VD6b9QtNHJ9Obcn0CljwP1Xu3ML8T83sjnay5tgXhTJykexuO4rl9gUtT+E9E7s9gKJfkBzcBRz0oMqKxuDDsa/JV6A5tdK5+fRvrktTyTzHTnzkLkDjTdzRc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=g5CGKLr+; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="g5CGKLr+" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-3a3696a0d3aso442110f8f.2 for ; Thu, 26 Jun 2025 06:42:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945334; x=1751550134; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Y9JptD8OjEc0dymN3Sn1kMVYGpGedrlrt38g4yTKhTU=; b=g5CGKLr+StoIpsOEX9vugl7BEZ8kwnFAbK2h4SGWxKUYLxF91DCAds+8Q5etdaBs+D bbFCBmaTNfMJo4c1bf+d8JdRVMiFWHvqYgHjOnNhlOIoTZgSYaz53ysOtN6l9AB5rXWR MKhR3QK6vaBXgR+vZJqpi+pSQTXuOi0h4e3NiDytDn3/Xd/CX67XLY7C0GMBa4Jdy9UZ ONsJuzLKtT0dbw6zrCBy/xJbINRTFUQ4O40TyhP+jQOSmMabcZCM5v0LlaLBHpmYhzsi urmMqK55Iwks8uiiwJp7bnV5ZglMABgVOXrboAqiFkTjFeEMzFV80bYKecRbEUMRW8Km Vqig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945334; x=1751550134; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Y9JptD8OjEc0dymN3Sn1kMVYGpGedrlrt38g4yTKhTU=; b=T8h9lTcCP+9wKwtShmQjyif5FCet2rLOzZUMF5wRbYUuZd+hfT5ZaunIBmn/cHZszU o+uR+MFl+kd62BxN7c18I/LWK7JZYLkIOVWmqsjewZimbWsXj34VHWjD95+lStRvpTfk FkeN3kPk/SkZqT7HB/5u4dOO9Hf6qECe7jKQvtiYbIRwIe+SmyUGHh+uy/4I+WHaOAy8 /Dj9rScUCiJB2SHXEp9YdfV8507SjDZR3fuKFseasTVNpHQuQVE4B4qIId8LLs7PfK4e lWTaTbYB0zW9kQ2KjrVAtl1LnlNn7NAF4bG3mdgk93C9dFENF/7hg//lV7Sw5HibHUvP 0s2A== X-Forwarded-Encrypted: i=1; AJvYcCVieAmGFTIK5Gqur8tAKrebbwF4DCGpOOK0IYv/TUGcEPKC1XjeOgtfRhbgIuEXasuIy+/OCGIfHdFOhKU=@vger.kernel.org X-Gm-Message-State: AOJu0YyW58DYyWdEsGmr1uNAbs5WlaHYoX7p/R9THTN4F0xlHXL3n99L pbXR79QBXD6GBw5BYHkQOLSSv3QvwSsPSCLTyHPFqfVaZumAj+o/0hF2Eb4AU1qpvImsoq8kS2D Oz98g2A== X-Google-Smtp-Source: AGHT+IGi3AChiiVQLB+PVCwJhxZrg5Dx2cB/Vg5qmRGcTtykgEnBDzWPmNw/C5nvicSc/BZ8ojT1bJ4nbes= X-Received: from wmsr19.prod.google.com ([2002:a05:600c:8b13:b0:442:ddf8:99dc]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:4614:b0:3a5:276b:1ec0 with SMTP id ffacd0b85a97d-3a6ed65b1d4mr6390427f8f.45.1750945334487; Thu, 26 Jun 2025 06:42:14 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:51 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-5-glider@google.com> Subject: [PATCH v2 04/11] kcov: factor out struct kcov_state From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Group several kcov-related fields (area, size, sequence) that are stored in various structures, into `struct kcov_state`, so that these fields can be easily passed around and manipulated. Note that now the spinlock in struct kcov applies to every member of struct kcov_state, including the sequence number. This prepares us for the upcoming change that will introduce more kcov state. Also update the MAINTAINERS entry: add include/linux/kcov_types..h, add myself as kcov reviewer. Signed-off-by: Alexander Potapenko --- Change-Id: If225682ea2f6e91245381b3270de16e7ea40df39 v2: - add myself to kcov MAINTAINERS - rename kcov-state.h to kcov_types.h - update the description - do not move mode into struct kcov_state - use '{ }' instead of '{ 0 }' --- MAINTAINERS | 2 + include/linux/kcov.h | 2 +- include/linux/kcov_types.h | 22 +++++++ include/linux/sched.h | 13 +---- kernel/kcov.c | 115 ++++++++++++++++--------------------- 5 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 include/linux/kcov_types.h diff --git a/MAINTAINERS b/MAINTAINERS index dd844ac8d9107..5bbc78b0fa6ed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12823,11 +12823,13 @@ F: include/linux/kcore.h KCOV R: Dmitry Vyukov R: Andrey Konovalov +R: Alexander Potapenko L: kasan-dev@googlegroups.com S: Maintained B: https://bugzilla.kernel.org/buglist.cgi?component=3DSanitizers&product= =3DMemory%20Management F: Documentation/dev-tools/kcov.rst F: include/linux/kcov.h +F: include/linux/kcov_types.h F: include/uapi/linux/kcov.h F: kernel/kcov.c F: scripts/Makefile.kcov diff --git a/include/linux/kcov.h b/include/linux/kcov.h index 932b4face1005..0e425c3524b86 100644 --- a/include/linux/kcov.h +++ b/include/linux/kcov.h @@ -2,7 +2,7 @@ #ifndef _LINUX_KCOV_H #define _LINUX_KCOV_H =20 -#include +#include #include =20 struct task_struct; diff --git a/include/linux/kcov_types.h b/include/linux/kcov_types.h new file mode 100644 index 0000000000000..53b25b6f0addd --- /dev/null +++ b/include/linux/kcov_types.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_KCOV_STATE_H +#define _LINUX_KCOV_STATE_H + +#ifdef CONFIG_KCOV +/* See kernel/kcov.c for more details. */ +struct kcov_state { + /* Size of the area (in long's). */ + unsigned int size; + + /* Buffer for coverage collection, shared with the userspace. */ + void *area; + + /* + * KCOV sequence number: incremented each time kcov is reenabled, used + * by kcov_remote_stop(), see the comment there. + */ + int sequence; +}; +#endif /* CONFIG_KCOV */ + +#endif /* _LINUX_KCOV_STATE_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index f96ac19828934..68af8d6eaee3a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1512,16 +1513,11 @@ struct task_struct { #endif /* CONFIG_TRACING */ =20 #ifdef CONFIG_KCOV - /* See kernel/kcov.c for more details. */ - /* Coverage collection mode enabled for this task (0 if disabled): */ unsigned int kcov_mode; =20 - /* Size of the kcov_area: */ - unsigned int kcov_size; - - /* Buffer for coverage collection: */ - void *kcov_area; + /* kcov buffer state for this task. */ + struct kcov_state kcov_state; =20 /* KCOV descriptor wired with this task or NULL: */ struct kcov *kcov; @@ -1529,9 +1525,6 @@ struct task_struct { /* KCOV common handle for remote coverage collection: */ u64 kcov_handle; =20 - /* KCOV sequence number: */ - int kcov_sequence; - /* Collect coverage from softirq context: */ unsigned int kcov_softirq; #endif diff --git a/kernel/kcov.c b/kernel/kcov.c index 0dd42b78694c9..ff7f118644f49 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -54,24 +55,17 @@ struct kcov { * - each code section for remote coverage collection */ refcount_t refcount; - /* The lock protects mode, size, area and t. */ + /* The lock protects state and t. */ spinlock_t lock; enum kcov_mode mode; - /* Size of arena (in long's). */ - unsigned int size; - /* Coverage buffer shared with user space. */ - void *area; + struct kcov_state state; + /* Task for which we collect coverage, or NULL. */ struct task_struct *t; /* Collecting coverage from remote (background) threads. */ bool remote; /* Size of remote area (in long's). */ unsigned int remote_size; - /* - * Sequence is incremented each time kcov is reenabled, used by - * kcov_remote_stop(), see the comment there. - */ - int sequence; }; =20 struct kcov_remote_area { @@ -92,12 +86,9 @@ static struct list_head kcov_remote_areas =3D LIST_HEAD_= INIT(kcov_remote_areas); struct kcov_percpu_data { void *irq_area; local_lock_t lock; - - unsigned int saved_mode; - unsigned int saved_size; - void *saved_area; + enum kcov_mode saved_mode; struct kcov *saved_kcov; - int saved_sequence; + struct kcov_state saved_state; }; =20 static DEFINE_PER_CPU(struct kcov_percpu_data, kcov_percpu_data) =3D { @@ -219,10 +210,10 @@ void notrace __sanitizer_cov_trace_pc(void) if (!check_kcov_mode(KCOV_MODE_TRACE_PC, t)) return; =20 - area =3D t->kcov_area; + area =3D t->kcov_state.area; /* The first 64-bit word is the number of subsequent PCs. */ pos =3D READ_ONCE(area[0]) + 1; - if (likely(pos < t->kcov_size)) { + if (likely(pos < t->kcov_state.size)) { /* Previously we write pc before updating pos. However, some * early interrupt code could bypass check_kcov_mode() check * and invoke __sanitizer_cov_trace_pc(). If such interrupt is @@ -252,10 +243,10 @@ static void notrace write_comp_data(u64 type, u64 arg= 1, u64 arg2, u64 ip) =20 /* * We write all comparison arguments and types as u64. - * The buffer was allocated for t->kcov_size unsigned longs. + * The buffer was allocated for t->kcov_state.size unsigned longs. */ - area =3D (u64 *)t->kcov_area; - max_pos =3D t->kcov_size * sizeof(unsigned long); + area =3D (u64 *)t->kcov_state.area; + max_pos =3D t->kcov_state.size * sizeof(unsigned long); =20 count =3D READ_ONCE(area[0]); =20 @@ -356,17 +347,15 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_switch); #endif /* ifdef CONFIG_KCOV_ENABLE_COMPARISONS */ =20 static void kcov_start(struct task_struct *t, struct kcov *kcov, - unsigned int size, void *area, enum kcov_mode mode, - int sequence) + enum kcov_mode mode, struct kcov_state *state) { - kcov_debug("t =3D %px, size =3D %u, area =3D %px\n", t, size, area); + kcov_debug("t =3D %px, size =3D %u, area =3D %px\n", t, state->size, + state->area); t->kcov =3D kcov; /* Cache in task struct for performance. */ - t->kcov_size =3D size; - t->kcov_area =3D area; - t->kcov_sequence =3D sequence; - /* See comment in check_kcov_mode(). */ + t->kcov_state =3D *state; barrier(); + /* See comment in check_kcov_mode(). */ WRITE_ONCE(t->kcov_mode, mode); } =20 @@ -375,14 +364,14 @@ static void kcov_stop(struct task_struct *t) WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED); barrier(); t->kcov =3D NULL; - t->kcov_size =3D 0; - t->kcov_area =3D NULL; + t->kcov_state.size =3D 0; + t->kcov_state.area =3D NULL; } =20 static void kcov_task_reset(struct task_struct *t) { kcov_stop(t); - t->kcov_sequence =3D 0; + t->kcov_state.sequence =3D 0; t->kcov_handle =3D 0; } =20 @@ -398,7 +387,7 @@ static void kcov_reset(struct kcov *kcov) kcov->mode =3D KCOV_MODE_INIT; kcov->remote =3D false; kcov->remote_size =3D 0; - kcov->sequence++; + kcov->state.sequence++; } =20 static void kcov_remote_reset(struct kcov *kcov) @@ -438,7 +427,7 @@ static void kcov_put(struct kcov *kcov) { if (refcount_dec_and_test(&kcov->refcount)) { kcov_remote_reset(kcov); - vfree(kcov->area); + vfree(kcov->state.area); kfree(kcov); } } @@ -495,8 +484,8 @@ static int kcov_mmap(struct file *filep, struct vm_area= _struct *vma) unsigned long flags; =20 spin_lock_irqsave(&kcov->lock, flags); - size =3D kcov->size * sizeof(unsigned long); - if (kcov->area =3D=3D NULL || vma->vm_pgoff !=3D 0 || + size =3D kcov->state.size * sizeof(unsigned long); + if (kcov->state.area =3D=3D NULL || vma->vm_pgoff !=3D 0 || vma->vm_end - vma->vm_start !=3D size) { res =3D -EINVAL; goto exit; @@ -504,7 +493,7 @@ static int kcov_mmap(struct file *filep, struct vm_area= _struct *vma) spin_unlock_irqrestore(&kcov->lock, flags); vm_flags_set(vma, VM_DONTEXPAND); for (off =3D 0; off < size; off +=3D PAGE_SIZE) { - page =3D vmalloc_to_page(kcov->area + off); + page =3D vmalloc_to_page(kcov->state.area + off); res =3D vm_insert_page(vma, vma->vm_start + off, page); if (res) { pr_warn_once("kcov: vm_insert_page() failed\n"); @@ -525,7 +514,7 @@ static int kcov_open(struct inode *inode, struct file *= filep) if (!kcov) return -ENOMEM; kcov->mode =3D KCOV_MODE_DISABLED; - kcov->sequence =3D 1; + kcov->state.sequence =3D 1; refcount_set(&kcov->refcount, 1); spin_lock_init(&kcov->lock); filep->private_data =3D kcov; @@ -560,10 +549,10 @@ static int kcov_get_mode(unsigned long arg) static void kcov_fault_in_area(struct kcov *kcov) { unsigned long stride =3D PAGE_SIZE / sizeof(unsigned long); - unsigned long *area =3D kcov->area; + unsigned long *area =3D kcov->state.area; unsigned long offset; =20 - for (offset =3D 0; offset < kcov->size; offset +=3D stride) + for (offset =3D 0; offset < kcov->state.size; offset +=3D stride) READ_ONCE(area[offset]); } =20 @@ -602,7 +591,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, * at task exit or voluntary by KCOV_DISABLE. After that it can * be enabled for another task. */ - if (kcov->mode !=3D KCOV_MODE_INIT || !kcov->area) + if (kcov->mode !=3D KCOV_MODE_INIT || !kcov->state.area) return -EINVAL; t =3D current; if (kcov->t !=3D NULL || t->kcov !=3D NULL) @@ -612,8 +601,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, return mode; kcov_fault_in_area(kcov); kcov->mode =3D mode; - kcov_start(t, kcov, kcov->size, kcov->area, kcov->mode, - kcov->sequence); + kcov_start(t, kcov, mode, &kcov->state); kcov->t =3D t; /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); @@ -630,7 +618,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, kcov_put(kcov); return 0; case KCOV_REMOTE_ENABLE: - if (kcov->mode !=3D KCOV_MODE_INIT || !kcov->area) + if (kcov->mode !=3D KCOV_MODE_INIT || !kcov->state.area) return -EINVAL; t =3D current; if (kcov->t !=3D NULL || t->kcov !=3D NULL) @@ -725,8 +713,8 @@ static long kcov_ioctl(struct file *filep, unsigned int= cmd, unsigned long arg) vfree(area); return -EBUSY; } - kcov->area =3D area; - kcov->size =3D size; + kcov->state.area =3D area; + kcov->state.size =3D size; kcov->mode =3D KCOV_MODE_INIT; spin_unlock_irqrestore(&kcov->lock, flags); return 0; @@ -825,10 +813,8 @@ static void kcov_remote_softirq_start(struct task_stru= ct *t) mode =3D READ_ONCE(t->kcov_mode); barrier(); if (kcov_mode_enabled(mode)) { + data->saved_state =3D t->kcov_state; data->saved_mode =3D mode; - data->saved_size =3D t->kcov_size; - data->saved_area =3D t->kcov_area; - data->saved_sequence =3D t->kcov_sequence; data->saved_kcov =3D t->kcov; kcov_stop(t); } @@ -839,13 +825,9 @@ static void kcov_remote_softirq_stop(struct task_struc= t *t) struct kcov_percpu_data *data =3D this_cpu_ptr(&kcov_percpu_data); =20 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 =3D 0; - data->saved_size =3D 0; - data->saved_area =3D NULL; - data->saved_sequence =3D 0; + kcov_start(t, data->saved_kcov, t->kcov_mode, + &data->saved_state); + data->saved_state =3D (struct kcov_state){}; data->saved_kcov =3D NULL; } } @@ -854,12 +836,12 @@ void kcov_remote_start(u64 handle) { struct task_struct *t =3D current; struct kcov_remote *remote; + struct kcov_state state; + enum kcov_mode mode; + unsigned long flags; + unsigned int size; struct kcov *kcov; - unsigned int mode; void *area; - unsigned int size; - int sequence; - unsigned long flags; =20 if (WARN_ON(!kcov_check_handle(handle, true, true, true))) return; @@ -904,7 +886,7 @@ void kcov_remote_start(u64 handle) * KCOV_DISABLE / kcov_remote_reset(). */ mode =3D kcov->mode; - sequence =3D kcov->sequence; + state.sequence =3D kcov->state.sequence; if (in_task()) { size =3D kcov->remote_size; area =3D kcov_remote_area_get(size); @@ -927,12 +909,14 @@ void kcov_remote_start(u64 handle) =20 /* Reset coverage size. */ *(u64 *)area =3D 0; + state.area =3D area; + state.size =3D size; =20 if (in_serving_softirq()) { kcov_remote_softirq_start(t); t->kcov_softirq =3D 1; } - kcov_start(t, kcov, size, area, mode, sequence); + kcov_start(t, kcov, t->kcov_mode, &state); =20 local_unlock_irqrestore(&kcov_percpu_data.lock, flags); } @@ -1030,9 +1014,9 @@ void kcov_remote_stop(void) } =20 kcov =3D t->kcov; - area =3D t->kcov_area; - size =3D t->kcov_size; - sequence =3D t->kcov_sequence; + area =3D t->kcov_state.area; + size =3D t->kcov_state.size; + sequence =3D t->kcov_state.sequence; =20 kcov_stop(t); if (in_serving_softirq()) { @@ -1045,8 +1029,9 @@ void kcov_remote_stop(void) * KCOV_DISABLE could have been called between kcov_remote_start() * and kcov_remote_stop(), hence the sequence check. */ - if (sequence =3D=3D kcov->sequence && kcov->remote) - kcov_move_area(kcov->mode, kcov->area, kcov->size, area); + if (sequence =3D=3D kcov->state.sequence && kcov->remote) + kcov_move_area(kcov->mode, kcov->state.area, kcov->state.size, + area); spin_unlock(&kcov->lock); =20 if (in_task()) { --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 87BE42E8899 for ; Thu, 26 Jun 2025 13:42:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945340; cv=none; b=ci9p1Fzu+DEP9O49VY7QeaK4k5uWK3r5ei8KTN7dm3uUtYyjONX5XPxCX3jPITbLQzqWVp89SuWiauu6aC9pVxseuQ7D6pq/fdNQY6L54kcMGwYqfb0nVsivoZH4domDVilNeSahA03JDyfaxyDOIoqjxE0DE3p1+mWFDExs90g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945340; c=relaxed/simple; bh=mt8bJyeWFEW+LLAMGTsAP+PR8cBkskNLXeDWMRtOIgU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=IXeAvL2nyyfw9ZYA4Pxw/f9uB3GeJDaX2FKJ7j3Qt8s2pePdbsHTGMWh4qpitQVK2wyz1hqgCbRs5II3Pzi3lDO/9eZ5Hx2ADtle0C4WR9godW6tUQ1k0/wThtkcNqy6B9FjQBj7s9wl5RLx2B2DXhego2yafI0kYujXMbL4IHU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=T0OC/eW8; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="T0OC/eW8" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-450db029f2aso4321435e9.3 for ; Thu, 26 Jun 2025 06:42:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945337; x=1751550137; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=48paaS1qVo9hnWK9htYJQbyGTvWCJegAFjsjDLyyhLA=; b=T0OC/eW8QPU++kWssJQknfkiosSszpaAdtdec7ApHinbun7QulpnjlPl2tGuPgvy4a bbotXxGjYTN+03gFPvnXbEXWZ61qbl4V/Kn6efKFrwzdc8aR1T/MJffcI4bItGQ1RcbT 5Gr8vvyLGhMeKGRZehczIqHAHh+5fhnysc0q/AL7xDGsHhfrpNDXZcxIMU9BuS0jrcwX UvWUCje6cQPFV6S41XNlbCTPjXMeAItoBKGJtCP0buKgc36BHhRPYauAiwOgPjAox29b /hAOCpKIsmAkQhsQrTX4+hQx4JvPbB3Tya6O1kiC9baTcHdRVRT0BLTyjNnqWS4T5aeA Pvog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945337; x=1751550137; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=48paaS1qVo9hnWK9htYJQbyGTvWCJegAFjsjDLyyhLA=; b=oVMOUivnso0dLGPQcplmkqaYxLvk+p8jagTSIhDnI0PkabIC5pqEtaspnZjvXIULCb Kpi8opAtqU6YqoKdFus0GVxDsOn8KJ9QjuM408ryeHEExYFvJfuS8AlNNdEEyaF6GsQF N9SiT8nGS7oTuyyhsLHCuyjgRdk58nC32UV6Wv/2MCyC9up9RDG98BL+9qmIayIVWkxz F7Ig0nna4kQmtH2buiEmYrSCt2VohweeBSv6epal2oV7CiXwtJvosqMrxJvACBJHlK3I fQ2VsclpehYNjnSpfh+tm6UR5tRVD4nbGaeu1YJuCy1U29rvzwjFO83RQBeiANVZ5uVE v0lA== X-Forwarded-Encrypted: i=1; AJvYcCXYl1+bUKlXQ/LD+qPI58MpC7tufIiNxKWq0HwTcZqJp4ikn+N9fcTJwF24Ai+zCIUbkCvBfDBtEzS5O7E=@vger.kernel.org X-Gm-Message-State: AOJu0Yx3nFQKqNNnrTcHTz4wvgkVTpDJjozBiSGgf9jZZ24sA7SwEt4T ZQymjEKPaiDDvmnH+fhKkJPCjzHOFzA75kRV5ki58VPQRtkDpBbDUqImquT0Gg5vKYo6z/AWWC9 AJum8JQ== X-Google-Smtp-Source: AGHT+IFiBXvch86YA5n4RWV9gvwQ3hSGsIWg2KfTTWT9pZpskEXh0rDiGYyZlblN2g5zh3880+zMquRCEMg= X-Received: from wmco17.prod.google.com ([2002:a05:600c:a311:b0:43d:5828:13ee]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600d:15a:10b0:43d:b3:fb1 with SMTP id 5b1f17b1804b1-45382a3dda3mr40122955e9.27.1750945337108; Thu, 26 Jun 2025 06:42:17 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:52 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-6-glider@google.com> Subject: [PATCH v2 05/11] mm/kasan: define __asan_before_dynamic_init, __asan_after_dynamic_init From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Calls to __asan_before_dynamic_init() and __asan_after_dynamic_init() are inserted by Clang when building with coverage guards. These functions can be used to detect initialization order fiasco bugs in the userspace, but it is fine for them to be no-ops in the kernel. Signed-off-by: Alexander Potapenko Reviewed-by: Dmitry Vyukov --- Change-Id: I7f8eb690a3d96f7d122205e8f1cba8039f6a68eb v2: - Address comments by Dmitry Vyukov: - rename CONFIG_KCOV_ENABLE_GUARDS to CONFIG_KCOV_UNIQUE - Move this patch before the one introducing CONFIG_KCOV_UNIQUE, per Marco Elver's request. --- mm/kasan/generic.c | 18 ++++++++++++++++++ mm/kasan/kasan.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index d54e89f8c3e76..b0b7781524348 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -238,6 +238,24 @@ void __asan_unregister_globals(void *ptr, ssize_t size) } EXPORT_SYMBOL(__asan_unregister_globals); =20 +#if defined(CONFIG_KCOV_UNIQUE) +/* + * __asan_before_dynamic_init() and __asan_after_dynamic_init() are insert= ed + * when the user requests building with coverage guards. In the userspace,= these + * two functions can be used to detect initialization order fiasco bugs, b= ut in + * the kernel they can be no-ops. + */ +void __asan_before_dynamic_init(const char *module_name) +{ +} +EXPORT_SYMBOL(__asan_before_dynamic_init); + +void __asan_after_dynamic_init(void) +{ +} +EXPORT_SYMBOL(__asan_after_dynamic_init); +#endif + #define DEFINE_ASAN_LOAD_STORE(size) \ void __asan_load##size(void *addr) \ { \ diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 129178be5e649..c817c46b4fcd2 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -582,6 +582,8 @@ void kasan_restore_multi_shot(bool enabled); =20 void __asan_register_globals(void *globals, ssize_t size); void __asan_unregister_globals(void *globals, ssize_t size); +void __asan_before_dynamic_init(const char *module_name); +void __asan_after_dynamic_init(void); void __asan_handle_no_return(void); void __asan_alloca_poison(void *, ssize_t size); void __asan_allocas_unpoison(void *stack_top, ssize_t stack_bottom); --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5613C2E8DFF for ; Thu, 26 Jun 2025 13:42:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945343; cv=none; b=tGew2A41oJxbNjWv2BUAMa4kxU8ytOud5Wo56pi+3c2JfMfMnjcEFCKQhhmoyP3BU9HmGQTpqOTx/Pbj4jJp1tJzd0UfQMgqmZL08MWo+wYLxLcDwxBPqw3w6j97TvK77OqDs+laHk5sNfFNpWqgN3c1tJrtbEe/GzCQ4W93PKI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945343; c=relaxed/simple; bh=SDpsO4zpal7cMoZ+kn3wHZTLrwHqGZDZWdZpzGWZ7dU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=L/3bVOS9yp+sZ2NM1Z5BSYoA5SMdL2GAy9PjdE9QfrYG0LFh+pd7qZ56f4JxwyYyvL+zA61St3+HEbBFIImkVLJ6y/wl52X0PF4tQdXM2KjayaZU+buFtpR+1ggNdSUPdpKapjTRQ2os4EtKiTbJdewFNT6XDOQwl3SD5l+gL1U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Nc86VJV2; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Nc86VJV2" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-3a6d90929d6so431652f8f.2 for ; Thu, 26 Jun 2025 06:42:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945339; x=1751550139; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=yNvNdo60faam5nFnHvZbzCMJ04X3V7FkkVfM1Z/F4Ac=; b=Nc86VJV2FWb0JBdNhjcgmjESTerRASNbo4hfO6Dj0LxJ5O6uqJ4TzriIe+WoreXtvB 78+R2lkuwMrj3gD3QhQvEMPBp49KwtCIwRH7PLe9VE2G1/6a7nNV8+peCrnOzxo0P1ok pknFowM8GNBm7ux5uVwaFCDrXrgom5BhFndY9v8FMhWMXOXNH0e6PYIf9FH/Y9EBMH/J pWa6EZxSpkU5nCxVX74LKn1akE19qOnj3wiDOiivMoVYtWaViNNlOErqdVtSyjPS4Dc5 u4Zomko2vaEHoQoP0gnq/btmcVm1/B4EypVrjpTW2X9p643KHk+IMGoem2HJSNTCNyq2 esyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945339; x=1751550139; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=yNvNdo60faam5nFnHvZbzCMJ04X3V7FkkVfM1Z/F4Ac=; b=VHk5Fxtz9JSMxxAHxDU8pk7A3d9BE05/NYr4gOgC53ioHUmcgHcxNbntb2tOKYs7/v MCxzSCCfbr/rzDed5FHUkJjk73UeZXhCbjxQDZ9UFs6SULH8uSYmpipyTCCdfZInSCnl Vn2JC4MtoB37q59ihkDjmlbtxgkURDn+UNxwNkFGhLBE+j9ZxA3w2lbuQM/xwp43CDg9 sSn1uZOtkLyDW2/b4YPmiLfMh6oXZdS93t9IpnrfQSdQ1f+pnThhp9qj9rUXYuqpr0rp +TWwUAK0U7Ie1ldEMN3EZCQVWNiEf+HNuL++DV3gqDJvBlpibeBV615IK19Ft8KLAjM0 uv4g== X-Forwarded-Encrypted: i=1; AJvYcCVOWRUHS7XTafg2v+QwHTIIVXDE5e7JJxXo4WU9dhzwH0fADXxXnOpx5lKV0mqT0Vj4C6A87W+2gQqgZUU=@vger.kernel.org X-Gm-Message-State: AOJu0Ywe/BDdQDs5hEYc15ghBL0Quur8pc+nSRNt/t2siGiA/xiRUz1Z R+BfmVi6SvDT3Xkuls+U6cWCHKtpm28OWyoCKD97D2AoB5JGw9pLRXSMdryrYJij8rKt/yu6nbS KzUiQhw== X-Google-Smtp-Source: AGHT+IFAobGVtIvf5Sucv9bQxprDVPwYKV9MHra8e/AYUMvHjoSyNF4V37vPeQ82J11RVjy8CWXJLi61tZo= X-Received: from wmbfs5.prod.google.com ([2002:a05:600c:3f85:b0:450:41ed:d20e]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:2011:b0:3a4:e54c:adf2 with SMTP id ffacd0b85a97d-3a6ed61a12cmr5925433f8f.5.1750945339545; Thu, 26 Jun 2025 06:42:19 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:53 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-7-glider@google.com> Subject: [PATCH v2 06/11] kcov: x86: introduce CONFIG_KCOV_UNIQUE From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, x86@kernel.org, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The new config switches coverage instrumentation to using __sanitizer_cov_trace_pc_guard(u32 *guard) instead of __sanitizer_cov_trace_pc(void) This relies on Clang's -fsanitize-coverage=3Dtrace-pc-guard flag [1]. Each callback receives a unique 32-bit guard variable residing in the __sancov_guards section. Those guards can be used by kcov to deduplicate the coverage on the fly. As a first step, we make the new instrumentation mode 1:1 compatible with the old one. [1] https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-gua= rds Cc: x86@kernel.org Signed-off-by: Alexander Potapenko --- Change-Id: Iacb1e71fd061a82c2acadf2347bba4863b9aec39 v2: - Address comments by Dmitry Vyukov - rename CONFIG_KCOV_ENABLE_GUARDS to CONFIG_KCOV_UNIQUE - update commit description and config description - Address comments by Marco Elver - rename sanitizer_cov_write_subsequent() to kcov_append_to_buffer() - make config depend on X86_64 (via ARCH_HAS_KCOV_UNIQUE) - swap #ifdef branches - tweak config description - remove redundant check for CONFIG_CC_HAS_SANCOV_TRACE_PC_GUARD --- arch/x86/Kconfig | 1 + arch/x86/kernel/vmlinux.lds.S | 1 + include/asm-generic/vmlinux.lds.h | 14 ++++++- include/linux/kcov.h | 2 + kernel/kcov.c | 61 +++++++++++++++++++++---------- lib/Kconfig.debug | 24 ++++++++++++ scripts/Makefile.kcov | 4 ++ scripts/module.lds.S | 23 ++++++++++++ tools/objtool/check.c | 1 + 9 files changed, 110 insertions(+), 21 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e21cca404943e..d104c5a193bdf 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -93,6 +93,7 @@ config X86 select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_KCOV if X86_64 + select ARCH_HAS_KCOV_UNIQUE if X86_64 select ARCH_HAS_KERNEL_FPU_SUPPORT select ARCH_HAS_MEM_ENCRYPT select ARCH_HAS_MEMBARRIER_SYNC_CORE diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index cda5f8362e9da..8076e8953fddc 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -372,6 +372,7 @@ SECTIONS . =3D ALIGN(PAGE_SIZE); __bss_stop =3D .; } + SANCOV_GUARDS_BSS =20 /* * The memory occupied from _text to here, __end_of_kernel_reserve, is diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinu= x.lds.h index 58a635a6d5bdf..875c4deb66208 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -102,7 +102,8 @@ * sections to be brought in with rodata. */ #if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CL= ANG) || \ -defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG) + defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG) || \ + defined(CONFIG_KCOV_UNIQUE) #define TEXT_MAIN .text .text.[0-9a-zA-Z_]* #else #define TEXT_MAIN .text @@ -121,6 +122,17 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPEL= LER_CLANG) #define SBSS_MAIN .sbss #endif =20 +#if defined(CONFIG_KCOV_UNIQUE) +#define SANCOV_GUARDS_BSS \ + __sancov_guards(NOLOAD) : { \ + __start___sancov_guards =3D .; \ + *(__sancov_guards); \ + __stop___sancov_guards =3D .; \ + } +#else +#define SANCOV_GUARDS_BSS +#endif + /* * GCC 4.5 and later have a 32 bytes section alignment for structures. * Except GCC 4.9, that feels the need to align on 64 bytes. diff --git a/include/linux/kcov.h b/include/linux/kcov.h index 0e425c3524b86..dd8bbee6fe274 100644 --- a/include/linux/kcov.h +++ b/include/linux/kcov.h @@ -107,6 +107,8 @@ typedef unsigned long long kcov_u64; #endif =20 void __sanitizer_cov_trace_pc(void); +void __sanitizer_cov_trace_pc_guard(u32 *guard); +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop); void __sanitizer_cov_trace_cmp1(u8 arg1, u8 arg2); void __sanitizer_cov_trace_cmp2(u16 arg1, u16 arg2); void __sanitizer_cov_trace_cmp4(u32 arg1, u32 arg2); diff --git a/kernel/kcov.c b/kernel/kcov.c index ff7f118644f49..8e98ca8d52743 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -195,27 +195,15 @@ static notrace unsigned long canonicalize_ip(unsigned= long ip) return ip; } =20 -/* - * Entry point from instrumented code. - * This is called once per basic-block/edge. - */ -void notrace __sanitizer_cov_trace_pc(void) +static notrace void kcov_append_to_buffer(unsigned long *area, int size, + unsigned long ip) { - struct task_struct *t; - unsigned long *area; - unsigned long ip =3D canonicalize_ip(_RET_IP_); - unsigned long pos; - - t =3D current; - if (!check_kcov_mode(KCOV_MODE_TRACE_PC, t)) - return; - - area =3D t->kcov_state.area; /* The first 64-bit word is the number of subsequent PCs. */ - pos =3D READ_ONCE(area[0]) + 1; - if (likely(pos < t->kcov_state.size)) { - /* Previously we write pc before updating pos. However, some - * early interrupt code could bypass check_kcov_mode() check + unsigned long pos =3D READ_ONCE(area[0]) + 1; + + if (likely(pos < size)) { + /* + * Some early interrupt code could bypass check_kcov_mode() check * and invoke __sanitizer_cov_trace_pc(). If such interrupt is * raised between writing pc and updating pos, the pc could be * overitten by the recursive __sanitizer_cov_trace_pc(). @@ -226,7 +214,40 @@ void notrace __sanitizer_cov_trace_pc(void) area[pos] =3D ip; } } + +/* + * Entry point from instrumented code. + * This is called once per basic-block/edge. + */ +#ifdef CONFIG_KCOV_UNIQUE +void notrace __sanitizer_cov_trace_pc_guard(u32 *guard) +{ + if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) + return; + + kcov_append_to_buffer(current->kcov_state.area, + current->kcov_state.size, + canonicalize_ip(_RET_IP_)); +} +EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard); + +void notrace __sanitizer_cov_trace_pc_guard_init(uint32_t *start, + uint32_t *stop) +{ +} +EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard_init); +#else /* !CONFIG_KCOV_UNIQUE */ +void notrace __sanitizer_cov_trace_pc(void) +{ + if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) + return; + + kcov_append_to_buffer(current->kcov_state.area, + current->kcov_state.size, + canonicalize_ip(_RET_IP_)); +} EXPORT_SYMBOL(__sanitizer_cov_trace_pc); +#endif =20 #ifdef CONFIG_KCOV_ENABLE_COMPARISONS static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip) @@ -254,7 +275,7 @@ static void notrace write_comp_data(u64 type, u64 arg1,= u64 arg2, u64 ip) start_index =3D 1 + count * KCOV_WORDS_PER_CMP; end_pos =3D (start_index + KCOV_WORDS_PER_CMP) * sizeof(u64); if (likely(end_pos <=3D max_pos)) { - /* See comment in __sanitizer_cov_trace_pc(). */ + /* See comment in kcov_append_to_buffer(). */ WRITE_ONCE(area[0], count + 1); barrier(); area[start_index] =3D type; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f9051ab610d54..24dcb721dbb0b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2156,6 +2156,8 @@ config ARCH_HAS_KCOV config CC_HAS_SANCOV_TRACE_PC def_bool $(cc-option,-fsanitize-coverage=3Dtrace-pc) =20 +config CC_HAS_SANCOV_TRACE_PC_GUARD + def_bool $(cc-option,-fsanitize-coverage=3Dtrace-pc-guard) =20 config KCOV bool "Code coverage for fuzzing" @@ -2172,6 +2174,28 @@ config KCOV =20 For more details, see Documentation/dev-tools/kcov.rst. =20 +config ARCH_HAS_KCOV_UNIQUE + bool + help + An architecture should select this when it can successfully + build and run with CONFIG_KCOV_UNIQUE. + +config KCOV_UNIQUE + depends on KCOV + depends on CC_HAS_SANCOV_TRACE_PC_GUARD && ARCH_HAS_KCOV_UNIQUE + bool "Use coverage guards for KCOV" + help + Use coverage guards instrumentation for KCOV, passing + -fsanitize-coverage=3Dtrace-pc-guard to the compiler. + + Every coverage callback is associated with a global variable that + allows to efficiently deduplicate coverage at collection time. + This drastically reduces the buffer size required for coverage + collection. + + This config comes at a cost of increased binary size (4 bytes of .bss + plus 1-2 instructions to pass an extra parameter, per basic block). + config KCOV_ENABLE_COMPARISONS bool "Enable comparison operands collection by KCOV" depends on KCOV diff --git a/scripts/Makefile.kcov b/scripts/Makefile.kcov index 67e8cfe3474b7..0b17533ef35f6 100644 --- a/scripts/Makefile.kcov +++ b/scripts/Makefile.kcov @@ -1,5 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only +ifeq ($(CONFIG_KCOV_UNIQUE),y) +kcov-flags-y +=3D -fsanitize-coverage=3Dtrace-pc-guard +else kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) +=3D -fsanitize-coverage=3Dtra= ce-pc +endif kcov-flags-$(CONFIG_KCOV_ENABLE_COMPARISONS) +=3D -fsanitize-coverage=3Dtr= ace-cmp kcov-flags-$(CONFIG_GCC_PLUGIN_SANCOV) +=3D -fplugin=3D$(objtree)/scripts= /gcc-plugins/sancov_plugin.so =20 diff --git a/scripts/module.lds.S b/scripts/module.lds.S index 450f1088d5fd3..314b56680ea1a 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -64,6 +64,29 @@ SECTIONS { MOD_CODETAG_SECTIONS() } #endif + +#ifdef CONFIG_KCOV_UNIQUE + __sancov_guards(NOLOAD) : { + __start___sancov_guards =3D .; + *(__sancov_guards); + __stop___sancov_guards =3D .; + } + + .text : { + *(.text .text.[0-9a-zA-Z_]*) + *(.text..L*) + } + + .init.text : { + *(.init.text .init.text.[0-9a-zA-Z_]*) + *(.init.text..L*) + } + .exit.text : { + *(.exit.text .exit.text.[0-9a-zA-Z_]*) + *(.exit.text..L*) + } +#endif + MOD_SEPARATE_CODETAG_SECTIONS() } =20 diff --git a/tools/objtool/check.c b/tools/objtool/check.c index b21b12ec88d96..62fbe9b2aa077 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1154,6 +1154,7 @@ static const char *uaccess_safe_builtin[] =3D { "write_comp_data", "check_kcov_mode", "__sanitizer_cov_trace_pc", + "__sanitizer_cov_trace_pc_guard", "__sanitizer_cov_trace_const_cmp1", "__sanitizer_cov_trace_const_cmp2", "__sanitizer_cov_trace_const_cmp4", --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BDBEA2E7648 for ; Thu, 26 Jun 2025 13:42:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945345; cv=none; b=CRILjpSsPAO1lZqkpjqJV3tg4XINft8xeA8oV4K8a+Dm4powMkLoWmJpSCAdBXJ/NJmuvQOgy8laxN8fCP3v6NGe1g5kEyGpMXuE/f6U29411nEJ/M2OdN5O9V2/VQumsNtOdWANQ8aKz+r9Vux+BHoZQbrcQ2WDqjx2UnDyfbI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945345; c=relaxed/simple; bh=n4GUHXxJO9DGY8nRbnY7BpSsOF3OqHkS8dbkQeKpkDE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=PgK9mFqD0tjijmUtlWlsGkjFqaZ47xC4hK9CgHNXJpAKtPcp1uk9Hbkr9dCDfq4jf6jF807ASYn2RTf7/sqJnTAsh3RPfVVSTmsSwmqQSLDgvFl7LojAR/iVT48brkS2/vS7IgdtEsS5TyiNtMP+/A/9Ge0Mqt9sTa5P1tms59c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=daCzbcHW; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="daCzbcHW" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-45359bfe631so5241935e9.0 for ; Thu, 26 Jun 2025 06:42:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945342; x=1751550142; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3X/PLO35Kby/7c8Y0k4KR1mlzE+5Joj5D37Kq7kXi8s=; b=daCzbcHWuhe7OaDa0hw5LZ1UpUNig1vqzQVvHSj6Vl/ww2Nmg6mWefBH2JIZc7n4Ga ljK4y7qoFFEI9NJ9abTdlfkfm5sfWDj3tiR2s4xEB4Vz0nmTuN/Dh7UmkGFPvzOx0Ijj iyj3/h0PMX4tFFOtNo4A61caeEF+gZvmBqunzq2LvMC2VjndflRTPafoTKmGMCQNj1te ROWP0RNH+r+t5EzzUNvpaB9hUmlP1AhhLgkgQgDy06Vsp+0nG2eWAIu6Bu0tC7B8AJj1 WCfXiFr3EHcBXmQJTE8Sm4lGsQl0o8r1w40N2ygpIBUqLhblPTXQwd21TcotfQ6pfbss 2Wow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945342; x=1751550142; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3X/PLO35Kby/7c8Y0k4KR1mlzE+5Joj5D37Kq7kXi8s=; b=ZCbbJPURhRXy+YkXKN29ZZKE3eMZSHRLtxOmIEsap4Fs9faaQqbcILomHeBSXin1Ju R7Bu4W9My6QOPtN4oFXWvjKQXuDpDCoX121zDutkjWGW+YohIBXVNznJx9eoBJ/0/N17 TTcQdZH7VKuKIqms4v3b0JEe0GyfZtDB0idd5bAf9n4kNcxZ1zqy7kRN9cOf4l118QLS 0iBFDkegr0yAX42ENP8Sx5mEsTXy9Nqb6DTklHVCuFDremwjP1z1ivUeCiTfa2tPlgy+ YhA/ZcHeUicK712hfxZ6ZUdj63MYzCm0arm/XTe5+Q+tQ4PodarkX5aCipqeFU84Vop3 7Uyg== X-Forwarded-Encrypted: i=1; AJvYcCWN7/xxRzUSjKSLTZNSuU52vT65S6t+3iynGetAnfm1N+8HncaNwFK7LTsIkYeG5X75mRG1raymuWHhdys=@vger.kernel.org X-Gm-Message-State: AOJu0Yw0bqMFIYZeI/yAG+f6Z89LKWaiaOI2eGTJmZplE5m5BBs4rEkK 3sQoElbnGEdrtcy+nn+Unk6AMw/c54F/zL5pUEGArqP8DakPxgnEm0A2SevGXGosX4+rJ99gBFJ YLlmRSA== X-Google-Smtp-Source: AGHT+IGaQiZVJFDkAZXUNY/qII1+3KZPhGoe4YjY7s27kiSMY+xTHrBWHJuDY1SfNVHdSJTiJKaZbj+Mpa8= X-Received: from wmbet8.prod.google.com ([2002:a05:600c:8188:b0:442:f451:ae05]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:3590:b0:442:d9f2:ded8 with SMTP id 5b1f17b1804b1-45381ab8dbemr83015875e9.15.1750945342082; Thu, 26 Jun 2025 06:42:22 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:54 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-8-glider@google.com> Subject: [PATCH v2 07/11] kcov: add trace and trace_size to struct kcov_state From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Keep kcov_state.area as the pointer to the memory buffer used by kcov and shared with the userspace. Store the pointer to the trace (part of the buffer holding sequential events) separately, as we will be splitting that buffer in multiple parts. No functional changes so far. Signed-off-by: Alexander Potapenko --- Change-Id: I50b5589ef0e0b6726aa0579334093c648f76790a v2: - Address comments by Dmitry Vyukov: - tweak commit description - Address comments by Marco Elver: - rename sanitizer_cov_write_subsequent() to kcov_append_to_buffer() - Update code to match the new description of struct kcov_state --- include/linux/kcov_types.h | 9 ++++++- kernel/kcov.c | 54 ++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/include/linux/kcov_types.h b/include/linux/kcov_types.h index 53b25b6f0addd..233e7a682654b 100644 --- a/include/linux/kcov_types.h +++ b/include/linux/kcov_types.h @@ -7,9 +7,16 @@ struct kcov_state { /* Size of the area (in long's). */ unsigned int size; + /* + * Pointer to user-provided memory used by kcov. This memory may + * contain multiple buffers. + */ + void *area; =20 + /* Size of the trace (in long's). */ + unsigned int trace_size; /* Buffer for coverage collection, shared with the userspace. */ - void *area; + unsigned long *trace; =20 /* * KCOV sequence number: incremented each time kcov is reenabled, used diff --git a/kernel/kcov.c b/kernel/kcov.c index 8e98ca8d52743..038261145cf93 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -195,11 +195,11 @@ static notrace unsigned long canonicalize_ip(unsigned= long ip) return ip; } =20 -static notrace void kcov_append_to_buffer(unsigned long *area, int size, +static notrace void kcov_append_to_buffer(unsigned long *trace, int size, unsigned long ip) { /* The first 64-bit word is the number of subsequent PCs. */ - unsigned long pos =3D READ_ONCE(area[0]) + 1; + unsigned long pos =3D READ_ONCE(trace[0]) + 1; =20 if (likely(pos < size)) { /* @@ -209,9 +209,9 @@ static notrace void kcov_append_to_buffer(unsigned long= *area, int size, * overitten by the recursive __sanitizer_cov_trace_pc(). * Update pos before writing pc to avoid such interleaving. */ - WRITE_ONCE(area[0], pos); + WRITE_ONCE(trace[0], pos); barrier(); - area[pos] =3D ip; + trace[pos] =3D ip; } } =20 @@ -225,8 +225,8 @@ void notrace __sanitizer_cov_trace_pc_guard(u32 *guard) if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) return; =20 - kcov_append_to_buffer(current->kcov_state.area, - current->kcov_state.size, + kcov_append_to_buffer(current->kcov_state.trace, + current->kcov_state.trace_size, canonicalize_ip(_RET_IP_)); } EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard); @@ -242,8 +242,8 @@ void notrace __sanitizer_cov_trace_pc(void) if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) return; =20 - kcov_append_to_buffer(current->kcov_state.area, - current->kcov_state.size, + kcov_append_to_buffer(current->kcov_state.trace, + current->kcov_state.trace_size, canonicalize_ip(_RET_IP_)); } EXPORT_SYMBOL(__sanitizer_cov_trace_pc); @@ -252,9 +252,9 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_pc); #ifdef CONFIG_KCOV_ENABLE_COMPARISONS static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip) { - struct task_struct *t; - u64 *area; u64 count, start_index, end_pos, max_pos; + struct task_struct *t; + u64 *trace; =20 t =3D current; if (!check_kcov_mode(KCOV_MODE_TRACE_CMP, t)) @@ -266,22 +266,22 @@ static void notrace write_comp_data(u64 type, u64 arg= 1, u64 arg2, u64 ip) * We write all comparison arguments and types as u64. * The buffer was allocated for t->kcov_state.size unsigned longs. */ - area =3D (u64 *)t->kcov_state.area; + trace =3D (u64 *)t->kcov_state.trace; max_pos =3D t->kcov_state.size * sizeof(unsigned long); =20 - count =3D READ_ONCE(area[0]); + count =3D READ_ONCE(trace[0]); =20 /* Every record is KCOV_WORDS_PER_CMP 64-bit words. */ start_index =3D 1 + count * KCOV_WORDS_PER_CMP; end_pos =3D (start_index + KCOV_WORDS_PER_CMP) * sizeof(u64); if (likely(end_pos <=3D max_pos)) { /* See comment in kcov_append_to_buffer(). */ - WRITE_ONCE(area[0], count + 1); + WRITE_ONCE(trace[0], count + 1); barrier(); - area[start_index] =3D type; - area[start_index + 1] =3D arg1; - area[start_index + 2] =3D arg2; - area[start_index + 3] =3D ip; + trace[start_index] =3D type; + trace[start_index + 1] =3D arg1; + trace[start_index + 2] =3D arg2; + trace[start_index + 3] =3D ip; } } =20 @@ -382,11 +382,13 @@ static void kcov_start(struct task_struct *t, struct = kcov *kcov, =20 static void kcov_stop(struct task_struct *t) { + int saved_sequence =3D t->kcov_state.sequence; + WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED); barrier(); t->kcov =3D NULL; - t->kcov_state.size =3D 0; - t->kcov_state.area =3D NULL; + t->kcov_state =3D (typeof(t->kcov_state)){ 0 }; + t->kcov_state.sequence =3D saved_sequence; } =20 static void kcov_task_reset(struct task_struct *t) @@ -736,6 +738,8 @@ static long kcov_ioctl(struct file *filep, unsigned int= cmd, unsigned long arg) } kcov->state.area =3D area; kcov->state.size =3D size; + kcov->state.trace =3D area; + kcov->state.trace_size =3D size; kcov->mode =3D KCOV_MODE_INIT; spin_unlock_irqrestore(&kcov->lock, flags); return 0; @@ -928,10 +932,12 @@ void kcov_remote_start(u64 handle) local_lock_irqsave(&kcov_percpu_data.lock, flags); } =20 - /* Reset coverage size. */ - *(u64 *)area =3D 0; state.area =3D area; state.size =3D size; + state.trace =3D area; + state.trace_size =3D size; + /* Reset coverage size. */ + state.trace[0] =3D 0; =20 if (in_serving_softirq()) { kcov_remote_softirq_start(t); @@ -1004,8 +1010,8 @@ void kcov_remote_stop(void) struct task_struct *t =3D current; struct kcov *kcov; unsigned int mode; - void *area; - unsigned int size; + void *area, *trace; + unsigned int size, trace_size; int sequence; unsigned long flags; =20 @@ -1037,6 +1043,8 @@ void kcov_remote_stop(void) kcov =3D t->kcov; area =3D t->kcov_state.area; size =3D t->kcov_state.size; + trace =3D t->kcov_state.trace; + trace_size =3D t->kcov_state.trace_size; sequence =3D t->kcov_state.sequence; =20 kcov_stop(t); --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F9D92E92CA for ; Thu, 26 Jun 2025 13:42:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945348; cv=none; b=BkZBY/gt3edBfBEp7tD2S5Qfx4HsSFCDZE1QJGqWm+L/M+6EXqXWp+nkNzo+80BAm2J2VBef5pn538yDgLxXbAMssu+X4LWYEdOBTHtrUS5Smk3t27jQuMuDJ8SSgrnaEV2KtuZakDKCGbwuUL4zKD4/kOCvYgjLKzE+qJCPtpg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945348; c=relaxed/simple; bh=Km3QcDQl7dSAYpce7fvzwIB5YMo1mP3vPDrWmpjq35Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GcPCVQ8mDj+xCNrzA+O+qAN8MPc0JSvX5l8ullwyP/pFHZOk3i2erAdkAVR+weGzibVwbNd4pobVXkJeBAOBPkYNkBD653I0+Flg8TZ1HFvimrfe1VNPh1f9/l/amRwKM1QXlDnO9T1vRWcNQ03FZZry80n7MnI5r4vUkts4I3c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=nowmzhYW; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="nowmzhYW" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-6069f1c97b3so860627a12.2 for ; Thu, 26 Jun 2025 06:42:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945345; x=1751550145; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=gRtiAm1l+bCEDwUYq636VEWKycADCHU49+iX/HPvsao=; b=nowmzhYWqUmGwfbkHvi1N5gu651MZ20aX19rctBWdsR7yj24lgdBUFSGnpir4LeJJX F23ZHsdFVGjP/CuUDT0zNlbSxCzIUTFCKbfKjl8eO8NwLBJUFcqotzhZQxIZdfnlBZZz DgXd6ymXiKb+0+xomhWS8E5PIrBL8Zm6TD73tzsx9hZBQeA0avBun0pQMulSxZZBjAmh wrojfde7/RM3W1cWzFIY8CXn8+Hx5QexEZebiWS1lT9a9Xqr5DjGkf+3a+Kfs01TfpZC 5GooV9qPuZxz6P0jf9uVSkIk6PyavbG7mumepKNIG2O8/48fvc3e9hHil/u/pCa27SrX vA4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945345; x=1751550145; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=gRtiAm1l+bCEDwUYq636VEWKycADCHU49+iX/HPvsao=; b=OWwcSEhUEJK9fK5CovqXkmtpV07x9rHSAUIakUe68h0zx8ItP9CnbNyRGl1mNjyYXN qFXolFzsIa/JTLKT75rHdZr1aS0ESXk1IZc55Z9oqzr3bGdKQ5vMnk3qho83h8YN03co rYEmy1FPXtfxDCWfCQBZGyIlxsQq6XkN6WmQcqkoZPbJb9nId3t/m+so7s6Eok5rshnq C0C3VTs6/OPxH+yCwtJl0X6YJsLrOdT+1A641TdPd+ieU27N/UoElzhAqyCfs4xvfMtz 0CNuDZOuq7N5BzS21qin5ABhvMXa06r/iv5Lc4WaVMhujvKZrB3WHnl+iIAiAf/fFypJ tCdQ== X-Forwarded-Encrypted: i=1; AJvYcCV5vU3naE9RhPLHvc+pyxls48jAKVFT0+OW+uXgcLI3rSIFCUxDQoYXesOwEd1c4C+mjpTMSU0ebpHbNcU=@vger.kernel.org X-Gm-Message-State: AOJu0YyaprEJ6jdn41mqOXJfNXzeEJVltljMnnvdRwuP5pIw4vnZfUQF K76yVZ+2NduPR48CJu/rZfWlD8o0FQ56KArIsVqdY4V0ZL+SaWE2EESVDx03RNbOD6rt60K4wLk Gfiws+A== X-Google-Smtp-Source: AGHT+IGpRJTKvjgChXTjdJ6ThSWOGSdYpupSaaPSchIqaKzEDhqU8NE8x5BJDf8EqU1/vYwJDS/la71KAoU= X-Received: from edbz3.prod.google.com ([2002:a05:6402:40c3:b0:607:2153:28eb]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:278a:b0:60c:4a96:423a with SMTP id 4fb4d7f45d1cf-60c4dd6eff6mr6768547a12.18.1750945344630; Thu, 26 Jun 2025 06:42:24 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:55 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-9-glider@google.com> Subject: [PATCH v2 08/11] kcov: add ioctl(KCOV_UNIQUE_ENABLE) From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" ioctl(KCOV_UNIQUE_ENABLE) enables collection of deduplicated coverage in the presence of CONFIG_KCOV_ENABLE_GUARDS. The buffer shared with the userspace is divided in two parts, one holding a bitmap, and the other one being the trace. The single parameter of ioctl(KCOV_UNIQUE_ENABLE) determines the number of words used for the bitmap. Each __sanitizer_cov_trace_pc_guard() instrumentation hook receives a pointer to a unique guard variable. Upon the first call of each hook, the guard variable is initialized with a unique integer, which is used to map those hooks to bits in the bitmap. In the new coverage collection mode, the kernel first checks whether the bit corresponding to a particular hook is set, and then, if it is not, the PC is written into the trace buffer, and the bit is set. Note: when CONFIG_KCOV_ENABLE_GUARDS is disabled, ioctl(KCOV_UNIQUE_ENABLE) returns -ENOTSUPP, which is consistent with the existing kcov code. Measuring the exact performance impact of this mode directly can be challenging. However, based on fuzzing experiments (50 instances x 24h with and without deduplication), we observe the following: - When normalized by pure fuzzing time, total executions decreased by 2.1% (p=3D0.01). - When normalized by fuzzer uptime, the reduction in total executions was statistically insignificant (-1.0% with p=3D0.20). Despite a potential slight slowdown in execution count, the new mode positively impacts fuzzing effectiveness: - Statistically significant increase in corpus size (+0.6%, p<0.01). - Statistically significant increase in coverage (+0.6%, p<0.01). - A 99.8% reduction in coverage overflows. Also update the documentation. Signed-off-by: Alexander Potapenko --- Change-Id: I9805e7b22619a50e05cc7c7d794dacf6f7de2f03 v2: - Address comments by Dmitry Vyukov: - rename CONFIG_KCOV_ENABLE_GUARDS to CONFIG_KCOV_UNIQUE - rename KCOV_MODE_TRACE_UNIQUE_PC to KCOV_MODE_UNIQUE_PC - simplify index allocation - update documentation and comments - Address comments by Marco Elver: - change _IOR to _IOW in KCOV_UNIQUE_ENABLE definition - rename sanitizer_cov_write_subsequent() to kcov_append_to_buffer() - Use __test_and_set_bit() to avoid the lock prefix on the bit operation - Update code to match the new description of struct kcov_state - Rename kcov_get_mode() to kcov_arg_to_mode() to avoid confusion with get_kcov_mode(). Also make it use `enum kcov_mode`. --- Documentation/dev-tools/kcov.rst | 43 ++++++++ include/linux/kcov.h | 2 + include/linux/kcov_types.h | 8 ++ include/uapi/linux/kcov.h | 1 + kernel/kcov.c | 165 ++++++++++++++++++++++++++----- 5 files changed, 192 insertions(+), 27 deletions(-) diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kco= v.rst index abf3ad2e784e8..6446887cd1c92 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst @@ -192,6 +192,49 @@ Normally the shared buffer is used as follows:: up to the buffer[0] value saved above | =20 =20 +Unique coverage collection +--------------------------- + +Instead of collecting a trace of PCs, KCOV can deduplicate them on the fly. +This mode is enabled by the ``KCOV_UNIQUE_ENABLE`` ioctl (only available if +``CONFIG_KCOV_UNIQUE`` is on). + +.. code-block:: c + + /* Same includes and defines as above. */ + #define KCOV_UNIQUE_ENABLE _IOW('c', 103, unsigned long) + #define BITMAP_SIZE (4<<10) + + /* Instead of KCOV_ENABLE, enable unique coverage collection. */ + if (ioctl(fd, KCOV_UNIQUE_ENABLE, BITMAP_SIZE)) + perror("ioctl"), exit(1); + /* Reset the coverage from the tail of the ioctl() call. */ + __atomic_store_n(&cover[BITMAP_SIZE], 0, __ATOMIC_RELAXED); + memset(cover, 0, BITMAP_SIZE * sizeof(unsigned long)); + + /* Call the target syscall call. */ + /* ... */ + + /* Read the number of collected PCs. */ + n =3D __atomic_load_n(&cover[BITMAP_SIZE], __ATOMIC_RELAXED); + /* Disable the coverage collection. */ + if (ioctl(fd, KCOV_DISABLE, 0)) + perror("ioctl"), exit(1); + +Calling ``ioctl(fd, KCOV_UNIQUE_ENABLE, bitmap_size)`` carves out ``bitmap= _size`` +unsigned long's from those allocated by ``KCOV_INIT_TRACE`` to keep an opa= que +bitmap that prevents the kernel from storing the same PC twice. The remain= ing +part of the buffer is used to collect PCs, like in other modes (this part = must +contain at least two unsigned long's, like when collecting non-unique PCs). + +The mapping between a PC and its position in the bitmap is persistent duri= ng the +kernel lifetime, so it is possible for the callers to directly use the bit= map +contents as a coverage signal (like when fuzzing userspace with AFL). + +In order to reset the coverage between the runs, the user needs to rewind = the +trace (by writing 0 into the first buffer element past ``bitmap_size``) an= d zero +the whole bitmap. + Comparison operands collection ------------------------------ =20 diff --git a/include/linux/kcov.h b/include/linux/kcov.h index dd8bbee6fe274..13c120a894107 100644 --- a/include/linux/kcov.h +++ b/include/linux/kcov.h @@ -10,6 +10,7 @@ struct task_struct; #ifdef CONFIG_KCOV =20 enum kcov_mode { + KCOV_MODE_INVALID =3D -1, /* Coverage collection is not enabled yet. */ KCOV_MODE_DISABLED =3D 0, /* KCOV was initialized, but tracing mode hasn't been chosen yet. */ @@ -23,6 +24,7 @@ enum kcov_mode { KCOV_MODE_TRACE_CMP =3D 3, /* The process owns a KCOV remote reference. */ KCOV_MODE_REMOTE =3D 4, + KCOV_MODE_UNIQUE_PC =3D 5, }; =20 #define KCOV_IN_CTXSW (1 << 30) diff --git a/include/linux/kcov_types.h b/include/linux/kcov_types.h index 233e7a682654b..5ab6e13a9e725 100644 --- a/include/linux/kcov_types.h +++ b/include/linux/kcov_types.h @@ -18,6 +18,14 @@ struct kcov_state { /* Buffer for coverage collection, shared with the userspace. */ unsigned long *trace; =20 + /* Size of the bitmap (in bits). */ + unsigned int bitmap_size; + /* + * Bitmap for coverage deduplication, shared with the + * userspace. + */ + unsigned long *bitmap; + /* * KCOV sequence number: incremented each time kcov is reenabled, used * by kcov_remote_stop(), see the comment there. diff --git a/include/uapi/linux/kcov.h b/include/uapi/linux/kcov.h index ed95dba9fa37e..e743ee011eeca 100644 --- a/include/uapi/linux/kcov.h +++ b/include/uapi/linux/kcov.h @@ -22,6 +22,7 @@ struct kcov_remote_arg { #define KCOV_ENABLE _IO('c', 100) #define KCOV_DISABLE _IO('c', 101) #define KCOV_REMOTE_ENABLE _IOW('c', 102, struct kcov_remote_arg) +#define KCOV_UNIQUE_ENABLE _IOW('c', 103, unsigned long) =20 enum { /* diff --git a/kernel/kcov.c b/kernel/kcov.c index 038261145cf93..2a4edbaad50d0 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -29,6 +29,10 @@ =20 #include =20 +#ifdef CONFIG_KCOV_UNIQUE +atomic_t kcov_guard_max_index =3D ATOMIC_INIT(0); +#endif + #define kcov_debug(fmt, ...) pr_debug("%s: " fmt, __func__, ##__VA_ARGS__) =20 /* Number of 64-bit words written per one comparison: */ @@ -163,10 +167,9 @@ static __always_inline bool in_softirq_really(void) return in_serving_softirq() && !in_hardirq() && !in_nmi(); } =20 -static notrace bool check_kcov_mode(enum kcov_mode needed_mode, - struct task_struct *t) +static notrace enum kcov_mode get_kcov_mode(struct task_struct *t) { - unsigned int mode; + enum kcov_mode mode; =20 /* * We are interested in code coverage as a function of a syscall inputs, @@ -174,7 +177,7 @@ static notrace bool check_kcov_mode(enum kcov_mode need= ed_mode, * coverage collection section in a softirq. */ if (!in_task() && !(in_softirq_really() && t->kcov_softirq)) - return false; + return KCOV_MODE_INVALID; mode =3D READ_ONCE(t->kcov_mode); /* * There is some code that runs in interrupts but for which @@ -184,7 +187,7 @@ static notrace bool check_kcov_mode(enum kcov_mode need= ed_mode, * kcov_start(). */ barrier(); - return mode =3D=3D needed_mode; + return mode; } =20 static notrace unsigned long canonicalize_ip(unsigned long ip) @@ -203,7 +206,7 @@ static notrace void kcov_append_to_buffer(unsigned long= *trace, int size, =20 if (likely(pos < size)) { /* - * Some early interrupt code could bypass check_kcov_mode() check + * Some early interrupt code could bypass get_kcov_mode() check * and invoke __sanitizer_cov_trace_pc(). If such interrupt is * raised between writing pc and updating pos, the pc could be * overitten by the recursive __sanitizer_cov_trace_pc(). @@ -220,14 +223,76 @@ static notrace void kcov_append_to_buffer(unsigned lo= ng *trace, int size, * This is called once per basic-block/edge. */ #ifdef CONFIG_KCOV_UNIQUE +DEFINE_PER_CPU(u32, saved_index); +/* + * Assign an index to a guard variable that does not have one yet. + * For an unlikely case of a race with another task executing the same bas= ic + * block for the first time with kcov enabled, we store the unused index i= n a + * per-cpu variable. + * In an even less likely case of the current task losing the race and get= ting + * rescheduled onto a CPU that already has a saved index, the index is + * discarded. This will result in an unused hole in the bitmap, but such e= vents + * should have minor impact on the overall memory consumption. + */ +static __always_inline u32 init_pc_guard(u32 *guard) +{ + /* If the current CPU has a saved free index, use it. */ + u32 index =3D this_cpu_xchg(saved_index, 0); + u32 old_guard; + + if (likely(!index)) + /* + * Allocate a new index. No overflow is possible, because 2**32 + * unique basic blocks will take more space than the max size + * of the kernel text segment. + */ + index =3D atomic_inc_return(&kcov_guard_max_index); + + /* + * Make sure another task is not initializing the same guard + * concurrently. + */ + old_guard =3D cmpxchg(guard, 0, index); + if (unlikely(old_guard)) { + /* We lost the race, save the index for future use. */ + this_cpu_write(saved_index, index); + return old_guard; + } + return index; +} + void notrace __sanitizer_cov_trace_pc_guard(u32 *guard) { - if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) - return; + enum kcov_mode mode =3D get_kcov_mode(current); + u32 pc_index; =20 - kcov_append_to_buffer(current->kcov_state.trace, - current->kcov_state.trace_size, - canonicalize_ip(_RET_IP_)); + switch (mode) { + case KCOV_MODE_UNIQUE_PC: + pc_index =3D READ_ONCE(*guard); + if (unlikely(!pc_index)) + pc_index =3D init_pc_guard(guard); + + /* + * Use the bitmap for coverage deduplication. We assume both + * s.bitmap and s.trace are non-NULL. + */ + if (likely(pc_index < current->kcov_state.bitmap_size)) + if (__test_and_set_bit(pc_index, + current->kcov_state.bitmap)) + return; + /* + * If the PC is new, or the bitmap is too small, write PC to the + * trace. + */ + fallthrough; + case KCOV_MODE_TRACE_PC: + kcov_append_to_buffer(current->kcov_state.trace, + current->kcov_state.trace_size, + canonicalize_ip(_RET_IP_)); + break; + default: + return; + } } EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard); =20 @@ -239,7 +304,7 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard_init); #else /* !CONFIG_KCOV_UNIQUE */ void notrace __sanitizer_cov_trace_pc(void) { - if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) + if (get_kcov_mode(current) !=3D KCOV_MODE_TRACE_PC) return; =20 kcov_append_to_buffer(current->kcov_state.trace, @@ -257,7 +322,7 @@ static void notrace write_comp_data(u64 type, u64 arg1,= u64 arg2, u64 ip) u64 *trace; =20 t =3D current; - if (!check_kcov_mode(KCOV_MODE_TRACE_CMP, t)) + if (get_kcov_mode(t) !=3D KCOV_MODE_TRACE_CMP) return; =20 ip =3D canonicalize_ip(ip); @@ -376,7 +441,7 @@ static void kcov_start(struct task_struct *t, struct kc= ov *kcov, /* Cache in task struct for performance. */ t->kcov_state =3D *state; barrier(); - /* See comment in check_kcov_mode(). */ + /* See comment in get_kcov_mode(). */ WRITE_ONCE(t->kcov_mode, mode); } =20 @@ -410,6 +475,10 @@ static void kcov_reset(struct kcov *kcov) kcov->mode =3D KCOV_MODE_INIT; kcov->remote =3D false; kcov->remote_size =3D 0; + kcov->state.trace =3D kcov->state.area; + kcov->state.trace_size =3D kcov->state.size; + kcov->state.bitmap =3D NULL; + kcov->state.bitmap_size =3D 0; kcov->state.sequence++; } =20 @@ -550,18 +619,23 @@ static int kcov_close(struct inode *inode, struct fil= e *filep) return 0; } =20 -static int kcov_get_mode(unsigned long arg) +static enum kcov_mode kcov_arg_to_mode(unsigned long arg, int *error) { - if (arg =3D=3D KCOV_TRACE_PC) + if (arg =3D=3D KCOV_TRACE_PC) { return KCOV_MODE_TRACE_PC; - else if (arg =3D=3D KCOV_TRACE_CMP) + } else if (arg =3D=3D KCOV_TRACE_CMP) { #ifdef CONFIG_KCOV_ENABLE_COMPARISONS return KCOV_MODE_TRACE_CMP; #else - return -ENOTSUPP; + if (error) + *error =3D -ENOTSUPP; + return KCOV_MODE_INVALID; #endif - else - return -EINVAL; + } else { + if (error) + *error =3D -EINVAL; + return KCOV_MODE_INVALID; + } } =20 /* @@ -596,12 +670,47 @@ static inline bool kcov_check_handle(u64 handle, bool= common_valid, return false; } =20 +static long kcov_handle_unique_enable(struct kcov *kcov, + unsigned long bitmap_words) +{ + struct task_struct *t =3D current; + + if (!IS_ENABLED(CONFIG_KCOV_UNIQUE)) + return -ENOTSUPP; + if (kcov->mode !=3D KCOV_MODE_INIT || !kcov->state.area) + return -EINVAL; + if (kcov->t !=3D NULL || t->kcov !=3D NULL) + return -EBUSY; + + /* + * Cannot use zero-sized bitmap, also the bitmap must leave at least two + * words for the trace. + */ + if ((!bitmap_words) || (bitmap_words >=3D (kcov->state.size - 1))) + return -EINVAL; + + kcov->state.bitmap_size =3D bitmap_words * sizeof(unsigned long) * 8; + kcov->state.bitmap =3D kcov->state.area; + kcov->state.trace_size =3D kcov->state.size - bitmap_words; + kcov->state.trace =3D ((unsigned long *)kcov->state.area + bitmap_words); + + kcov_fault_in_area(kcov); + kcov->mode =3D KCOV_MODE_UNIQUE_PC; + kcov_start(t, kcov, kcov->mode, &kcov->state); + kcov->t =3D t; + /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ + kcov_get(kcov); + + return 0; +} + static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd, unsigned long arg) { struct task_struct *t; unsigned long flags, unused; - int mode, i; + enum kcov_mode mode; + int error =3D 0, i; struct kcov_remote_arg *remote_arg; struct kcov_remote *remote; =20 @@ -619,9 +728,9 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, t =3D current; if (kcov->t !=3D NULL || t->kcov !=3D NULL) return -EBUSY; - mode =3D kcov_get_mode(arg); - if (mode < 0) - return mode; + mode =3D kcov_arg_to_mode(arg, &error); + if (mode =3D=3D KCOV_MODE_INVALID) + return error; kcov_fault_in_area(kcov); kcov->mode =3D mode; kcov_start(t, kcov, mode, &kcov->state); @@ -629,6 +738,8 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); return 0; + case KCOV_UNIQUE_ENABLE: + return kcov_handle_unique_enable(kcov, arg); case KCOV_DISABLE: /* Disable coverage for the current task. */ unused =3D arg; @@ -647,9 +758,9 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, if (kcov->t !=3D NULL || t->kcov !=3D NULL) return -EBUSY; remote_arg =3D (struct kcov_remote_arg *)arg; - mode =3D kcov_get_mode(remote_arg->trace_mode); - if (mode < 0) - return mode; + mode =3D kcov_arg_to_mode(remote_arg->trace_mode, &error); + if (mode =3D=3D KCOV_MODE_INVALID) + return error; if ((unsigned long)remote_arg->area_size > LONG_MAX / sizeof(unsigned long)) return -EINVAL; --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A88992E973D for ; Thu, 26 Jun 2025 13:42:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945350; cv=none; b=ZBdvjRVwHt2axDps3YePMdVX96Xmov0DXbfol40t7oGGV7t1e4iib1yAkMZ7ocq+0E/nD+2D3JFofplPv/qUQQZRaHl/TT6D/H51F3urtwuoCnOi9IVXMWCzp3yVJG7SJpKemuNwRO/fPI5NOAB2CmfzouS228O6rrIDUpgInC8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945350; c=relaxed/simple; bh=6fEu5xm2trEbRlj3pvMFD8BmZuIrIsPIDCm6Uq3X55M=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=LtbK/YCe9JFJUL2x1Y78QtO9CXEimnWmM2QLFHOMZYFGxlGZKSukU2fSA0JnZ8lSF5C7SeOn+CE8luWLbbPybcMkCShBcdt97uTLVJnFWCE5Vfp39/k9JAN52zlZ+POfGl8OKBnv0BdbctABVLZTRduBbewhsl6W5a2chyB14O4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=4km5mbwI; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="4km5mbwI" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4530c186394so4466555e9.0 for ; Thu, 26 Jun 2025 06:42:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945347; x=1751550147; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=aC+obdeMHn5fESAyhGJX79KJV5tcOZyYRgpJyGh+V2A=; b=4km5mbwIHgwPTw4+ZzYVNDaxcI7GRq4HMpe0ZFuaRqZ/7zEqamvtYn8ur2NDuvbvyh WZnoIqB2+wKGmLGu3e4q7/VJHva5Urh1qdLVc2fZVhDl8SiAOLDcCCXR+GSo4rCqBAa7 BLwzhf3jzhEEnvZCbojRlsAHOxlIiGsXKSlfnaa0KehVuIN3VG0B/+ZcogrTuvWtRLEe qKUaPoS4J6nDgMmSDLUATWpwW0UDr5AXHLrw/a3dgoMOT4mICZAuaKsmXTUXD5D7Byp6 T2OnSY4+Iv3j1a3vfqHtS4PhXX1Sc9jdQbuMV6Hv22tjZPRxR/6aOWAuljeVbTdLRcjy q/Sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945347; x=1751550147; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=aC+obdeMHn5fESAyhGJX79KJV5tcOZyYRgpJyGh+V2A=; b=v8syVBY32Y2ZeyaT3go3pSbsQ61BSK+4r09+rEZmi3JgiVolmr6DUDX4678CVejEOq HMipyjxyWXXz57wbKdLN6kYg1DlRovlQ5Ld6rmrUIw/uOr1opWebCAJwO9Kcmj0AYrfA CW5uj7nt6FjMzEn2P9m4HQh4TKgYJAPaFCdWRPjb2o6xOi5brczrTGFb9BA5ZBQGjYgN eGdlATTmLl1iBhF40nrGDwb0ha/VvCppXPucgvcqtxIty3C9WWkOytgvEEP5DCTsqVh7 ypT4DvGxaFzfi/0rU/y4Bs7WshjW6f8sZ39KokDRV7L/Zy8tyxZb2vqcCeA4vsbuKHCV gD3A== X-Forwarded-Encrypted: i=1; AJvYcCVomZWOMHCW6cIfE5QshRPJZCkuoPlUsCQ305bvPx7KJ7s9tLd8xr4pY5ZhL04Dmyo05tN64ipX6t+GD9s=@vger.kernel.org X-Gm-Message-State: AOJu0Ywh9HSb4zJ21eZtQdqxV2878bTcKO8K/VZ05YJRaWHMQvz1sXYx ic7iUrSOfjObXT0Ecpl0CidQ2UFOxy7xJCVdZDyfxMRgholTzerRbTmQJMT7krKySzbtDP3Oop6 x4a5AXQ== X-Google-Smtp-Source: AGHT+IGWO+HrAaqGj2gtoSP/kfGQbklHzcGbtW41p+3xOWzJKYf8BaOxWZt7gmFhkNW4P0nR4xu2cE6r/YY= X-Received: from wmbhe15.prod.google.com ([2002:a05:600c:540f:b0:43c:ef7b:ffac]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:3590:b0:453:6ca:16a6 with SMTP id 5b1f17b1804b1-45381ab7e02mr85005005e9.10.1750945347145; Thu, 26 Jun 2025 06:42:27 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:56 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-10-glider@google.com> Subject: [PATCH v2 09/11] kcov: add ioctl(KCOV_RESET_TRACE) From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Provide a mechanism to reset the coverage for the current task without writing directly to the coverage buffer. This is slower, but allows the fuzzers to map the coverage buffer as read-only, making it harder to corrupt. Signed-off-by: Alexander Potapenko --- v2: - Update code to match the new description of struct kcov_state --- Documentation/dev-tools/kcov.rst | 26 ++++++++++++++++++++++++++ include/uapi/linux/kcov.h | 1 + kernel/kcov.c | 15 +++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kco= v.rst index 6446887cd1c92..e215c0651e16d 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst @@ -470,3 +470,29 @@ local tasks spawned by the process and the global task= that handles USB bus #1: perror("close"), exit(1); return 0; } + + +Resetting coverage with an KCOV_RESET_TRACE +------------------------------------------- + +The ``KCOV_RESET_TRACE`` ioctl provides a mechanism to clear collected cov= erage +data for the current task. It resets the program counter (PC) trace and, if +``KCOV_UNIQUE_ENABLE`` mode is active, also zeroes the associated bitmap. + +The primary use case for this ioctl is to enhance safety during fuzzing. +Normally, a user could map the kcov buffer with ``PROT_READ | PROT_WRITE``= and +reset the trace from the user-space program. However, when fuzzing system = calls, +the kernel itself might inadvertently write to this shared buffer, corrupt= ing +the coverage data. + +To prevent this, a fuzzer can map the buffer with ``PROT_READ`` and use +``ioctl(fd, KCOV_RESET_TRACE, 0)`` to safely clear the buffer from the ker= nel +side before each fuzzing iteration. + +Note that: + +* This ioctl is safer but slower than directly writing to the shared memory + buffer due to the overhead of a system call. +* ``KCOV_RESET_TRACE`` is itself a system call, and its execution will be = traced + by kcov. Consequently, immediately after the ioctl returns, cover[0] wil= l be + greater than 0. diff --git a/include/uapi/linux/kcov.h b/include/uapi/linux/kcov.h index e743ee011eeca..8ab77cc3afa76 100644 --- a/include/uapi/linux/kcov.h +++ b/include/uapi/linux/kcov.h @@ -23,6 +23,7 @@ struct kcov_remote_arg { #define KCOV_DISABLE _IO('c', 101) #define KCOV_REMOTE_ENABLE _IOW('c', 102, struct kcov_remote_arg) #define KCOV_UNIQUE_ENABLE _IOW('c', 103, unsigned long) +#define KCOV_RESET_TRACE _IO('c', 104) =20 enum { /* diff --git a/kernel/kcov.c b/kernel/kcov.c index 2a4edbaad50d0..1693004d89764 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -740,6 +740,21 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsign= ed int cmd, return 0; case KCOV_UNIQUE_ENABLE: return kcov_handle_unique_enable(kcov, arg); + case KCOV_RESET_TRACE: + unused =3D arg; + if (unused !=3D 0 || current->kcov !=3D kcov) + return -EINVAL; + t =3D current; + if (WARN_ON(kcov->t !=3D t)) + return -EINVAL; + mode =3D kcov->mode; + if (mode < KCOV_MODE_TRACE_PC) + return -EINVAL; + if (kcov->state.bitmap) + bitmap_zero(kcov->state.bitmap, + kcov->state.bitmap_size); + WRITE_ONCE(kcov->state.trace[0], 0); + return 0; case KCOV_DISABLE: /* Disable coverage for the current task. */ unused =3D arg; --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73EEE2E7178 for ; Thu, 26 Jun 2025 13:42:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945353; cv=none; b=rvUBIlLQqkrwC9zRC2p8sqDPqSZAygmeE4ySj8RFd1+Oer2jA82WnqU9MBfip19dlxe+laV6lBmPLvJgbkrOPhSV2sR8cloqw3UCGPADW5J1ND7uSiRq7LsdOdofZ0g6Z5kpTD8VIACvbPmV+o+tLOb95+nhOHi1EsW1LX0IZFU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945353; c=relaxed/simple; bh=6Sim0Svh0po+AOrS5Z99BcPUVmlUUB1YXJVhr54SynE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YBg4EPTwpMd3DrduPHs4RXHgbIbs4510D7ZvGD9qXhmbFcChpM1mkqRZA14Rf4btSbNodlY5YenP1uwpq011lotgRLfqKRn6nsmZOUm3eI7k5wA6GtBDAQe/DPPo1xclVYqdw7OOY5Lxa1v4eRQot1hzEYx0SvFgDWprqXha5MM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=UCJQDb5Y; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="UCJQDb5Y" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4535ee06160so7077895e9.3 for ; Thu, 26 Jun 2025 06:42:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945350; x=1751550150; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=27NsffT4riRoTxmVby2GFeNcIx8l/sjMhtQmARW+nyU=; b=UCJQDb5YZiW+xNcxw9tZW649mxxgFEvZ6rUS5MSGSgAXELzbo/Mtw0Z1lbMGAfwpjc i5ebNnuiqRPxNbVYy2xYnH2LGGYcl51qY1zXLEmSHv2dVnMlD38U0COj+m0tlhcx41x+ A8DQa3t884e8B4Eun5C1/XxrksuG/QOisoVlkX2qF+6LnNbhCVTVXuWloDYwQr+CplWw YQThuTSb+fuRIq7iStkFxXNZDRefrPVTK3ficdDCXUvkV2W2fc+RC5aJcuq8LoFDsI9x FBdqkRUWEc72KZNRJDNBt0E6ucMESecNg8NXUmTmUDqT9aWMncmjmT58eQgM2UIg9iAz nOKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945350; x=1751550150; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=27NsffT4riRoTxmVby2GFeNcIx8l/sjMhtQmARW+nyU=; b=E96hsq4cw+Kd7fb0NNUC7H0Mbp7MBr4UEeyzW+Y5iFVTiWxcVC4TU2ypF+R0tupbUh hVoMI60ki46pv6TiuGZxWlvau78KHia3dlof8pHdVp5i/gzYwxoHHIBie7GPuHf3S7HW KXon9/C2rhBSaUV5tuoNkEmet+3G4qZp76Ti26PwB0o9JajmwgFu6q14jprLrpc606WO pOIY7YrqsAxTqTzAxsOTYteOfvjHF2NAK4XPx4IYaAoOuey3DGZlMzj0TFRl/OaRvHon kf+rvYH3nA95zkbT1z+rIUgZcWuxbIZQocXU3iMzC7YJgzSrnoWgKSifXesqe6Ey3eIh l/ag== X-Forwarded-Encrypted: i=1; AJvYcCV+5Nl5DNyLFzmwxi+3dhZfBi8P1zpPRw+Do6W8Z+0HHdzLPDFONtDtXI65vonWELhuGvN28eNMy514/NA=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/aH1CbtmEG3KT0ZbASUW75xOnjJFzBmDL6LUg//As4KB44cwR H9WfGJFTpLMRewlhSbiX/9QCqWL8nlec84EzrDCuDGDrEoX43hmplATY1Qs/K+6cWyU2DTb/uC7 xLvdlsA== X-Google-Smtp-Source: AGHT+IGZB0ehnepJgPiwUdBRqsv8DxeTaw+Ry2Dm9goNImao5iIjKM4uY1X1cr+kjxiTD848f50hBFx1HPc= X-Received: from wmbhj16.prod.google.com ([2002:a05:600c:5290:b0:440:60ac:3f40]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:3b03:b0:453:a88:d509 with SMTP id 5b1f17b1804b1-45381aa4972mr90416265e9.10.1750945349795; Thu, 26 Jun 2025 06:42:29 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:57 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-11-glider@google.com> Subject: [PATCH v2 10/11] kcov: selftests: add kcov_test From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Implement test fixtures for testing different combinations of coverage collection modes: - unique and non-unique coverage; - collecting PCs and comparison arguments; - mapping the buffer as RO and RW. To build: $ make -C tools/testing/selftests/kcov kcov_test Signed-off-by: Alexander Potapenko --- MAINTAINERS | 1 + tools/testing/selftests/kcov/Makefile | 6 + tools/testing/selftests/kcov/kcov_test.c | 364 +++++++++++++++++++++++ 3 files changed, 371 insertions(+) create mode 100644 tools/testing/selftests/kcov/Makefile create mode 100644 tools/testing/selftests/kcov/kcov_test.c diff --git a/MAINTAINERS b/MAINTAINERS index 5bbc78b0fa6ed..0ec909e085077 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12833,6 +12833,7 @@ F: include/linux/kcov_types.h F: include/uapi/linux/kcov.h F: kernel/kcov.c F: scripts/Makefile.kcov +F: tools/testing/selftests/kcov/ =20 KCSAN M: Marco Elver diff --git a/tools/testing/selftests/kcov/Makefile b/tools/testing/selftest= s/kcov/Makefile new file mode 100644 index 0000000000000..08abf8b60bcf9 --- /dev/null +++ b/tools/testing/selftests/kcov/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +LDFLAGS +=3D -static + +TEST_GEN_PROGS :=3D kcov_test + +include ../lib.mk diff --git a/tools/testing/selftests/kcov/kcov_test.c b/tools/testing/selft= ests/kcov/kcov_test.c new file mode 100644 index 0000000000000..4d3ca41f28af4 --- /dev/null +++ b/tools/testing/selftests/kcov/kcov_test.c @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test the kernel coverage (/sys/kernel/debug/kcov). + * + * Copyright 2025 Google LLC. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest_harness.h" + +/* Normally these defines should be provided by linux/kcov.h, but they are= n't there yet. */ +#define KCOV_UNIQUE_ENABLE _IOW('c', 103, unsigned long) +#define KCOV_RESET_TRACE _IO('c', 104) + +#define COVER_SIZE (64 << 10) +#define BITMAP_SIZE (4 << 10) + +#define DEBUG_COVER_PCS 0 + +FIXTURE(kcov) +{ + int fd; + unsigned long *mapping; + size_t mapping_size; +}; + +FIXTURE_VARIANT(kcov) +{ + int mode; + bool fast_reset; + bool map_readonly; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov, mode_trace_pc) +{ + /* clang-format on */ + .mode =3D KCOV_TRACE_PC, + .fast_reset =3D true, + .map_readonly =3D false, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov, mode_trace_cmp) +{ + /* clang-format on */ + .mode =3D KCOV_TRACE_CMP, + .fast_reset =3D true, + .map_readonly =3D false, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov, reset_ioctl_rw) +{ + /* clang-format on */ + .mode =3D KCOV_TRACE_PC, + .fast_reset =3D false, + .map_readonly =3D false, +}; + +FIXTURE_VARIANT_ADD(kcov, reset_ioctl_ro) +/* clang-format off */ +{ + /* clang-format on */ + .mode =3D KCOV_TRACE_PC, + .fast_reset =3D false, + .map_readonly =3D true, +}; + +int kcov_open_init(struct __test_metadata *_metadata, unsigned long size, + int prot, unsigned long **out_mapping) +{ + unsigned long *mapping; + + /* A single fd descriptor allows coverage collection on a single thread. = */ + int fd =3D open("/sys/kernel/debug/kcov", O_RDWR); + + ASSERT_NE(fd, -1) + { + perror("open"); + } + + EXPECT_EQ(ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE), 0) + { + perror("ioctl KCOV_INIT_TRACE"); + close(fd); + } + + /* Mmap buffer shared between kernel- and user-space. */ + mapping =3D (unsigned long *)mmap(NULL, size * sizeof(unsigned long), + prot, MAP_SHARED, fd, 0); + ASSERT_NE((void *)mapping, MAP_FAILED) + { + perror("mmap"); + close(fd); + } + *out_mapping =3D mapping; + + return fd; +} + +FIXTURE_SETUP(kcov) +{ + int prot =3D variant->map_readonly ? PROT_READ : (PROT_READ | PROT_WRITE); + + /* Read-only mapping is incompatible with fast reset. */ + ASSERT_FALSE(variant->map_readonly && variant->fast_reset); + + self->mapping_size =3D COVER_SIZE; + self->fd =3D kcov_open_init(_metadata, self->mapping_size, prot, + &(self->mapping)); + + /* Enable coverage collection on the current thread. */ + EXPECT_EQ(ioctl(self->fd, KCOV_ENABLE, variant->mode), 0) + { + perror("ioctl KCOV_ENABLE"); + munmap(self->mapping, COVER_SIZE * sizeof(unsigned long)); + close(self->fd); + } +} + +void kcov_uninit_close(struct __test_metadata *_metadata, int fd, + unsigned long *mapping, size_t size) +{ + /* Disable coverage collection for the current thread. */ + EXPECT_EQ(ioctl(fd, KCOV_DISABLE, 0), 0) + { + perror("ioctl KCOV_DISABLE"); + } + + /* Free resources. */ + EXPECT_EQ(munmap(mapping, size * sizeof(unsigned long)), 0) + { + perror("munmap"); + } + + EXPECT_EQ(close(fd), 0) + { + perror("close"); + } +} + +FIXTURE_TEARDOWN(kcov) +{ + kcov_uninit_close(_metadata, self->fd, self->mapping, + self->mapping_size); +} + +void dump_collected_pcs(struct __test_metadata *_metadata, unsigned long *= cover, + size_t start, size_t end) +{ + int i =3D 0; + + TH_LOG("Collected %lu PCs", end - start); +#if DEBUG_COVER_PCS + for (i =3D start; i < end; i++) + TH_LOG("0x%lx", cover[i + 1]); +#endif +} + +/* Coverage collection helper without assertions. */ +unsigned long collect_coverage_unchecked(struct __test_metadata *_metadata, + unsigned long *cover, bool dump) +{ + unsigned long before, after; + + before =3D __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + /* + * Call the target syscall call. Here we use read(-1, NULL, 0) as an exam= ple. + * This will likely return an error (-EFAULT or -EBADF), but the goal is = to + * collect coverage for the syscall's entry/exit paths. + */ + read(-1, NULL, 0); + + after =3D __atomic_load_n(&cover[0], __ATOMIC_RELAXED); + + if (dump) + dump_collected_pcs(_metadata, cover, before, after); + return after - before; +} + +unsigned long collect_coverage_once(struct __test_metadata *_metadata, + unsigned long *cover) +{ + unsigned long collected =3D + collect_coverage_unchecked(_metadata, cover, /*dump*/ true); + + /* Coverage must be non-zero. */ + EXPECT_GT(collected, 0); + return collected; +} + +void reset_coverage(struct __test_metadata *_metadata, bool fast, int fd, + unsigned long *mapping) +{ + unsigned long count; + + if (fast) { + __atomic_store_n(&mapping[0], 0, __ATOMIC_RELAXED); + } else { + EXPECT_EQ(ioctl(fd, KCOV_RESET_TRACE, 0), 0) + { + perror("ioctl KCOV_RESET_TRACE"); + } + count =3D __atomic_load_n(&mapping[0], __ATOMIC_RELAXED); + EXPECT_NE(count, 0); + } +} + +TEST_F(kcov, kcov_basic_syscall_coverage) +{ + unsigned long first, second, before, after, i; + + /* Reset coverage that may be left over from the fixture setup. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + + /* Collect the coverage for a single syscall two times in a row. */ + first =3D collect_coverage_once(_metadata, self->mapping); + second =3D collect_coverage_once(_metadata, self->mapping); + /* Collected coverage should not differ too much. */ + EXPECT_GT(first * 10, second); + EXPECT_GT(second * 10, first); + + /* Now reset the buffer and collect the coverage again. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + collect_coverage_once(_metadata, self->mapping); + + /* Now try many times to fill up the buffer. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + while (collect_coverage_unchecked(_metadata, self->mapping, + /*dump*/ false)) { + /* Do nothing. */ + } + before =3D __atomic_load_n(&(self->mapping[0]), __ATOMIC_RELAXED); + /* + * Resetting with ioctl may still generate some coverage, but much less + * than there was before. + */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + after =3D __atomic_load_n(&(self->mapping[0]), __ATOMIC_RELAXED); + EXPECT_GT(before, after); + /* Collecting coverage after reset will now succeed. */ + collect_coverage_once(_metadata, self->mapping); +} + +FIXTURE(kcov_uniq) +{ + int fd; + unsigned long *mapping; + size_t mapping_size; + unsigned long *bitmap; + size_t bitmap_size; + unsigned long *cover; + size_t cover_size; +}; + +FIXTURE_VARIANT(kcov_uniq) +{ + bool fast_reset; + bool map_readonly; +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov_uniq, fast_rw) +{ + /* clang-format on */ + .fast_reset =3D true, + .map_readonly =3D false, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov_uniq, slow_rw) +{ + /* clang-format on */ + .fast_reset =3D false, + .map_readonly =3D false, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(kcov_uniq, slow_ro) +{ + /* clang-format on */ + .fast_reset =3D false, + .map_readonly =3D true, +}; + +FIXTURE_SETUP(kcov_uniq) +{ + int prot =3D variant->map_readonly ? PROT_READ : (PROT_READ | PROT_WRITE); + + /* Read-only mapping is incompatible with fast reset. */ + ASSERT_FALSE(variant->map_readonly && variant->fast_reset); + + self->mapping_size =3D COVER_SIZE; + self->fd =3D kcov_open_init(_metadata, self->mapping_size, prot, + &(self->mapping)); + + /* Enable coverage collection on the current thread. */ + EXPECT_EQ(ioctl(self->fd, KCOV_UNIQUE_ENABLE, BITMAP_SIZE), 0) + { + perror("ioctl KCOV_ENABLE"); + munmap(self->mapping, COVER_SIZE * sizeof(unsigned long)); + close(self->fd); + } +} + +FIXTURE_TEARDOWN(kcov_uniq) +{ + kcov_uninit_close(_metadata, self->fd, self->mapping, + self->mapping_size); +} + +TEST_F(kcov_uniq, kcov_uniq_coverage) +{ + unsigned long first, second, before, after, i; + + /* Reset coverage that may be left over from the fixture setup. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + + /* + * Collect the coverage for a single syscall two times in a row. + * Use collect_coverage_unchecked(), because it may return zero coverage. + */ + first =3D collect_coverage_unchecked(_metadata, self->mapping, + /*dump*/ true); + second =3D collect_coverage_unchecked(_metadata, self->mapping, + /*dump*/ true); + + /* Now reset the buffer and collect the coverage again. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + collect_coverage_once(_metadata, self->mapping); + + /* Now try many times to saturate the unique coverage bitmap. */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + for (i =3D 0; i < 1000; i++) + collect_coverage_unchecked(_metadata, self->mapping, + /*dump*/ false); + /* Another invocation of collect_coverage_unchecked() should not produce = new coverage. */ + EXPECT_EQ(collect_coverage_unchecked(_metadata, self->mapping, + /*dump*/ false), + 0); + + before =3D __atomic_load_n(&(self->mapping[0]), __ATOMIC_RELAXED); + /* + * Resetting with ioctl may still generate some coverage, but much less + * than there was before. + */ + reset_coverage(_metadata, variant->fast_reset, self->fd, self->mapping); + after =3D __atomic_load_n(&(self->mapping[0]), __ATOMIC_RELAXED); + EXPECT_GT(before, after); + /* Collecting coverage after reset will now succeed. */ + collect_coverage_once(_metadata, self->mapping); +} + +TEST_HARNESS_MAIN --=20 2.50.0.727.gbf7dc18ff4-goog From nobody Wed Oct 8 16:06:38 2025 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03A442EA47E for ; Thu, 26 Jun 2025 13:42:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945356; cv=none; b=iFA8sXHWmkepnIFQYtSwHGmSAJ+QorOAPzj1bB8W5Ls6bdu0HKSntaUIf/4RnDsAiWCsFSlc4VUKSyzlSdEQUlTWBR5KXRavqd/3PVqk0+kBCDd62KGPfFLsmaUvYOcCrv0BRxNw8XlyZK62jsigoHhr1YpFRnmofHg3fsvlPAI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750945356; c=relaxed/simple; bh=w15P/PQBicPWdOby0zTbVfr+DY+39BuDdIlOJm29TiM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WOBF7u4gYh6Od+htQlXuGp0SKHqfaf2RIc72NQc8ZygmKWyeJGc1040ajm6Srmtq+jMvt/yzcqJKfD9RPhWU6KqVvUNDULlOseV62p4K/7r+XZAdym0sotVtjmcerw2P/h3lYh4Y4JCfWrgj/4UZBnp9KXgpRk3eK9g7Km09phM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--glider.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=KTc4vahT; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--glider.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KTc4vahT" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4537f56ab74so6567435e9.3 for ; Thu, 26 Jun 2025 06:42:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1750945352; x=1751550152; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hl3fNVnAsDqURU0FpEqnT2FFnl4Elpb08ixBMdGUI4M=; b=KTc4vahTg7iEyEcJUleLcOsjZvpJ5COtGcRfgiYiOqQ4+XR0RBs2bnAJpeGuss5kEN 7/znuhrvwldyb9iUx4p1TLIxR7cdHBfbUJe9NJPKw+YwaVIbMzj81o7OAHvK5c8Wkb1i GbAYzvwFf8YPsDx+0y8J4ChAk0uM3uvP5fr/OipNXnQkV8vYWKfGy7sNS+2q00KXVmmg DWrRwIJ7i8QOh0aaUp9Cv4qj69HK15pBNeTC7K5agO7PfipM47u4I2G3LOQrIkAnkdY9 7GSdiL9XHRSoST/9vQi73LYDYfydRryDIfEAhD38c+AN9aT5vqTd4pSbxn8cc0hye0Py VnkA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750945352; x=1751550152; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hl3fNVnAsDqURU0FpEqnT2FFnl4Elpb08ixBMdGUI4M=; b=Ij+wG/IBCvs4qSZGO+uDp53D5nRYK5kCgZiGDUPOZ5e885WhWOsIv5wIBjorQhwiUn AYPsmy+ocMZ1/2pyLtquisFvZnA06azISdVzQ01XG6/o7b+l2FXRI8zcixciR0GA5aUt 5FHwRCjtqxdwfxaiV0xppyU+DIDciWjWiBGkbVrNc3C7+LmwaR+36mecY+qw/PkF+pHw GWRypJQjWPacqg71zrrTEvsJKxa88uVzp96+v14KGhLQc4gFR1C2p+m1zpW2I/zesYzx 1pveVepDVfUSCZziSxF1x/5bVHHfM83BcThdgFJ9/Ki96mtIg01CFLXIKQQiLvl3aFG0 7DDQ== X-Forwarded-Encrypted: i=1; AJvYcCV9lspF2KEaxv0f2tCqfGGqB8uZNNvygZ6H3mBT5MeBiFBnhuJR+/QgJn42p/4zk47CdrLq9c9NqAEHf3M=@vger.kernel.org X-Gm-Message-State: AOJu0YwnhkDawjLIEfSgSYBHOtBGaj5bKFCDFKqMsxeCgufwTfyR1i3w bXleZdsB6hcP/DWbiqPvnPg+qD41lNc/70FFUzluW8BfItkFeb6Zz2yHgS4sE4bOChH43ezPa+P EU5OBZw== X-Google-Smtp-Source: AGHT+IENWlCXe8zC3L+/iHXjmM2xaIYjroNIQok/FPBEWl0gkEtFHeIYnHyQb7vvDlNbdrCSTkiUDCFE35w= X-Received: from wmbej3.prod.google.com ([2002:a05:600c:3e83:b0:453:8ab1:7b7f]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:600c:3590:b0:453:6ca:16a6 with SMTP id 5b1f17b1804b1-45381ab7e02mr85008665e9.10.1750945352580; Thu, 26 Jun 2025 06:42:32 -0700 (PDT) Date: Thu, 26 Jun 2025 15:41:58 +0200 In-Reply-To: <20250626134158.3385080-1-glider@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250626134158.3385080-1-glider@google.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250626134158.3385080-12-glider@google.com> Subject: [PATCH v2 11/11] kcov: use enum kcov_mode in kcov_mode_enabled() From: Alexander Potapenko To: glider@google.com Cc: quic_jiangenj@quicinc.com, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, Aleksandr Nogikh , Andrey Konovalov , Borislav Petkov , Dave Hansen , Dmitry Vyukov , Ingo Molnar , Josh Poimboeuf , Marco Elver , Peter Zijlstra , Thomas Gleixner Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace the remaining declarations of `unsigned int mode` with `enum kcov_mode mode`. No functional change. Signed-off-by: Alexander Potapenko --- kernel/kcov.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/kcov.c b/kernel/kcov.c index 1693004d89764..62ce4c65f79fa 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -951,7 +951,7 @@ static const struct file_operations kcov_fops =3D { * collecting coverage and copies all collected coverage into the kcov are= a. */ =20 -static inline bool kcov_mode_enabled(unsigned int mode) +static inline bool kcov_mode_enabled(enum kcov_mode mode) { return (mode & ~KCOV_IN_CTXSW) !=3D KCOV_MODE_DISABLED; } @@ -959,7 +959,7 @@ static inline bool kcov_mode_enabled(unsigned int mode) static void kcov_remote_softirq_start(struct task_struct *t) { struct kcov_percpu_data *data =3D this_cpu_ptr(&kcov_percpu_data); - unsigned int mode; + enum kcov_mode mode; =20 mode =3D READ_ONCE(t->kcov_mode); barrier(); @@ -1135,7 +1135,7 @@ void kcov_remote_stop(void) { struct task_struct *t =3D current; struct kcov *kcov; - unsigned int mode; + enum kcov_mode mode; void *area, *trace; unsigned int size, trace_size; int sequence; --=20 2.50.0.727.gbf7dc18ff4-goog