History

kcsan: Remove reporting indirection

Now that we have separate kcsan_report_*() functions, we can factor the distinct logic for each of the report cases out of kcsan_report(). While this means each case has to handle mutual exclusion independently, this minimizes the conditionality of code and makes it easier to read, and will permit passing distinct bits of information to print_report() in future. There should be no functional change as a result of this patch.

Mark Rutland committed 5 years ago

Commit 19dfdc01 parent 39b2e761 file · +49 −66Browse files

Unified · Split

kernel/kcsan/report.c+49−66
@@ -434,13 +434,11 @@ static void print_report(enum kcsan_value_change value_change, · 433 unmodified lines
434434
435435 static void release_report(unsigned long *flags, struct other_info *other_info)
436436 {
437− if (other_info)
438− /*
439− * Use size to denote valid/invalid, since KCSAN entirely
440− * ignores 0-sized accesses.
441− */
442− other_info->ai.size = 0;
443−
437+ /*
438+ * Use size to denote valid/invalid, since KCSAN entirely ignores
439+ * 0-sized accesses.
440+ */
441+ other_info->ai.size = 0;
444442 raw_spin_unlock_irqrestore(&report_lock, *flags);
445443 }
446444
@@ -573,61 +571,6 @@ discard: · 126 unmodified lines
573571 return false;
574572 }
575573
576−/*
577− * Depending on the report type either sets @other_info and returns false, or
578− * awaits @other_info and returns true. If @other_info is not required for the
579− * report type, simply acquires @report_lock and returns true.
580− */
581−static noinline bool prepare_report(unsigned long *flags,
582− enum kcsan_report_type type,
583− const struct access_info *ai,
584− struct other_info *other_info)
585−{
586− switch (type) {
587− case KCSAN_REPORT_CONSUMED_WATCHPOINT:
588− prepare_report_producer(flags, ai, other_info);
589− return false;
590− case KCSAN_REPORT_RACE_SIGNAL:
591− return prepare_report_consumer(flags, ai, other_info);
592− default:
593− /* @other_info not required; just acquire @report_lock. */
594− raw_spin_lock_irqsave(&report_lock, *flags);
595− return true;
596− }
597−}
598−
599−static void kcsan_report(const struct access_info *ai, enum kcsan_value_change value_change,
600− enum kcsan_report_type type, struct other_info *other_info)
601−{
602− unsigned long flags = 0;
603−
604− kcsan_disable_current();
605−
606− /*
607− * Because we may generate reports when we're in scheduler code, the use
608− * of printk() could deadlock. Until such time that all printing code
609− * called in print_report() is scheduler-safe, accept the risk, and just
610− * get our message out. As such, also disable lockdep to hide the
611− * warning, and avoid disabling lockdep for the rest of the kernel.
612− */
613− lockdep_off();
614−
615− if (prepare_report(&flags, type, ai, other_info)) {
616− /*
617− * Never report if value_change is FALSE, only if we it is
618− * either TRUE or MAYBE. In case of MAYBE, further filtering may
619− * be done once we know the full stack trace in print_report().
620− */
621− if (value_change != KCSAN_VALUE_CHANGE_FALSE)
622− print_report(value_change, type, ai, other_info);
623−
624− release_report(&flags, other_info);
625− }
626−
627− lockdep_on();
628− kcsan_enable_current();
629−}
630−
631574 static struct access_info prepare_access_info(const volatile void *ptr, size_t size,
632575 int access_type)
633576 {
@@ -644,22 +587,62 @@ void kcsan_report_set_info(const volatile void *ptr, size_t size, int access_typ · 10 unmodified lines
644587 int watchpoint_idx)
645588 {
646589 const struct access_info ai = prepare_access_info(ptr, size, access_type);
590+ unsigned long flags;
591+
592+ kcsan_disable_current();
593+ lockdep_off(); /* See kcsan_report_known_origin(). */
647594
648− kcsan_report(&ai, KCSAN_VALUE_CHANGE_MAYBE, KCSAN_REPORT_CONSUMED_WATCHPOINT,
649− &other_infos[watchpoint_idx]);
595+ prepare_report_producer(&flags, &ai, &other_infos[watchpoint_idx]);
596+
597+ lockdep_on();
598+ kcsan_enable_current();
650599 }
651600
652601 void kcsan_report_known_origin(const volatile void *ptr, size_t size, int access_type,
653602 enum kcsan_value_change value_change, int watchpoint_idx)
654603 {
655604 const struct access_info ai = prepare_access_info(ptr, size, access_type);
605+ struct other_info *other_info = &other_infos[watchpoint_idx];
606+ unsigned long flags = 0;
656607
657− kcsan_report(&ai, value_change, KCSAN_REPORT_RACE_SIGNAL, &other_infos[watchpoint_idx]);
608+ kcsan_disable_current();
609+ /*
610+ * Because we may generate reports when we're in scheduler code, the use
611+ * of printk() could deadlock. Until such time that all printing code
612+ * called in print_report() is scheduler-safe, accept the risk, and just
613+ * get our message out. As such, also disable lockdep to hide the
614+ * warning, and avoid disabling lockdep for the rest of the kernel.
615+ */
616+ lockdep_off();
617+
618+ if (!prepare_report_consumer(&flags, &ai, other_info))
619+ goto out;
620+ /*
621+ * Never report if value_change is FALSE, only when it is
622+ * either TRUE or MAYBE. In case of MAYBE, further filtering may
623+ * be done once we know the full stack trace in print_report().
624+ */
625+ if (value_change != KCSAN_VALUE_CHANGE_FALSE)
626+ print_report(value_change, KCSAN_REPORT_RACE_SIGNAL, &ai, other_info);
627+
628+ release_report(&flags, other_info);
629+out:
630+ lockdep_on();
631+ kcsan_enable_current();
658632 }
659633
660634 void kcsan_report_unknown_origin(const volatile void *ptr, size_t size, int access_type)
661635 {
662636 const struct access_info ai = prepare_access_info(ptr, size, access_type);
637+ unsigned long flags;
638+
639+ kcsan_disable_current();
640+ lockdep_off(); /* See kcsan_report_known_origin(). */
641+
642+ raw_spin_lock_irqsave(&report_lock, flags);
643+ print_report(KCSAN_VALUE_CHANGE_TRUE, KCSAN_REPORT_RACE_UNKNOWN_ORIGIN, &ai, NULL);
644+ raw_spin_unlock_irqrestore(&report_lock, flags);
663645
664− kcsan_report(&ai, KCSAN_VALUE_CHANGE_TRUE, KCSAN_REPORT_RACE_UNKNOWN_ORIGIN, NULL);
646+ lockdep_on();
647+ kcsan_enable_current();
665648 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t