From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.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 27851231C9C for ; Wed, 16 Apr 2025 08:55:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793703; cv=none; b=C4FVDdSPr41xKNLxYnTHRPVVfEWzrACpIhWJ7WuYXg/VI7Q6sK/PIfYS1x8lHPF5iwbUlM2FS7fTIlbYOupbYfRHY9+Mn9Yakmf7Uah7Y8D09fc3bDgbcoJldF8a0ywmIri4nEzV6rVb1/9sdIgwm6zT4Yf/IrkSTmcgn7rEDQw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793703; c=relaxed/simple; bh=KtYa9ptAIenoFcZebd/OoA0MHCY7YUeNZ+OuOJPwff0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Bw0jJMMN4/4hvXk9ojmaf4+FPg3sP+mw5Fwym13mPMwwu4FpG2jatVkuxX7OJFgr9TQIRb4tIi6yCoXJkpNbGiZXmDF0BGUmf9Ur1mc5b3C5e3oAp8p6P3OSqTmfHK80UukmY4GWZwZNtAAzS4P+lmz+eam5FHES9Qu7Sk2+qq8= 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=OBVlE+B5; arc=none smtp.client-ip=209.85.218.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="OBVlE+B5" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-ab39f65dc10so76233866b.1 for ; Wed, 16 Apr 2025 01:55:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793699; x=1745398499; 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=fawUJ+aFly0mZ/Doql3hbHEHCvseg6enUQu7sHu+ODc=; b=OBVlE+B5qfRvp6Rqu/5dKCjCJ3FixmFs1IcU9XnvDony1VCP0IPFuxe9KU4LcaYOON S2dCCTAvyEH0SU11uyXVhSsLp+RxbHnLPkYBCuBnrS9wCRvZebZo5bhaaNppxq1hFPJY W622invc3iYWT3tyRyLrbRl6EASjrDglBINDn1xPgx24WVcCJxqZ1HZysmecJEXAT26/ 7OWFlzlP7u+v+f9DrrgGEkohvkja5yalSXwMciURwD0mr9AZxNQJNgpy5O11qXR7EYHs lSZCfFoubYRMxHzibrcucvYClraQZbljeahE/Bk5YJqavUJQjpSW/tvk54BJg9bq70YP Q0Og== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793699; x=1745398499; 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=fawUJ+aFly0mZ/Doql3hbHEHCvseg6enUQu7sHu+ODc=; b=o1sI4JKxl6GTL/0y8LzxK+5S7Ha0VmLP/F86vkbQjBxExvCj67VdT2ylA45/ofHpX1 PzwoJub/M90iHmQEj+oaHOTJteei+Hx0NsrldFU5bHQafQk3RwO420HrOTiwXTfXNM2Q uGRhzfsjOzEUFtfm4pb8AlEfM/SHDu6BFLu4wagkh+g0TtferQD80D15KQyieLZjTG4q dFpBN6JQ7b8LS6PeFIlzWS3pkufk2Q8p+6Razrhr3QBmK9QjW13/eG4vXOd+35gZ/4BA tDsEEr+9ys/hyhvwEp912hUAwdXAUZiWaQna5fJOl4mYKaAXDg/IxkiBrPtCxvuhbP3I KD5g== X-Forwarded-Encrypted: i=1; AJvYcCUPlachGQ0LdbxvxSvt8lDVnySRncvI9ByNcPkNOnYIU8eZKQc3a3N7FMZ1XMOzB0TW6zr5dwOwYbYanIM=@vger.kernel.org X-Gm-Message-State: AOJu0YzfNmdVBwI/ECRdQaBBWu+Uh93+Kn0tEd6PkbkFTp/om35lH3K4 jyrtpzROMmDpGv1y2ZJoJumhW5xDVHJdom1vlDRDgX9B0TbE1cErPUIPkxguIJbBxcScAtwmE5I 47w== X-Google-Smtp-Source: AGHT+IFMpHxojJPc6OHaoIu0fIr+RlbRszpzoKA4cMK2zk+nFPapDuFTHF6A9VyK9BuvqoeWKMYRbb/SAa8= X-Received: from ejaz16.prod.google.com ([2002:a17:906:2410:b0:ac2:ea20:40ac]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:d2a:b0:ac7:efed:3ab with SMTP id a640c23a62f3a-acb429e5b2amr87507766b.21.1744793699499; Wed, 16 Apr 2025 01:54:59 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:39 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-2-glider@google.com> Subject: [PATCH 1/7] 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 --- 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..7cc6123c2baa4 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); } @@ -728,13 +730,15 @@ 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)))) + if (get_user(remote_num_handles, + (unsigned __user *)(arg + + offsetof(struct kcov_remote_arg, + num_handles)))) 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.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.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 06AB2233150 for ; Wed, 16 Apr 2025 08:55:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793706; cv=none; b=jS9iNuBfzr4NEIh06HDrPBf3U2xqqWypWn6u9G5UwGD5Ed9ZfDUFK88vdWyrbujSjK63ZFkGJhgG528jdw8xA0mVR/ghH0tO4Hu4sQxbJ3VbAguUHat/FmiRZliL61iM7DpLrYGhs/NXsx3VhvRNMfqKaLOv8LNtCVUl7Mgd7NU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793706; c=relaxed/simple; bh=Uv5ToHuVZz7bHbtTqmRT7fOen0Oq5f3Hx/xWPI1HKvQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hP773eVJWR+VW7FPWFQ8y5d9ck9jNMMCD0lJBXqlxEZN7iMsiBk6NHr0nL99Z/bIctPas5BSlUG6MJEw0Phz/l8I2848NrvP9Km4KwFPn8EAiCn+GyGSDUo8r1bIbooTP1o8oCT9UhhjxXX1lmdPSoC9OcXiFz7bkO9NYYqoBXw= 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=yS4BLKSm; arc=none smtp.client-ip=209.85.218.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="yS4BLKSm" Received: by mail-ej1-f74.google.com with SMTP id a640c23a62f3a-ac7791ecb7bso55557266b.0 for ; Wed, 16 Apr 2025 01:55:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793702; x=1745398502; 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=sEqgbWaFKnoyLR0T1Nn8MCFuEM6WZXK8ceBl3Z/X9PI=; b=yS4BLKSmD1axgvmEznsL4oZ+5twJBN7BOgeIffWXEqSKdVVK0pvP1YDSlhuUrqXXgJ dJSW5EjaXvQFNGs6GKPV4M6HbpoE+gBac+RPUozm+GsQD1bpKdETDVPptWUhaEEgxx2V 44OrTYxgu9pj6fdOHn9FS9OD6Hk9IagvJHHYUMj86MAX0aOON4FcvnjgMMV9xOyZPwtn 3BIo9yPv6U8ODIbpC1vzlPzmMekLh/10YVoXN950rJKLKf02VHDhHi1wMjuPABK9S6hg 6OYzvUQxA/ZnkrbDmsWJCUNeR8NI/2yiYhNZuhbDPlGKFAhHqkqGNDhLtUIb4Y54UyQo ecwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793702; x=1745398502; 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=sEqgbWaFKnoyLR0T1Nn8MCFuEM6WZXK8ceBl3Z/X9PI=; b=pdnlhgBUezxlYrAfLkMLrgvXzJCJ4ABsSzKTnEvRfoVz1f27GCQ4kThAUgNslaTqkw 4Ph3Dzg+Ks5Mop8VZ7lrhsjEPUeRwZdysZZQ1Zv07sQcKPkYezOe7z7mMpVND/LjhDzH 1S41nIkL0wUtfs/aECUV8UH3cSnx39snoETlPiLedYaCnMH66WpmE4A+1A0OWimAEO5x yl/yZxa0lMhmq/ZrkxbUpRT3qZ/Lok4VlgCEz9pDOoxKMkeo6Gt0GPWrBsLfVk0MplID f4pEGPe6xQpZTph6ElMIIiRPeSpB75aMbjq363tfkGqrdE4OoPXyMN3EyxAfh8n9NV1W cFGw== X-Forwarded-Encrypted: i=1; AJvYcCVOJZ/+L5Rna0L/RPSPrveCYmWb+ArEYc52oNZGkRYP0XL2TBCaS1xehFhIPWB7+15IrDVO0pfOJTTF/Ng=@vger.kernel.org X-Gm-Message-State: AOJu0YxQ0JyQ9uJhgAsMRkpJvCllbkOsaYRmb2qjw0JJ5yjFVGxIvNih bf3i/l1dlWG1qg5y5dWyH1IU4sFMRqTX3KvTbc6nnY99Xp4XWvYDG++u8fI/HslfONrsnu43mRp CTg== X-Google-Smtp-Source: AGHT+IHTW4YezaZ7fg7LTIC7A5D3OUE3b5Ej/z75hZGa2y0H+K2BY34cjdA8VLxASHdcc2NWYkjxvkTnEtg= X-Received: from ejce27.prod.google.com ([2002:a17:906:375b:b0:ac7:9acb:58d3]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:6091:b0:acb:37ae:619c with SMTP id a640c23a62f3a-acb427d0d30mr81725666b.15.1744793702149; Wed, 16 Apr 2025 01:55:02 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:40 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-3-glider@google.com> Subject: [PATCH 2/7] 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, mode, sequence) that are stored in various structures, into `struct kcov_state`, so that these fields can be easily passed around and manipulated. This prepares us for the upcoming change that will introduce more kcov state. Also update the MAINTAINERS entry. Signed-off-by: Alexander Potapenko --- MAINTAINERS | 1 + include/linux/kcov-state.h | 31 ++++++++ include/linux/kcov.h | 14 ++-- include/linux/sched.h | 16 +--- kernel/kcov.c | 149 ++++++++++++++++--------------------- 5 files changed, 106 insertions(+), 105 deletions(-) create mode 100644 include/linux/kcov-state.h diff --git a/MAINTAINERS b/MAINTAINERS index 00e94bec401e1..2f9bea40d9760 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12511,6 +12511,7 @@ 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-state.h F: include/linux/kcov.h F: include/uapi/linux/kcov.h F: kernel/kcov.c diff --git a/include/linux/kcov-state.h b/include/linux/kcov-state.h new file mode 100644 index 0000000000000..4c4688d01c616 --- /dev/null +++ b/include/linux/kcov-state.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_KCOV_STATE_H +#define _LINUX_KCOV_STATE_H + +#ifdef CONFIG_KCOV +struct kcov_state { + /* See kernel/kcov.c for more details. */ + /* + * Coverage collection mode enabled for this task (0 if disabled). + * This field is used for synchronization, so it is kept outside of + * the below struct. + */ + unsigned int mode; + + struct { + /* 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; + } s; +}; +#endif /* CONFIG_KCOV */ + +#endif /* _LINUX_KCOV_STATE_H */ diff --git a/include/linux/kcov.h b/include/linux/kcov.h index 932b4face1005..e1f7d793c1cb3 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; @@ -30,14 +30,14 @@ enum kcov_mode { 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; \ +#define kcov_prepare_switch(t) \ + do { \ + (t)->kcov_state.mode |=3D KCOV_IN_CTXSW; \ } while (0) =20 -#define kcov_finish_switch(t) \ - do { \ - (t)->kcov_mode &=3D ~KCOV_IN_CTXSW; \ +#define kcov_finish_switch(t) \ + do { \ + (t)->kcov_state.mode &=3D ~KCOV_IN_CTXSW; \ } while (0) =20 /* See Documentation/dev-tools/kcov.rst for usage details. */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 9c15365a30c08..70077ad51083c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1485,26 +1486,13 @@ 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; - - /* Size of the kcov_area: */ - unsigned int kcov_size; - - /* Buffer for coverage collection: */ - void *kcov_area; - + struct kcov_state kcov_state; /* KCOV descriptor wired with this task or NULL: */ struct kcov *kcov; =20 /* 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 7cc6123c2baa4..8fcbca236bec5 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -54,24 +55,16 @@ 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 +85,8 @@ 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; 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 { @@ -184,7 +173,7 @@ static notrace bool check_kcov_mode(enum kcov_mode need= ed_mode, */ if (!in_task() && !(in_softirq_really() && t->kcov_softirq)) return false; - mode =3D READ_ONCE(t->kcov_mode); + mode =3D READ_ONCE(t->kcov_state.mode); /* * There is some code that runs in interrupts but for which * in_interrupt() returns false (e.g. preempt_schedule_irq()). @@ -219,10 +208,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.s.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.s.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 +241,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.s.area; + max_pos =3D t->kcov_state.s.size * sizeof(unsigned long); =20 count =3D READ_ONCE(area[0]); =20 @@ -356,33 +345,31 @@ 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) + 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->s.size, + state->s.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.s =3D state->s; barrier(); - WRITE_ONCE(t->kcov_mode, mode); + /* See comment in check_kcov_mode(). */ + WRITE_ONCE(t->kcov_state.mode, state->mode); } =20 static void kcov_stop(struct task_struct *t) { - WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED); + WRITE_ONCE(t->kcov_state.mode, KCOV_MODE_DISABLED); barrier(); t->kcov =3D NULL; - t->kcov_size =3D 0; - t->kcov_area =3D NULL; + t->kcov_state.s.size =3D 0; + t->kcov_state.s.area =3D NULL; } =20 static void kcov_task_reset(struct task_struct *t) { kcov_stop(t); - t->kcov_sequence =3D 0; + t->kcov_state.s.sequence =3D 0; t->kcov_handle =3D 0; } =20 @@ -395,10 +382,10 @@ void kcov_task_init(struct task_struct *t) static void kcov_reset(struct kcov *kcov) { kcov->t =3D NULL; - kcov->mode =3D KCOV_MODE_INIT; + kcov->state.mode =3D KCOV_MODE_INIT; kcov->remote =3D false; kcov->remote_size =3D 0; - kcov->sequence++; + kcov->state.s.sequence++; } =20 static void kcov_remote_reset(struct kcov *kcov) @@ -438,7 +425,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.s.area); kfree(kcov); } } @@ -495,8 +482,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.s.size * sizeof(unsigned long); + if (kcov->state.s.area =3D=3D NULL || vma->vm_pgoff !=3D 0 || vma->vm_end - vma->vm_start !=3D size) { res =3D -EINVAL; goto exit; @@ -504,7 +491,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.s.area + off); res =3D vm_insert_page(vma, vma->vm_start + off, page); if (res) { pr_warn_once("kcov: vm_insert_page() failed\n"); @@ -524,8 +511,8 @@ static int kcov_open(struct inode *inode, struct file *= filep) kcov =3D kzalloc(sizeof(*kcov), GFP_KERNEL); if (!kcov) return -ENOMEM; - kcov->mode =3D KCOV_MODE_DISABLED; - kcov->sequence =3D 1; + kcov->state.mode =3D KCOV_MODE_DISABLED; + kcov->state.s.sequence =3D 1; refcount_set(&kcov->refcount, 1); spin_lock_init(&kcov->lock); filep->private_data =3D kcov; @@ -560,10 +547,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.s.area; unsigned long offset; =20 - for (offset =3D 0; offset < kcov->size; offset +=3D stride) + for (offset =3D 0; offset < kcov->state.s.size; offset +=3D stride) READ_ONCE(area[offset]); } =20 @@ -602,7 +589,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->state.mode !=3D KCOV_MODE_INIT || !kcov->state.s.area) return -EINVAL; t =3D current; if (kcov->t !=3D NULL || t->kcov !=3D NULL) @@ -611,9 +598,8 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, if (mode < 0) return mode; kcov_fault_in_area(kcov); - kcov->mode =3D mode; - kcov_start(t, kcov, kcov->size, kcov->area, kcov->mode, - kcov->sequence); + kcov->state.mode =3D mode; + kcov_start(t, kcov, &kcov->state); kcov->t =3D t; /* Put either in kcov_task_exit() or in KCOV_DISABLE. */ kcov_get(kcov); @@ -630,7 +616,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->state.mode !=3D KCOV_MODE_INIT || !kcov->state.s.area) return -EINVAL; t =3D current; if (kcov->t !=3D NULL || t->kcov !=3D NULL) @@ -642,9 +628,9 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigne= d int cmd, if ((unsigned long)remote_arg->area_size > LONG_MAX / sizeof(unsigned long)) return -EINVAL; - kcov->mode =3D mode; + kcov->state.mode =3D mode; t->kcov =3D kcov; - t->kcov_mode =3D KCOV_MODE_REMOTE; + t->kcov_state.mode =3D KCOV_MODE_REMOTE; kcov->t =3D t; kcov->remote =3D true; kcov->remote_size =3D remote_arg->area_size; @@ -719,14 +705,14 @@ static long kcov_ioctl(struct file *filep, unsigned i= nt cmd, unsigned long arg) if (area =3D=3D NULL) return -ENOMEM; spin_lock_irqsave(&kcov->lock, flags); - if (kcov->mode !=3D KCOV_MODE_DISABLED) { + if (kcov->state.mode !=3D KCOV_MODE_DISABLED) { spin_unlock_irqrestore(&kcov->lock, flags); vfree(area); return -EBUSY; } - kcov->area =3D area; - kcov->size =3D size; - kcov->mode =3D KCOV_MODE_INIT; + kcov->state.s.area =3D area; + kcov->state.s.size =3D size; + kcov->state.mode =3D KCOV_MODE_INIT; spin_unlock_irqrestore(&kcov->lock, flags); return 0; case KCOV_REMOTE_ENABLE: @@ -822,13 +808,11 @@ static void kcov_remote_softirq_start(struct task_str= uct *t) struct kcov_percpu_data *data =3D this_cpu_ptr(&kcov_percpu_data); unsigned int mode; =20 - mode =3D READ_ONCE(t->kcov_mode); + mode =3D READ_ONCE(t->kcov_state.mode); barrier(); if (kcov_mode_enabled(mode)) { - 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_state.s =3D t->kcov_state.s; + data->saved_state.mode =3D mode; data->saved_kcov =3D t->kcov; kcov_stop(t); } @@ -839,13 +823,8 @@ 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, &data->saved_state); + data->saved_state =3D (struct kcov_state){ 0 }; data->saved_kcov =3D NULL; } } @@ -854,12 +833,11 @@ void kcov_remote_start(u64 handle) { struct task_struct *t =3D current; struct kcov_remote *remote; + struct kcov_state state; + 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; @@ -872,8 +850,8 @@ void kcov_remote_start(u64 handle) * Check that kcov_remote_start() is not called twice in background * threads nor called by user tasks (with enabled kcov). */ - mode =3D READ_ONCE(t->kcov_mode); - if (WARN_ON(in_task() && kcov_mode_enabled(mode))) { + state.mode =3D READ_ONCE(t->kcov_state.mode); + if (WARN_ON(in_task() && kcov_mode_enabled(state.mode))) { local_unlock_irqrestore(&kcov_percpu_data.lock, flags); return; } @@ -903,8 +881,8 @@ void kcov_remote_start(u64 handle) * Read kcov fields before unlock to prevent races with * KCOV_DISABLE / kcov_remote_reset(). */ - mode =3D kcov->mode; - sequence =3D kcov->sequence; + state.mode =3D kcov->state.mode; + state.s.sequence =3D kcov->state.s.sequence; if (in_task()) { size =3D kcov->remote_size; area =3D kcov_remote_area_get(size); @@ -927,12 +905,14 @@ void kcov_remote_start(u64 handle) =20 /* Reset coverage size. */ *(u64 *)area =3D 0; + state.s.area =3D area; + state.s.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, &state); =20 local_unlock_irqrestore(&kcov_percpu_data.lock, flags); } @@ -1009,7 +989,7 @@ void kcov_remote_stop(void) =20 local_lock_irqsave(&kcov_percpu_data.lock, flags); =20 - mode =3D READ_ONCE(t->kcov_mode); + mode =3D READ_ONCE(t->kcov_state.mode); barrier(); if (!kcov_mode_enabled(mode)) { local_unlock_irqrestore(&kcov_percpu_data.lock, flags); @@ -1030,9 +1010,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.s.area; + size =3D t->kcov_state.s.size; + sequence =3D t->kcov_state.s.sequence; =20 kcov_stop(t); if (in_serving_softirq()) { @@ -1045,8 +1025,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.s.sequence && kcov->remote) + kcov_move_area(kcov->state.mode, kcov->state.s.area, + kcov->state.s.size, area); spin_unlock(&kcov->lock); =20 if (in_task()) { @@ -1089,10 +1070,10 @@ static void __init selftest(void) * potentially traced functions in this region. */ start =3D jiffies; - current->kcov_mode =3D KCOV_MODE_TRACE_PC; + current->kcov_state.mode =3D KCOV_MODE_TRACE_PC; while ((jiffies - start) * MSEC_PER_SEC / HZ < 300) ; - current->kcov_mode =3D 0; + current->kcov_state.mode =3D 0; pr_err("done running self test\n"); } #endif --=20 2.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f73.google.com (mail-ej1-f73.google.com [209.85.218.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 B2257231A37 for ; Wed, 16 Apr 2025 08:55:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793708; cv=none; b=e89IjHLPlUFiOKmdhmL5vaFCCpLgb9ZJAeJa+swAVG1WpfbbJCzxwGYvLd+EDl12d+/kn9YvdiNEA9NZfd8T8V7Phg/HIqyhmUFZhc+LXhK0nAeJ+k40oscp6le7GOU//k5LLqBbi/OD1AUbgaf1J6uv7vqfiCBKDrShqhb8xoU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793708; c=relaxed/simple; bh=wf+7s96UajTNndiXoBnU62ZqCuQvpKeDgATZuDbUUsQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=MEQG5FFDBw+N0fkCnbMeZeJriOVbZ0vEqKWilFOBPaAM1xVnfq3/1XngNgz43cfX5mGSTHEKuCkCOCSiydfkRzHOmiEQM9oMfM8UP5HplhEtNsIvH6bOHz0Hx/O+sA7tUYR3gujH/61MRceBXxGjhIBj9BH9VfrYOHZWm67O4JY= 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=C5SxFASg; arc=none smtp.client-ip=209.85.218.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="C5SxFASg" Received: by mail-ej1-f73.google.com with SMTP id a640c23a62f3a-ac293748694so622874766b.0 for ; Wed, 16 Apr 2025 01:55:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793705; x=1745398505; 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=hH2r0HpjHA+TAtMnP8ob7jw0ZAHM0/6/eJ5rdM10bGc=; b=C5SxFASgdj7i4JLmrFR5a36tHrrFiVoUqeMpXLP5fyuAAC3uerysrBV8niZkd6+vuc b5O+oGp7LN13J4nyq0dH8/Zuw10y0FYLioJEbMMKIpK5kcFnjx7ZPQ/Hfuc81+5n0IPp J7Qs2LrrN3tyCAqzhkJ7I5Lp8xwjW4WlmqDPuJJ42aIzMxmvInZ0h31Op85HkHIapNyM hvC04nKyR0ElymT+tBOIyUhkdx/J2i0dmLNS092AhynN315gfsW4vmMj+LJbRiwRwVn7 c8BUqkiGSSnQSsHSAcfi7rgIsn+8SWZQETpnDbB+tHsBWoLNc5MKzY7gvUHNGwpg/IRn FglA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793705; x=1745398505; 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=hH2r0HpjHA+TAtMnP8ob7jw0ZAHM0/6/eJ5rdM10bGc=; b=emyxsGaie70ETFrqQuP9iKRRDKv+AwJrUaT6ZXlMaiVAyjfPriJacbV3qmLhRLzjcC 9r1zNUDBLJG2ajs8Em0rgZ97v5TMP/zjsCJ0qPlPX+hD24+rBiPNQqc88W6FIfXlaG1x 7XBr4llKa2QotA42a9cr649V+NiDwF9Hx3hqBIHyBVxbvHcBxuQQEq3Lr1KBowS6yGmn pka3BzWHeRYP/KwZC7bm87l/Sbz8hEO+QCKGYsWznq4cRAuzedAwlwSbX1/Nao9hHzvZ XImnFvwzbTTgB1jLh2B1yxUd+n4GgGC+5UdqY97FFhfs9TdlQ2DsdzOZcCFVA9KbR7WH wmag== X-Forwarded-Encrypted: i=1; AJvYcCXyoKbTyXvoODU2YDD9scyQlMHNRU0SU5enkU1dfqXG+w9iscGIhKsK0X14NZxlWVXdx8Lgd+JhXp+7TTY=@vger.kernel.org X-Gm-Message-State: AOJu0Yy7zWhUI459CeSq7WT62Wxndq+xCGeszfoIii9LmWIDes8oIFrc Gk/W//eYXw4cpQHecuuF5KwhxI64w2PzPy0FljQ1cubHAeDW0QFcEmx8hABPKSqMfUcxMgmAYRO IyQ== X-Google-Smtp-Source: AGHT+IHLysqpTjLpAqWg5WxyJTA9vRLgfkOcTMsAwCG2Ki/9QmdowjbxmDNblFkznXklYcgsxssJPtj0TZ0= X-Received: from ejkh19.prod.google.com ([2002:a17:906:7193:b0:aca:c1c0:e337]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:9494:b0:acb:349d:f909 with SMTP id a640c23a62f3a-acb42a50028mr74361466b.31.1744793705000; Wed, 16 Apr 2025 01:55:05 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:41 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-4-glider@google.com> Subject: [PATCH 3/7] kcov: x86: introduce CONFIG_KCOV_ENABLE_GUARDS 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) 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. Cc: x86@kernel.org Signed-off-by: Alexander Potapenko --- 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 | 16 ++++++++ scripts/Makefile.kcov | 4 ++ scripts/module.lds.S | 23 ++++++++++++ tools/objtool/check.c | 1 + 8 files changed, 101 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 0deb4887d6e96..2acfbbde33820 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -390,6 +390,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 0d5b186abee86..3ff150f152737 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_ENABLE_GUARDS) #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_ENABLE_GUARDS) +#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 e1f7d793c1cb3..7ec2669362fd1 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 8fcbca236bec5..b97f429d17436 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -193,27 +193,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 void sanitizer_cov_write_subsequent(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.s.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.s.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(). @@ -224,7 +212,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. + */ +#ifndef CONFIG_KCOV_ENABLE_GUARDS +void notrace __sanitizer_cov_trace_pc(void) +{ + if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) + return; + + sanitizer_cov_write_subsequent(current->kcov_state.s.area, + current->kcov_state.s.size, + canonicalize_ip(_RET_IP_)); +} EXPORT_SYMBOL(__sanitizer_cov_trace_pc); +#else +void notrace __sanitizer_cov_trace_pc_guard(u32 *guard) +{ + if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) + return; + + sanitizer_cov_write_subsequent(current->kcov_state.s.area, + current->kcov_state.s.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); +#endif =20 #ifdef CONFIG_KCOV_ENABLE_COMPARISONS static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip) @@ -252,7 +273,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 sanitizer_cov_write_subsequent(). */ WRITE_ONCE(area[0], count + 1); barrier(); area[start_index] =3D type; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 35796c290ca35..a81d086b8e1ff 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2135,6 +2135,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" @@ -2151,6 +2153,20 @@ config KCOV =20 For more details, see Documentation/dev-tools/kcov.rst. =20 +config KCOV_ENABLE_GUARDS + depends on KCOV + depends on CC_HAS_SANCOV_TRACE_PC_GUARD + bool "Use fsanitize-coverage=3Dtrace-pc-guard 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 comes at a cost of increased binary size (4 bytes of .bss + per basic block, plus 1-2 instructions to pass an extra parameter). + 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..ec63d471d5773 100644 --- a/scripts/Makefile.kcov +++ b/scripts/Makefile.kcov @@ -1,5 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only +ifeq ($(CONFIG_KCOV_ENABLE_GUARDS),y) +kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC_GUARD) +=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..ec7e9247f8de6 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -64,6 +64,29 @@ SECTIONS { MOD_CODETAG_SECTIONS() } #endif + +#ifdef CONFIG_KCOV_ENABLE_GUARDS + __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 ce973d9d8e6d8..a5db690dd2def 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1149,6 +1149,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.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f73.google.com (mail-ej1-f73.google.com [209.85.218.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 6DBB023371E for ; Wed, 16 Apr 2025 08:55:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793711; cv=none; b=T1xPL1ik2cOZ0AzeNIfNSDVnlFn5WgVvqwio3sMrj0EQ696IInYm/8dIgUHhqlKoUZKDfD2W2WND22LdIBpF349s7oTlt2vQO1hnWshk25eBxZjU5kqttSGz6tf6D23BeZHWmaqL1bDXL51LjNH4sCZ21nuepFgi+h0fot0D3eg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793711; c=relaxed/simple; bh=LpOL65sGsG7Az4e//JrWMOg/Lwmm8AClYhRDaY4MFgg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tTaGIA2l2gh3s9KeS1yz/2Fmj41RvNDvpaZHa4BSUj4O6XM/h/TI624GTgM91lbl4lkv3AsIRDoVMjlOEnGoqSo2l7X7QsOhXD4e0epc0pxqdvfsXGmKvzwVDbBT02GKEnGM6A9uyUV8x6XWrskF44DkChpD5GyYz1+EzQff9N4= 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=EHj+R712; arc=none smtp.client-ip=209.85.218.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="EHj+R712" Received: by mail-ej1-f73.google.com with SMTP id a640c23a62f3a-ac6caf952d7so633472566b.3 for ; Wed, 16 Apr 2025 01:55:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793708; x=1745398508; 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=D7PaNu9SLcaDW6rJLrXYufwflTdOL8oZuD382JbLKOQ=; b=EHj+R712nnN+/J5oltrnyAqQgCq25RlFPAAuJsltwbit6xvjCqKkPBt4+9wWCiobzp YXs2r9gbJIFhsB0vaCzHs/R8t8Kc4MVIqQ4zBqLTcEOlkeM+EJEfKPmdfl6AJnS2TqR9 iWHyFSU9v04vBeRfNCTxAT8vPjgIfILcHT5ze5AhxoJppBey879NC2G4JitpIQEYejeJ bULydd2EYghHTrHDeUzOk0y3JxWpQAvGj+XSkTdEygKkW2piHxwgCW4/HPDzE0tnqmIK Qzl6MSN99WhUBPVu7/pfQ7KWyFP1amMPGcpf8r79CedofInjVeH255PJCtKzlU03Ph3Z QvqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793708; x=1745398508; 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=D7PaNu9SLcaDW6rJLrXYufwflTdOL8oZuD382JbLKOQ=; b=XB6Z5V4G4d/r4yqalO0zMYjOKxUWZwIQcEt9MtZJ5XicWKuWAdS100cYHt/xTqrbuS hyqKa2+SLMz4DWgiRFj4bvLKGJ2rJoxkZoHSTQRyHkgutSuRh+QHtLnC3w6VhseZYPII kbyv5oFXP72yQZUx8J/+Yl+UiRsQ3QHRMw07UeJr/1gjvNbzp5Hk3K21nrX55tNLmHQP ZRqE2MgG1DyMiiK7ej05BvYYvW/Ie9++HH9kPxlc4JvI2mQgagPr0Y2f9+YI0Ep9DZbw UiA8WUDsW47qLlNLcZkTwznu0Rt6zzjjDtC/jWfQohUTMo1kvm3qUBgj5oZ1oP0OLNi8 9Ntg== X-Forwarded-Encrypted: i=1; AJvYcCWe8d/AzWBFCqH6TMt3l7NqNVaQxVGnVL2lsCJVsMtyJLze/s48JjAHD1EeNoDqspRTrlmVq+dhLoz6/ZY=@vger.kernel.org X-Gm-Message-State: AOJu0YxAXTE9PPIv+yvIMuQAEbiRAO/JV/DtMdrp+7/WuamXNcmwq0r+ UARI9BOZq2/vtxo313bl+2hDf2t8c4OyHLip0yZIrqO7sK48lyfSWjU/fOmdkBRQTuF/c1l8ZSk +yQ== X-Google-Smtp-Source: AGHT+IG9lth0q3y30P/VyLYjisZmGmSRBC3r0wPf3kzY90O2m4xRYk1/bvFuHz0H5Eow7kT1r9e29N8gQwY= X-Received: from ejbgq18.prod.google.com ([2002:a17:906:e252:b0:ac2:8b71:dd54]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:748:b0:ac1:e53c:d13f with SMTP id a640c23a62f3a-acb42c13a70mr69983766b.50.1744793707726; Wed, 16 Apr 2025 01:55:07 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:42 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-5-glider@google.com> Subject: [PATCH 4/7] 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 change so far. Signed-off-by: Alexander Potapenko --- include/linux/kcov-state.h | 9 ++++++- kernel/kcov.c | 54 ++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/include/linux/kcov-state.h b/include/linux/kcov-state.h index 4c4688d01c616..6e576173fd442 100644 --- a/include/linux/kcov-state.h +++ b/include/linux/kcov-state.h @@ -15,9 +15,16 @@ struct kcov_state { struct { /* 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 diff --git a/kernel/kcov.c b/kernel/kcov.c index b97f429d17436..7b726fd761c1b 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -193,11 +193,11 @@ static notrace unsigned long canonicalize_ip(unsigned= long ip) return ip; } =20 -static void sanitizer_cov_write_subsequent(unsigned long *area, int size, +static void sanitizer_cov_write_subsequent(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)) { /* @@ -207,9 +207,9 @@ static void sanitizer_cov_write_subsequent(unsigned lon= g *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 @@ -223,8 +223,8 @@ void notrace __sanitizer_cov_trace_pc(void) if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) return; =20 - sanitizer_cov_write_subsequent(current->kcov_state.s.area, - current->kcov_state.s.size, + sanitizer_cov_write_subsequent(current->kcov_state.s.trace, + current->kcov_state.s.trace_size, canonicalize_ip(_RET_IP_)); } EXPORT_SYMBOL(__sanitizer_cov_trace_pc); @@ -234,8 +234,8 @@ void notrace __sanitizer_cov_trace_pc_guard(u32 *guard) if (!check_kcov_mode(KCOV_MODE_TRACE_PC, current)) return; =20 - sanitizer_cov_write_subsequent(current->kcov_state.s.area, - current->kcov_state.s.size, + sanitizer_cov_write_subsequent(current->kcov_state.s.trace, + current->kcov_state.s.trace_size, canonicalize_ip(_RET_IP_)); } EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard); @@ -250,9 +250,9 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard_init); #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)) @@ -264,22 +264,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.s.area; + trace =3D (u64 *)t->kcov_state.s.trace; max_pos =3D t->kcov_state.s.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 sanitizer_cov_write_subsequent(). */ - 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 @@ -380,11 +380,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.s.sequence; + WRITE_ONCE(t->kcov_state.mode, KCOV_MODE_DISABLED); barrier(); t->kcov =3D NULL; - t->kcov_state.s.size =3D 0; - t->kcov_state.s.area =3D NULL; + t->kcov_state.s =3D (typeof(t->kcov_state.s)){ 0 }; + t->kcov_state.s.sequence =3D saved_sequence; } =20 static void kcov_task_reset(struct task_struct *t) @@ -733,6 +735,8 @@ static long kcov_ioctl(struct file *filep, unsigned int= cmd, unsigned long arg) } kcov->state.s.area =3D area; kcov->state.s.size =3D size; + kcov->state.s.trace =3D area; + kcov->state.s.trace_size =3D size; kcov->state.mode =3D KCOV_MODE_INIT; spin_unlock_irqrestore(&kcov->lock, flags); return 0; @@ -924,10 +928,12 @@ void kcov_remote_start(u64 handle) local_lock_irqsave(&kcov_percpu_data.lock, flags); } =20 - /* Reset coverage size. */ - *(u64 *)area =3D 0; state.s.area =3D area; state.s.size =3D size; + state.s.trace =3D area; + state.s.trace_size =3D size; + /* Reset coverage size. */ + state.s.trace[0] =3D 0; =20 if (in_serving_softirq()) { kcov_remote_softirq_start(t); @@ -1000,8 +1006,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 @@ -1033,6 +1039,8 @@ void kcov_remote_stop(void) kcov =3D t->kcov; area =3D t->kcov_state.s.area; size =3D t->kcov_state.s.size; + trace =3D t->kcov_state.s.trace; + trace_size =3D t->kcov_state.s.trace_size; sequence =3D t->kcov_state.s.sequence; =20 kcov_stop(t); --=20 2.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f73.google.com (mail-ej1-f73.google.com [209.85.218.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 46B9E233D7B for ; Wed, 16 Apr 2025 08:55:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793714; cv=none; b=AHS6CvOfQs4YtB8HyGqe+IYhAMH9se4f0w/HqEbzeyFNN7FhAg4lh1Jxr+dyoQ1QBLWzFZCbMN8jcpfJZshIguNzucVf4QeAAn8tzizi78snFMRKtv1xweGpFNujK2fvb5GE5zDKYOMqzoQgHKVz283FUNEDR3R9nsuvl4p+6vU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793714; c=relaxed/simple; bh=dPOIh10gure8X6wh/3OaULp/Lh1z2dfsF7yCMitW81M=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Mexs5tBKtvHl5fTFQdoI42VRKLKApw66tdKZnlDPTHsn//aPMhfPl231QP/+r31oNajFTdcAf4NfzRkJ1EbOg6JbP8Cxir7XX/pPE0mCBvsbvTQJDv2FGKozcjw4u0gDeALJmGdw/yKV0xOAbyp3bLcWhZ6lJGa36gDEM50SEiI= 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=whzbAV4M; arc=none smtp.client-ip=209.85.218.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="whzbAV4M" Received: by mail-ej1-f73.google.com with SMTP id a640c23a62f3a-ac28f255a36so516272566b.3 for ; Wed, 16 Apr 2025 01:55:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793710; x=1745398510; 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=ZC4wZ/r+6T3+g58Jq4R0q5y2fMNgcKM6hKjFFkcrcac=; b=whzbAV4Mwj0ttS4aYj3A6GsaLcgawMj2mw+v8lSM9jNyqZeOjTmEJlPcTBL53nNcxj mD0C/RAQivlP0HbKBGonN3wLGFea73b+Bf0zBpKlZManWMHXnK0Jh1ZUC94fEfk2jEMc V/yjtNOcjZfGvgwYHMhE09ZoCvTcR+DzBN7z11vSUofTm3oN+xkev9EAaa3IRz+gcx+x 6+oQgFi18N5jwX1E8A/vhr6eijoyfbDL9Bx6/WXNRQRBUZH972qQWLdjlvPfMY3217Yf cVJn/KJ0XwyPTMtQiE/BhYYbbVJA1PPG0vIOqC0d0mpkSIntbhcKbgkBilZCSNLFn/Bf eNzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793710; x=1745398510; 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=ZC4wZ/r+6T3+g58Jq4R0q5y2fMNgcKM6hKjFFkcrcac=; b=J177dVKNVdPX/WhRMLwfmLNpAFrNMSCkn/z9EaDbaOyYhfvUe/l80E5I6bLxfEYm+p EUsx0j+SdEkia2LkEpGp/LVQvSGZnmZR0kEx/ZXHtOBzVmzTgO8NobLuUeciXOSl8DmG Y3Wk2GDQXmTehqFYuD0Y8keON88FDQSKJTdLlsNxKcguZA+KXwp+uBF7B83xCExFtZ9u 5ZaEJuj7zfDHZdsWn/W8qRUMXK8ezVS6SuyX5c9koKQ/nE5GhJ2zNW1oa63Vl+h9y17M pZ8YYx7AG2O2UD62bH6w0VYmgJtLQ6ToZHa1thMxqB90sJNGnVqz5J/+Bi5LmrEfK7pM 1zAg== X-Forwarded-Encrypted: i=1; AJvYcCUMGOX7yzCAdNB4k+lP4Mekgr1XmOBB8/O7VttbqbF7gQ/NPN8m4voiq63jj4EPAdqbf8MkxRJIzW6258s=@vger.kernel.org X-Gm-Message-State: AOJu0Yw3q1YWWrrEa7jX6HWfKMxSYIFpY666Vc/WFK45j4+pkM3lk8Hz Y17iQ94dwQYjL/V2daqccDTKDlYgpxGunJDiOTjkoJedAEkC++FiXbNo/yTHosSEd+NH0jIu6Ga wJg== X-Google-Smtp-Source: AGHT+IHqEJTrvIEc+myvUhn+5RHItbzkzPoGAvROGKJhXQ5+K0wH8/TsMQnizWCRPxTgDF3unV1G0QkOht8= X-Received: from ejzs20.prod.google.com ([2002:a17:906:c314:b0:ac6:b746:be0b]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a17:906:f594:b0:abf:4708:8644 with SMTP id a640c23a62f3a-acb42add337mr75919066b.43.1744793710441; Wed, 16 Apr 2025 01:55:10 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:43 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-6-glider@google.com> Subject: [PATCH 5/7] 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. Also update the documentation. Signed-off-by: Alexander Potapenko --- Documentation/dev-tools/kcov.rst | 43 +++++++++++ include/linux/kcov-state.h | 8 ++ include/linux/kcov.h | 2 + include/uapi/linux/kcov.h | 1 + kernel/kcov.c | 129 +++++++++++++++++++++++++++---- 5 files changed, 170 insertions(+), 13 deletions(-) diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kco= v.rst index 6611434e2dd24..271260642d1a6 100644 --- a/Documentation/dev-tools/kcov.rst +++ b/Documentation/dev-tools/kcov.rst @@ -137,6 +137,49 @@ 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 +Unique coverage collection +--------------------------- + +Instead of collecting raw PCs, KCOV can deduplicate them on the fly. +This mode is enabled by the ``KCOV_UNIQUE_ENABLE`` ioctl (only available if +``CONFIG_KCOV_ENABLE_GUARDS`` 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`` +words from those allocated by ``KCOV_INIT_TRACE`` to keep an opaque bitmap= that +prevents the kernel from storing the same PC twice. The remaining part of = the +trace is used to collect PCs, like in other modes (this part must contain = at +least two words, 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 word past ``bitmap_size``) and wipe the= whole +bitmap. + Comparison operands collection ------------------------------ =20 diff --git a/include/linux/kcov-state.h b/include/linux/kcov-state.h index 6e576173fd442..26e275fe90684 100644 --- a/include/linux/kcov-state.h +++ b/include/linux/kcov-state.h @@ -26,6 +26,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/linux/kcov.h b/include/linux/kcov.h index 7ec2669362fd1..41eebcd3ab335 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_TRACE_UNIQUE_PC =3D 5, }; =20 #define KCOV_IN_CTXSW (1 << 30) diff --git a/include/uapi/linux/kcov.h b/include/uapi/linux/kcov.h index ed95dba9fa37e..fe1695ddf8a06 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 _IOR('c', 103, unsigned long) =20 enum { /* diff --git a/kernel/kcov.c b/kernel/kcov.c index 7b726fd761c1b..dea25c8a53b52 100644 --- a/kernel/kcov.c +++ b/kernel/kcov.c @@ -29,6 +29,10 @@ =20 #include =20 +#ifdef CONFIG_KCOV_ENABLE_GUARDS +atomic_t kcov_guard_max_index =3D ATOMIC_INIT(1); +#endif + #define kcov_debug(fmt, ...) pr_debug("%s: " fmt, __func__, ##__VA_ARGS__) =20 /* Number of 64-bit words written per one comparison: */ @@ -161,8 +165,7 @@ 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; =20 @@ -172,7 +175,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_state.mode); /* * There is some code that runs in interrupts but for which @@ -182,7 +185,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) @@ -201,7 +204,7 @@ static void sanitizer_cov_write_subsequent(unsigned lon= g *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,7 +223,7 @@ static void sanitizer_cov_write_subsequent(unsigned lon= g *trace, int size, #ifndef CONFIG_KCOV_ENABLE_GUARDS 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 sanitizer_cov_write_subsequent(current->kcov_state.s.trace, @@ -229,14 +232,73 @@ void notrace __sanitizer_cov_trace_pc(void) } EXPORT_SYMBOL(__sanitizer_cov_trace_pc); #else + +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, we store the unused index in a per-cpu variable. + * In an even less likely case the current task may lose a race and get + * rescheduled onto a CPU that already has a saved index, discarding that = index. + * This will result in an unused hole in the bitmap, but such events shoul= d 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) - 1; + + /* + * 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; + u32 pc_index; + enum kcov_mode mode =3D get_kcov_mode(current); =20 - sanitizer_cov_write_subsequent(current->kcov_state.s.trace, - current->kcov_state.s.trace_size, - canonicalize_ip(_RET_IP_)); + switch (mode) { + case KCOV_MODE_TRACE_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.s.bitmap_size)) + if (test_and_set_bit(pc_index, + current->kcov_state.s.bitmap)) + return; + /* If the PC is new, write it to the trace. */ + fallthrough; + case KCOV_MODE_TRACE_PC: + sanitizer_cov_write_subsequent(current->kcov_state.s.trace, + current->kcov_state.s.trace_size, + canonicalize_ip(_RET_IP_)); + break; + default: + return; + } } EXPORT_SYMBOL(__sanitizer_cov_trace_pc_guard); =20 @@ -255,7 +317,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); @@ -374,7 +436,7 @@ static void kcov_start(struct task_struct *t, struct kc= ov *kcov, /* Cache in task struct for performance. */ t->kcov_state.s =3D state->s; barrier(); - /* See comment in check_kcov_mode(). */ + /* See comment in get_kcov_mode(). */ WRITE_ONCE(t->kcov_state.mode, state->mode); } =20 @@ -408,6 +470,10 @@ static void kcov_reset(struct kcov *kcov) kcov->state.mode =3D KCOV_MODE_INIT; kcov->remote =3D false; kcov->remote_size =3D 0; + kcov->state.s.trace =3D kcov->state.s.area; + kcov->state.s.trace_size =3D kcov->state.s.size; + kcov->state.s.bitmap =3D NULL; + kcov->state.s.bitmap_size =3D 0; kcov->state.s.sequence++; } =20 @@ -594,6 +660,41 @@ 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_ENABLE_GUARDS)) + return -ENOTSUPP; + if (kcov->state.mode !=3D KCOV_MODE_INIT || !kcov->state.s.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.s.size - 1))) + return -EINVAL; + + kcov->state.s.bitmap_size =3D bitmap_words * sizeof(unsigned long) * 8; + kcov->state.s.bitmap =3D kcov->state.s.area; + kcov->state.s.trace_size =3D kcov->state.s.size - bitmap_words; + kcov->state.s.trace =3D + ((unsigned long *)kcov->state.s.area + bitmap_words); + + kcov_fault_in_area(kcov); + kcov->state.mode =3D KCOV_MODE_TRACE_UNIQUE_PC; + kcov_start(t, kcov, &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) { @@ -627,6 +728,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; --=20 2.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.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 EC9CC233144 for ; Wed, 16 Apr 2025 08:55:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793717; cv=none; b=npZZPs4s3/RIBpdA+59vpxmOjNov0cZX5S7Dw481G9tDK+krSwy12Zqbk8Oligt0czwdEoezmER44s3fxr9KlFuYXw5BJBNafH0FGGxiYZ6CIUwbyFjxzcsusCKY9o9Ef/FM7FpbC8jxwxAlx8tv9EKlDv0XpfG0jzbK2sAalrI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793717; c=relaxed/simple; bh=er+DJxKzIeHX5hexvve8j1XLT4IbutWOowishPWCDrs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pEanvhTiKc37ijg7GHEJYRyjz9L7sWusQD9DtEKbNjRalBgq4E6IzIPSm/GBk9MXa1i2HBuG3WonqP6iP1Rs2vWNboUyySPZcgg91iWItE9OzO3tyxO8lrdK+lSjnmjpuInNJb5BybpSiE1h1sXSJ6fOvPuOuqApM7Xu9fgNOb4= 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=Lw3WE8Zu; arc=none smtp.client-ip=209.85.208.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="Lw3WE8Zu" Received: by mail-ed1-f74.google.com with SMTP id 4fb4d7f45d1cf-5f435440ea1so2938031a12.1 for ; Wed, 16 Apr 2025 01:55:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793713; x=1745398513; 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=JTFzqr/xcSaN2yUJr69OYVSpzwgxx9PIurYAIv+eQpU=; b=Lw3WE8ZumWnyiVTE2yqIvs431G1XmQ6o5dZHKkIPqBqJr4qXt5Wkx3FaRiVIw/QKZm gRydfrEhiiHTPeAODwqG2w10qYO3TORtfT5EMSCEDcfqu2QpmD677FICNnCi7aEEylG/ ZiEKyCN4WDYcCvDLwxwd81ZZze2B062ykMLaP5TcxoeQcDf2O8V3nfumUziDm6EbM2vZ udy0//ptfu9T70tkCbNnnAJsZEsVifNU/UlBX2LtgnXW9DRLeDOaqmInKCHdQQQj31s0 CLm/XTvr5er5iStbUjJNB6cmhgROY/od+shE2U3Y/HXQMGPXgcmNfbu8ekNG37kGXIIB QLSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793713; x=1745398513; 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=JTFzqr/xcSaN2yUJr69OYVSpzwgxx9PIurYAIv+eQpU=; b=VXNbD+fAs4ckA1luFMKbSCxS/cxZw65WpD+QFikrJwtyWgb7Wp1Dhsw+rea0Tut0+x r9MWEOyigvus0iXaHxyTHedcP8VtC5EuMxdsmBBQjwVjTz0JIHFCoJupUfB8RdPLI8/8 exIOalmavAss91t+u2mGcJkwaTOq8DE2h9j4iyPd6XCMiMIzqfzn+YHq9b/Cur32N9cy 7q8IEIL55W9pr30QrpMJwCqZxu0QjPN+8zqW5ctkbTm0YVcoMgylhq7S+fozVFimdUeB GGsBJatYM5wu1q6V9q/oPoqT0jI8AkatS0BfXLXbMwAI9XmXRhLBSwtm8HxAdssZ5UNr Q1lw== X-Forwarded-Encrypted: i=1; AJvYcCVSxp4ERy/T/4jh0EnTMkJ4alfM/XrEdE8i9V21kmgMT0Br4DBFwZDpw926jngKuTdRvzAE3SIBVyVY88g=@vger.kernel.org X-Gm-Message-State: AOJu0Yzxfn6CTwH+NOztRLhFGvCseX/ELmwiJJFScIEtW5+k6619zwS0 F1H6M8doqqUHW0eTm1G6a/1rcymcVq4dri8I8mwetOp6WnON835MWPyXhIQi4yczq4hHZfEIbEk imQ== X-Google-Smtp-Source: AGHT+IGa+BXef7MTLYEDEJ5TGukgjebm/ZwTNU9BAmLBbXlnhC1Rts2yCTcbcszxgvnuWzaU+YMGv+E91QA= X-Received: from edjb8.prod.google.com ([2002:a50:ccc8:0:b0:5e0:677b:d382]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:1e91:b0:5ec:9352:7b20 with SMTP id 4fb4d7f45d1cf-5f4b6dfb88dmr841880a12.0.1744793713231; Wed, 16 Apr 2025 01:55:13 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:44 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-7-glider@google.com> Subject: [PATCH 6/7] x86: objtool: add support for R_X86_64_REX_GOTPCRELX 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" When compiling modules with -fsanitize-coverage=3Dtrace-pc-guard, Clang will emit R_X86_64_REX_GOTPCRELX relocations for the __start___sancov_guards and __stop___sancov_guards symbols. Although these relocations can be resolved within the same binary, they are left over by the linker because of the --emit-relocs flag. This patch makes it possible to resolve the R_X86_64_REX_GOTPCRELX relocations at runtime, as doing so does not require a .got section. In addition, add a missing overflow check to R_X86_64_PC32/R_X86_64_PLT32. Cc: x86@kernel.org Signed-off-by: Alexander Potapenko --- arch/x86/include/asm/elf.h | 1 + arch/x86/kernel/module.c | 8 ++++++++ arch/x86/um/asm/elf.h | 1 + tools/objtool/arch/x86/decode.c | 1 + 4 files changed, 11 insertions(+) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 1fb83d47711f9..15d0438467e94 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -63,6 +63,7 @@ typedef struct user_i387_struct elf_fpregset_t; #define R_X86_64_8 14 /* Direct 8 bit sign extended */ #define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ #define R_X86_64_PC64 24 /* Place relative 64-bit signed */ +#define R_X86_64_REX_GOTPCRELX 42 /* R_X86_64_GOTPCREL with optimizations = */ =20 /* * These are used to set parameters in the core dumps. diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 8984abd91c001..6c8b524bfbe3b 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -133,6 +133,14 @@ static int __write_relocate_add(Elf64_Shdr *sechdrs, case R_X86_64_PC32: case R_X86_64_PLT32: val -=3D (u64)loc; + if ((s64)val !=3D *(s32 *)&val) + goto overflow; + size =3D 4; + break; + case R_X86_64_REX_GOTPCRELX: + val -=3D (u64)loc; + if ((s64)val !=3D *(s32 *)&val) + goto overflow; size =3D 4; break; case R_X86_64_PC64: diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h index 62ed5d68a9788..f314478ce9bc3 100644 --- a/arch/x86/um/asm/elf.h +++ b/arch/x86/um/asm/elf.h @@ -119,6 +119,7 @@ do { \ #define R_X86_64_8 14 /* Direct 8 bit sign extended */ #define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ #define R_X86_64_PC64 24 /* Place relative 64-bit signed */ +#define R_X86_64_REX_GOTPCRELX 42 /* R_X86_64_GOTPCREL with optimizations = */ =20 /* * This is used to ensure we don't load something for the wrong architectu= re. diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decod= e.c index fe1362c345647..8736524d60344 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -93,6 +93,7 @@ bool arch_pc_relative_reloc(struct reloc *reloc) case R_X86_64_PLT32: case R_X86_64_GOTPC32: case R_X86_64_GOTPCREL: + case R_X86_64_REX_GOTPCRELX: return true; =20 default: --=20 2.49.0.604.gff1f9ca942-goog From nobody Fri Dec 19 20:36:14 2025 Received: from mail-ej1-f73.google.com (mail-ej1-f73.google.com [209.85.218.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 BE920235BFF for ; Wed, 16 Apr 2025 08:55:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793720; cv=none; b=HC+KbbfaD94BBYn5vPnHmWM3CRCIykUlklg4eM9gWtk6eKY16cM3xp1PY3eu6JFvR96s+NwTEJThK0YU4xZdZI9E+Y3XdSqErLDXrb+xfpvN9EZukCPK7fiU+syXNFSHVTYHhKRO1RRH6Oy49y9Bwn2fk083M/A43hjQYOH8uVU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744793720; c=relaxed/simple; bh=5LBeZUOimaQ9vgaU+v5OspIev/8kHog8cARhuN1dCts=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tY/MDsdDbqy4WUUVDIhfsfjZ56dPIvZOhyL6Ksa3ZLfylDfMZa3aqFVf8HdJe+6dXqMTiG1b6Ne4rI1S8FwY51abTT72fuapVnIR9lnrbB7tLavmN4lkTcHwidGtzzEinHPs0g6jd4MeJ73/qnFi2nwd+QmciO/Ypi04Jv6RoNo= 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=P6kwwoTC; arc=none smtp.client-ip=209.85.218.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="P6kwwoTC" Received: by mail-ej1-f73.google.com with SMTP id a640c23a62f3a-ac737973d03so438801366b.1 for ; Wed, 16 Apr 2025 01:55:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1744793716; x=1745398516; 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=Zc2x1kjeEyidtKH2uktLTwpBYFAA28n/I/Yhs6L1K7g=; b=P6kwwoTC6qv476hNCllPrSAUx15WSyPMbRM1DlFqdZWTJgDTSg7dCe5/ZMfKB6d6/Q Mf0RFzsps/47cOssnz8cq3pOfjzwnoKFErJ6vEKIGhDHJh1O987S8uMD3AGYZDq2n4dQ 6d6LauufxHNccZwMeaY0ouaGsSJ62fzw/1Tl6XD74o6yvvkxoimzEd0mQs05CQvipV4D hPtc2hlNii73TKck5X88g2xZmA5C7UJIcKck7PaF2rSoWAm8hBoT77AlD11yQhNMAfkO jE4G/+BEjhRnsgzGGt/Ar606k4d+zE76b0Ekjc1DACLQqeWO9TVJ7jMjlT5NLKFhhAfC o01Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744793716; x=1745398516; 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=Zc2x1kjeEyidtKH2uktLTwpBYFAA28n/I/Yhs6L1K7g=; b=D+2cLgVamy4XkbwiAt+LXyMsUL6teMAMwn51lHoJ2RxnfPiKvj9+1XJ13256VUEwln cCh4RqV0G6mlGczZC+lPtDav3zeEDMhadJmSf20+ww/aWcTkGTEZ6NgsMdcYAFyjp4PF bCoUpEL/a0eW6CTci1N9savZ/JLEtG1jOesDwWGoc8beQ9PZvKcNRA2OtZ4g/nse+i28 F/zAzeTtCTobXZxYgfZFrZW5uO3taDORjclkejz5DxdIzu+OXuoW2Dx9+9cCeusxBzO5 UW36qUFn2IiqMSz3+aHLYcb+OD2L33j+/x7tJPjmocDsVLDb1vp0VIzrKPshfMem+p+l zNww== X-Forwarded-Encrypted: i=1; AJvYcCXXt2fk6CSeIxYtzNp2OnpCLGiXVpCZGz8ws4f13DolNdoZ//74LjBGIUmdg7rAEQnRPM/4gF923PCFPuI=@vger.kernel.org X-Gm-Message-State: AOJu0Yzg0CaIF2FlxNrSqsL5G7YyIk6XSMlE1iEd0WCchewOe3XNhNZp Sa187VRReY4K1Vew6RzjCEMsVrAuLfRE4/bc2TgqHaSvm4TvBrMy+h/H7jmTvNjC51f3Ie3n4QL 55Q== X-Google-Smtp-Source: AGHT+IFCGzvTikBw+YoyEU2VTSvmPZU9EeQkTPgq9teicmMWsnUZMgILdju6RjbTnmnyAorVu8B4VqFNbRQ= X-Received: from edro11.prod.google.com ([2002:aa7:d3cb:0:b0:5f4:b068:4902]) (user=glider job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:5203:b0:5ed:89f0:27fd with SMTP id 4fb4d7f45d1cf-5f4b74b2309mr852670a12.19.1744793716020; Wed, 16 Apr 2025 01:55:16 -0700 (PDT) Date: Wed, 16 Apr 2025 10:54:45 +0200 In-Reply-To: <20250416085446.480069-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: <20250416085446.480069-1-glider@google.com> X-Mailer: git-send-email 2.49.0.604.gff1f9ca942-goog Message-ID: <20250416085446.480069-8-glider@google.com> Subject: [PATCH 7/7] 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 --- 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..91067bb63666e 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_ENABLE_GUARDS) +/* + * __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.49.0.604.gff1f9ca942-goog