Skip to content

Commit 3159d79

Browse files
Congyu-Liuakpm00
authored andcommitted
kcov: update pos before writing pc in trace function
In __sanitizer_cov_trace_pc(), 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 raised between writing pc and updating pos, the pc could be overitten by the recursive __sanitizer_cov_trace_pc(). As suggested by Dmitry, we cold update pos before writing pc to avoid such interleaving. Apply the same change to write_comp_data(). Link: https://lkml.kernel.org/r/20220523053531.1572793-1-liu3101@purdue.edu Signed-off-by: Congyu Liu <liu3101@purdue.edu> Reviewed-by: Dmitry Vyukov <dvyukov@google.com> Cc: Andrey Konovalov <andreyknvl@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 863e0d8 commit 3159d79

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

kernel/kcov.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,16 @@ void notrace __sanitizer_cov_trace_pc(void)
204204
/* The first 64-bit word is the number of subsequent PCs. */
205205
pos = READ_ONCE(area[0]) + 1;
206206
if (likely(pos < t->kcov_size)) {
207-
area[pos] = ip;
207+
/* Previously we write pc before updating pos. However, some
208+
* early interrupt code could bypass check_kcov_mode() check
209+
* and invoke __sanitizer_cov_trace_pc(). If such interrupt is
210+
* raised between writing pc and updating pos, the pc could be
211+
* overitten by the recursive __sanitizer_cov_trace_pc().
212+
* Update pos before writing pc to avoid such interleaving.
213+
*/
208214
WRITE_ONCE(area[0], pos);
215+
barrier();
216+
area[pos] = ip;
209217
}
210218
}
211219
EXPORT_SYMBOL(__sanitizer_cov_trace_pc);
@@ -236,11 +244,13 @@ static void notrace write_comp_data(u64 type, u64 arg1, u64 arg2, u64 ip)
236244
start_index = 1 + count * KCOV_WORDS_PER_CMP;
237245
end_pos = (start_index + KCOV_WORDS_PER_CMP) * sizeof(u64);
238246
if (likely(end_pos <= max_pos)) {
247+
/* See comment in __sanitizer_cov_trace_pc(). */
248+
WRITE_ONCE(area[0], count + 1);
249+
barrier();
239250
area[start_index] = type;
240251
area[start_index + 1] = arg1;
241252
area[start_index + 2] = arg2;
242253
area[start_index + 3] = ip;
243-
WRITE_ONCE(area[0], count + 1);
244254
}
245255
}
246256

0 commit comments

Comments
 (0)