cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

permissive.h (2716B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Special rules for ignoring entire classes of data-racy memory accesses. None
      4 * of the rules here imply that such data races are generally safe!
      5 *
      6 * All rules in this file can be configured via CONFIG_KCSAN_PERMISSIVE. Keep
      7 * them separate from core code to make it easier to audit.
      8 *
      9 * Copyright (C) 2019, Google LLC.
     10 */
     11
     12#ifndef _KERNEL_KCSAN_PERMISSIVE_H
     13#define _KERNEL_KCSAN_PERMISSIVE_H
     14
     15#include <linux/bitops.h>
     16#include <linux/sched.h>
     17#include <linux/types.h>
     18
     19/*
     20 * Access ignore rules based on address.
     21 */
     22static __always_inline bool kcsan_ignore_address(const volatile void *ptr)
     23{
     24	if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE))
     25		return false;
     26
     27	/*
     28	 * Data-racy bitops on current->flags are too common, ignore completely
     29	 * for now.
     30	 */
     31	return ptr == &current->flags;
     32}
     33
     34/*
     35 * Data race ignore rules based on access type and value change patterns.
     36 */
     37static bool
     38kcsan_ignore_data_race(size_t size, int type, u64 old, u64 new, u64 diff)
     39{
     40	if (!IS_ENABLED(CONFIG_KCSAN_PERMISSIVE))
     41		return false;
     42
     43	/*
     44	 * Rules here are only for plain read accesses, so that we still report
     45	 * data races between plain read-write accesses.
     46	 */
     47	if (type || size > sizeof(long))
     48		return false;
     49
     50	/*
     51	 * A common pattern is checking/setting just 1 bit in a variable; for
     52	 * example:
     53	 *
     54	 *	if (flags & SOME_FLAG) { ... }
     55	 *
     56	 * and elsewhere flags is updated concurrently:
     57	 *
     58	 *	flags |= SOME_OTHER_FLAG; // just 1 bit
     59	 *
     60	 * While it is still recommended that such accesses be marked
     61	 * appropriately, in many cases these types of data races are so common
     62	 * that marking them all is often unrealistic and left to maintainer
     63	 * preference.
     64	 *
     65	 * The assumption in all cases is that with all known compiler
     66	 * optimizations (including those that tear accesses), because no more
     67	 * than 1 bit changed, the plain accesses are safe despite the presence
     68	 * of data races.
     69	 *
     70	 * The rules here will ignore the data races if we observe no more than
     71	 * 1 bit changed.
     72	 *
     73	 * Of course many operations can effecively change just 1 bit, but the
     74	 * general assuption that data races involving 1-bit changes can be
     75	 * tolerated still applies.
     76	 *
     77	 * And in case a true bug is missed, the bug likely manifests as a
     78	 * reportable data race elsewhere.
     79	 */
     80	if (hweight64(diff) == 1) {
     81		/*
     82		 * Exception: Report data races where the values look like
     83		 * ordinary booleans (one of them was 0 and the 0th bit was
     84		 * changed) More often than not, they come with interesting
     85		 * memory ordering requirements, so let's report them.
     86		 */
     87		if (!((!old || !new) && diff == 1))
     88			return true;
     89	}
     90
     91	return false;
     92}
     93
     94#endif /* _KERNEL_KCSAN_PERMISSIVE_H */