mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Congyu Liu <liu3101@purdue.edu>
To: dvyukov@google.com, andreyknvl@gmail.com
Cc: kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org,
	Congyu Liu <liu3101@purdue.edu>
Subject: [PATCH] kcov: fix race caused by unblocked interrupt
Date: Tue, 17 May 2022 21:05:32 +0000	[thread overview]
Message-ID: <20220517210532.1506591-1-liu3101@purdue.edu> (raw)

Some code runs in interrupts cannot be blocked by `in_task()` check.
In some unfortunate interleavings, such interrupt is raised during
serializing trace data and the incoming nested trace functionn could
lead to loss of previous trace data. For instance, in
`__sanitizer_cov_trace_pc`, if such interrupt is raised between
`area[pos] = ip;` and `WRITE_ONCE(area[0], pos);`, then trace data in
`area[pos]` could be replaced.

The fix is done by adding a flag indicating if the trace buffer is being
updated. No modification to trace buffer is allowed when the flag is set.

Signed-off-by: Congyu Liu <liu3101@purdue.edu>
---
 include/linux/sched.h |  3 +++
 kernel/kcov.c         | 16 ++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index a8911b1f35aa..d06cedd9595f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1408,6 +1408,9 @@ struct task_struct {
 
 	/* Collect coverage from softirq context: */
 	unsigned int			kcov_softirq;
+
+	/* Flag of if KCOV area is being written: */
+	bool				kcov_writing;
 #endif
 
 #ifdef CONFIG_MEMCG
diff --git a/kernel/kcov.c b/kernel/kcov.c
index b3732b210593..a595a8ad5d8a 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -165,6 +165,8 @@ static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_stru
 	 */
 	if (!in_task() && !(in_serving_softirq() && t->kcov_softirq))
 		return false;
+	if (READ_ONCE(t->kcov_writing))
+		return false;
 	mode = READ_ONCE(t->kcov_mode);
 	/*
 	 * There is some code that runs in interrupts but for which
@@ -201,12 +203,19 @@ void notrace __sanitizer_cov_trace_pc(void)
 		return;
 
 	area = t->kcov_area;
+
+	/* Prevent race from unblocked interrupt. */
+	WRITE_ONCE(t->kcov_writing, true);
+	barrier();
+
 	/* The first 64-bit word is the number of subsequent PCs. */
 	pos = READ_ONCE(area[0]) + 1;
 	if (likely(pos < t->kcov_size)) {
 		area[pos] = ip;
 		WRITE_ONCE(area[0], pos);
 	}
+	barrier();
+	WRITE_ONCE(t->kcov_writing, false);
 }
 EXPORT_SYMBOL(__sanitizer_cov_trace_pc);
 
@@ -230,6 +239,10 @@ static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip)
 	area = (u64 *)t->kcov_area;
 	max_pos = t->kcov_size * sizeof(unsigned long);
 
+	/* Prevent race from unblocked interrupt. */
+	WRITE_ONCE(t->kcov_writing, true);
+	barrier();
+
 	count = READ_ONCE(area[0]);
 
 	/* Every record is KCOV_WORDS_PER_CMP 64-bit words. */
@@ -242,6 +255,8 @@ static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip)
 		area[start_index + 3] = ip;
 		WRITE_ONCE(area[0], count + 1);
 	}
+	barrier();
+	WRITE_ONCE(t->kcov_writing, false);
 }
 
 void notrace __sanitizer_cov_trace_cmp1(u8 arg1, u8 arg2)
@@ -335,6 +350,7 @@ static void kcov_start(struct task_struct *t, struct kcov *kcov,
 	t->kcov_size = size;
 	t->kcov_area = area;
 	t->kcov_sequence = sequence;
+	t->kcov_writing = false;
 	/* See comment in check_kcov_mode(). */
 	barrier();
 	WRITE_ONCE(t->kcov_mode, mode);
-- 
2.34.1


             reply	other threads:[~2022-05-17 21:07 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-17 21:05 Congyu Liu [this message]
2022-05-18  8:56 ` Dmitry Vyukov
2022-05-18  8:59   ` Dmitry Vyukov
2022-05-21  3:59     ` Liu, Congyu
2022-05-21  8:45       ` Dmitry Vyukov
2022-05-21 17:01         ` Liu, Congyu
2022-05-22  9:09           ` Dmitry Vyukov
2022-05-23  4:56             ` Liu, Congyu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220517210532.1506591-1-liu3101@purdue.edu \
    --to=liu3101@purdue.edu \
    --cc=andreyknvl@gmail.com \
    --cc=dvyukov@google.com \
    --cc=kasan-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®