Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8fa80c50 authored by Will Deacon's avatar Will Deacon Committed by Ingo Molnar
Browse files

nospec: Move array_index_nospec() parameter checking into separate macro



For architectures providing their own implementation of
array_index_mask_nospec() in asm/barrier.h, attempting to use WARN_ONCE() to
complain about out-of-range parameters using WARN_ON() results in a mess
of mutually-dependent include files.

Rather than unpick the dependencies, simply have the core code in nospec.h
perform the checking for us.

Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Acked-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1517840166-15399-1-git-send-email-will.deacon@arm.com


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent be3233fb
Loading
Loading
Loading
Loading
+21 −15
Original line number Diff line number Diff line
@@ -19,6 +19,16 @@
static inline unsigned long array_index_mask_nospec(unsigned long index,
						    unsigned long size)
{
	/*
	 * Always calculate and emit the mask even if the compiler
	 * thinks the mask is not needed. The compiler does not take
	 * into account the value of @index under speculation.
	 */
	OPTIMIZER_HIDE_VAR(index);
	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
}
#endif

/*
 * Warn developers about inappropriate array_index_nospec() usage.
 *
@@ -29,19 +39,15 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
 * This warning is compiled out when the compiler can infer that
 * @index and @size are less than LONG_MAX.
 */
	if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,
			"array_index_nospec() limited to range of [0, LONG_MAX]\n"))
		return 0;

	/*
	 * Always calculate and emit the mask even if the compiler
	 * thinks the mask is not needed. The compiler does not take
	 * into account the value of @index under speculation.
	 */
	OPTIMIZER_HIDE_VAR(index);
	return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
}
#endif
#define array_index_mask_nospec_check(index, size)				\
({										\
	if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,			\
	    "array_index_nospec() limited to range of [0, LONG_MAX]\n"))	\
		_mask = 0;							\
	else									\
		_mask = array_index_mask_nospec(index, size);			\
	_mask;									\
})

/*
 * array_index_nospec - sanitize an array index after a bounds check
@@ -61,7 +67,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
({									\
	typeof(index) _i = (index);					\
	typeof(size) _s = (size);					\
	unsigned long _mask = array_index_mask_nospec(_i, _s);		\
	unsigned long _mask = array_index_mask_nospec_check(_i, _s);	\
									\
	BUILD_BUG_ON(sizeof(_i) > sizeof(long));			\
	BUILD_BUG_ON(sizeof(_s) > sizeof(long));			\