From: Alexander Potapenko <glider@google.com> To: Mark Rutland <mark.rutland@arm.com> Cc: Andrew Morton <akpm@linux-foundation.org>, Alexander Popov <alex.popov@linux.com>, Andrey Ryabinin <aryabinin@virtuozzo.com>, Quentin Casasnovas <quentin.casasnovas@oracle.com>, Dmitriy Vyukov <dvyukov@google.com>, Andrey Konovalov <andreyknvl@google.com>, Kees Cook <keescook@chromium.org>, Vegard Nossum <vegard.nossum@oracle.com>, syzkaller <syzkaller@googlegroups.com>, Linux Memory Management List <linux-mm@kvack.org>, LKML <linux-kernel@vger.kernel.org> Subject: Re: [PATCH v2 1/3] kcov: support comparison operands collection Date: Tue, 10 Oct 2017 17:28:10 +0200 [thread overview] Message-ID: <CAG_fn=UsTCyueyuMGT8i6ZoX9CWwvE9GhJAWnsJsPhf1AY2Z4Q@mail.gmail.com> (raw) In-Reply-To: <20171009154610.GA22534@leverpostej> On Mon, Oct 9, 2017 at 8:46 AM, Mark Rutland <mark.rutland@arm.com> wrote: > Hi, > > I look forward to using this! :) > > I just have afew comments below. > > On Mon, Oct 09, 2017 at 05:05:19PM +0200, Alexander Potapenko wrote: >> +/* >> + * Defines the format for the types of collected comparisons. >> + */ >> +enum kcov_cmp_type { >> + /* >> + * LSB shows whether one of the arguments is a compile-time constant. >> + */ >> + KCOV_CMP_CONST = 1, >> + /* >> + * Second and third LSBs contain the size of arguments (1/2/4/8 bytes). >> + */ >> + KCOV_CMP_SIZE1 = 0, >> + KCOV_CMP_SIZE2 = 2, >> + KCOV_CMP_SIZE4 = 4, >> + KCOV_CMP_SIZE8 = 6, >> + KCOV_CMP_SIZE_MASK = 6, >> +}; > > Given that LSB is meant to be OR-ed in, (and hence combinations of > values are meaningful) I don't think it makes sense for this to be an > enum. This would clearer as something like: > > /* > * The format for the types of collected comparisons. > * > * Bit 0 shows whether one of the arguments is a compile-time constant. > * Bits 1 & 2 contain log2 of the argument size, up to 8 bytes. > */ > #define KCOV_CMP_CONST (1 << 0) > #define KCOV_CMP_SIZE(n) ((n) << 1) > #define KCOV_CMP_MASK KCOV_CMP_SIZE(3) Agreed. > ... I note that a few places in the kernel use a 128-bit type. Are > 128-bit comparisons not instrumented? > > [...] > >> +static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) >> +{ >> + enum kcov_mode mode; >> + >> + /* >> + * We are interested in code coverage as a function of a syscall inputs, >> + * so we ignore code executed in interrupts. >> + */ >> + if (!t || !in_task()) >> + return false; > > This !t check can go, as with the one in __sanitizer_cov_trace_pc, since > t is always current, and therefore cannot be NULL. Ok. > IIRC there's a patch queued for that, which this may conflict with. Sorry, I don't quite understand what exactly is conflicting here. >> + mode = READ_ONCE(t->kcov_mode); >> + /* >> + * There is some code that runs in interrupts but for which >> + * in_interrupt() returns false (e.g. preempt_schedule_irq()). >> + * READ_ONCE()/barrier() effectively provides load-acquire wrt >> + * interrupts, there are paired barrier()/WRITE_ONCE() in >> + * kcov_ioctl_locked(). >> + */ >> + barrier(); >> + if (mode != needed_mode) >> + return false; >> + return true; > > This would be simpler as: > > return mode == needed_mode; Agreed. > [...] > >> + area = t->kcov_area; >> + /* 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); > > Not a new problem, but if the area for one thread is mmap'd, and read by > another thread, these two writes could be seen out-of-order, since we > don't have an smp_wmb() between them. > > I guess Syzkaller doesn't read the mmap'd kcov file from another thread? (Dmitry answered this one already) >> } >> } >> EXPORT_SYMBOL(__sanitizer_cov_trace_pc); >> >> +#ifdef CONFIG_KCOV_ENABLE_COMPARISONS >> +static void 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; >> + >> + t = current; >> + if (!check_kcov_mode(KCOV_MODE_TRACE_CMP, t)) >> + return; >> + >> +#ifdef CONFIG_RANDOMIZE_BASE >> + ip -= kaslr_offset(); >> +#endif > > Given we have this in two places, it might make sense to have a helper > like: > > unsigned long canonicalize_ip(unsigned long ip) > { > #ifdef CONFIG_RANDOMIZE_BASE > ip -= kaslr_offset(); > #endif > return ip; > } Done. > ... to minimize the ifdeffery elsewhere. > >> + >> + /* >> + * We write all comparison arguments and types as u64. >> + * The buffer was allocated for t->kcov_size unsigned longs. >> + */ >> + area = (u64 *)t->kcov_area; >> + max_pos = t->kcov_size * sizeof(unsigned long); >> + >> + count = READ_ONCE(area[0]); >> + >> + /* Every record is KCOV_WORDS_PER_CMP 64-bit words. */ >> + start_index = 1 + count * KCOV_WORDS_PER_CMP; >> + end_pos = (start_index + KCOV_WORDS_PER_CMP) * sizeof(u64); >> + if (likely(end_pos <= max_pos)) { >> + area[start_index] = type; >> + area[start_index + 1] = arg1; >> + area[start_index + 2] = arg2; >> + area[start_index + 3] = ip; >> + WRITE_ONCE(area[0], count + 1); > > That ordering problem applies here, too. > > Thanks, > Mark. -- Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Paul Manicle, Halimah DeLaine Prado Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg
WARNING: multiple messages have this Message-ID (diff)
From: Alexander Potapenko <glider@google.com> To: Mark Rutland <mark.rutland@arm.com> Cc: Andrew Morton <akpm@linux-foundation.org>, Alexander Popov <alex.popov@linux.com>, Andrey Ryabinin <aryabinin@virtuozzo.com>, Quentin Casasnovas <quentin.casasnovas@oracle.com>, Dmitriy Vyukov <dvyukov@google.com>, Andrey Konovalov <andreyknvl@google.com>, Kees Cook <keescook@chromium.org>, Vegard Nossum <vegard.nossum@oracle.com>, syzkaller <syzkaller@googlegroups.com>, Linux Memory Management List <linux-mm@kvack.org>, LKML <linux-kernel@vger.kernel.org> Subject: Re: [PATCH v2 1/3] kcov: support comparison operands collection Date: Tue, 10 Oct 2017 17:28:10 +0200 [thread overview] Message-ID: <CAG_fn=UsTCyueyuMGT8i6ZoX9CWwvE9GhJAWnsJsPhf1AY2Z4Q@mail.gmail.com> (raw) In-Reply-To: <20171009154610.GA22534@leverpostej> On Mon, Oct 9, 2017 at 8:46 AM, Mark Rutland <mark.rutland@arm.com> wrote: > Hi, > > I look forward to using this! :) > > I just have afew comments below. > > On Mon, Oct 09, 2017 at 05:05:19PM +0200, Alexander Potapenko wrote: >> +/* >> + * Defines the format for the types of collected comparisons. >> + */ >> +enum kcov_cmp_type { >> + /* >> + * LSB shows whether one of the arguments is a compile-time constant. >> + */ >> + KCOV_CMP_CONST = 1, >> + /* >> + * Second and third LSBs contain the size of arguments (1/2/4/8 bytes). >> + */ >> + KCOV_CMP_SIZE1 = 0, >> + KCOV_CMP_SIZE2 = 2, >> + KCOV_CMP_SIZE4 = 4, >> + KCOV_CMP_SIZE8 = 6, >> + KCOV_CMP_SIZE_MASK = 6, >> +}; > > Given that LSB is meant to be OR-ed in, (and hence combinations of > values are meaningful) I don't think it makes sense for this to be an > enum. This would clearer as something like: > > /* > * The format for the types of collected comparisons. > * > * Bit 0 shows whether one of the arguments is a compile-time constant. > * Bits 1 & 2 contain log2 of the argument size, up to 8 bytes. > */ > #define KCOV_CMP_CONST (1 << 0) > #define KCOV_CMP_SIZE(n) ((n) << 1) > #define KCOV_CMP_MASK KCOV_CMP_SIZE(3) Agreed. > ... I note that a few places in the kernel use a 128-bit type. Are > 128-bit comparisons not instrumented? > > [...] > >> +static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t) >> +{ >> + enum kcov_mode mode; >> + >> + /* >> + * We are interested in code coverage as a function of a syscall inputs, >> + * so we ignore code executed in interrupts. >> + */ >> + if (!t || !in_task()) >> + return false; > > This !t check can go, as with the one in __sanitizer_cov_trace_pc, since > t is always current, and therefore cannot be NULL. Ok. > IIRC there's a patch queued for that, which this may conflict with. Sorry, I don't quite understand what exactly is conflicting here. >> + mode = READ_ONCE(t->kcov_mode); >> + /* >> + * There is some code that runs in interrupts but for which >> + * in_interrupt() returns false (e.g. preempt_schedule_irq()). >> + * READ_ONCE()/barrier() effectively provides load-acquire wrt >> + * interrupts, there are paired barrier()/WRITE_ONCE() in >> + * kcov_ioctl_locked(). >> + */ >> + barrier(); >> + if (mode != needed_mode) >> + return false; >> + return true; > > This would be simpler as: > > return mode == needed_mode; Agreed. > [...] > >> + area = t->kcov_area; >> + /* 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); > > Not a new problem, but if the area for one thread is mmap'd, and read by > another thread, these two writes could be seen out-of-order, since we > don't have an smp_wmb() between them. > > I guess Syzkaller doesn't read the mmap'd kcov file from another thread? (Dmitry answered this one already) >> } >> } >> EXPORT_SYMBOL(__sanitizer_cov_trace_pc); >> >> +#ifdef CONFIG_KCOV_ENABLE_COMPARISONS >> +static void 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; >> + >> + t = current; >> + if (!check_kcov_mode(KCOV_MODE_TRACE_CMP, t)) >> + return; >> + >> +#ifdef CONFIG_RANDOMIZE_BASE >> + ip -= kaslr_offset(); >> +#endif > > Given we have this in two places, it might make sense to have a helper > like: > > unsigned long canonicalize_ip(unsigned long ip) > { > #ifdef CONFIG_RANDOMIZE_BASE > ip -= kaslr_offset(); > #endif > return ip; > } Done. > ... to minimize the ifdeffery elsewhere. > >> + >> + /* >> + * We write all comparison arguments and types as u64. >> + * The buffer was allocated for t->kcov_size unsigned longs. >> + */ >> + area = (u64 *)t->kcov_area; >> + max_pos = t->kcov_size * sizeof(unsigned long); >> + >> + count = READ_ONCE(area[0]); >> + >> + /* Every record is KCOV_WORDS_PER_CMP 64-bit words. */ >> + start_index = 1 + count * KCOV_WORDS_PER_CMP; >> + end_pos = (start_index + KCOV_WORDS_PER_CMP) * sizeof(u64); >> + if (likely(end_pos <= max_pos)) { >> + area[start_index] = type; >> + area[start_index + 1] = arg1; >> + area[start_index + 2] = arg2; >> + area[start_index + 3] = ip; >> + WRITE_ONCE(area[0], count + 1); > > That ordering problem applies here, too. > > Thanks, > Mark. -- Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Paul Manicle, Halimah DeLaine Prado Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2017-10-10 15:28 UTC|newest] Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-10-09 15:05 [PATCH v2 1/3] kcov: support comparison operands collection Alexander Potapenko 2017-10-09 15:05 ` Alexander Potapenko 2017-10-09 15:05 ` [PATCH v2 2/3] Makefile: support flag -fsanitizer-coverage=trace-cmp Alexander Potapenko 2017-10-09 15:05 ` Alexander Potapenko 2017-10-09 15:53 ` Andrey Ryabinin 2017-10-09 15:53 ` Andrey Ryabinin 2017-10-10 15:28 ` Alexander Potapenko 2017-10-10 15:28 ` Alexander Potapenko 2017-10-10 21:53 ` kbuild test robot 2017-10-09 15:05 ` [PATCH v2 3/3] kcov: update documentation Alexander Potapenko 2017-10-09 15:05 ` Alexander Potapenko 2017-10-09 15:46 ` [PATCH v2 1/3] kcov: support comparison operands collection Mark Rutland 2017-10-09 15:46 ` Mark Rutland 2017-10-09 18:15 ` Dmitry Vyukov 2017-10-09 18:15 ` Dmitry Vyukov 2017-10-09 18:37 ` Mark Rutland 2017-10-09 18:37 ` Mark Rutland 2017-10-09 18:46 ` Dmitry Vyukov 2017-10-09 18:46 ` Dmitry Vyukov 2017-10-10 9:56 ` Mark Rutland 2017-10-10 9:56 ` Mark Rutland 2017-10-10 15:28 ` Alexander Potapenko [this message] 2017-10-10 15:28 ` Alexander Potapenko 2017-10-10 15:34 ` Dmitry Vyukov 2017-10-10 15:34 ` Dmitry Vyukov 2017-10-11 9:56 ` Alexander Potapenko 2017-10-11 9:56 ` Alexander Potapenko
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='CAG_fn=UsTCyueyuMGT8i6ZoX9CWwvE9GhJAWnsJsPhf1AY2Z4Q@mail.gmail.com' \ --to=glider@google.com \ --cc=akpm@linux-foundation.org \ --cc=alex.popov@linux.com \ --cc=andreyknvl@google.com \ --cc=aryabinin@virtuozzo.com \ --cc=dvyukov@google.com \ --cc=keescook@chromium.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mm@kvack.org \ --cc=mark.rutland@arm.com \ --cc=quentin.casasnovas@oracle.com \ --cc=syzkaller@googlegroups.com \ --cc=vegard.nossum@oracle.com \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.