Line data Source code
1 0 : /*
2 : * Copyright (c) 2019 Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_MISC_SPECULATION_H
8 : #define ZEPHYR_MISC_SPECULATION_H
9 :
10 : #include <zephyr/types.h>
11 :
12 : /**
13 : * Sanitize an array index against bounds check bypass attacks aka the
14 : * Spectre V1 vulnerability.
15 : *
16 : * CPUs with speculative execution may speculate past any size checks and
17 : * leak confidential data due to analysis of micro-architectural properties.
18 : * This will unconditionally truncate any out-of-bounds indexes to
19 : * zero in the speculative execution path using bit twiddling instead of
20 : * any branch instructions.
21 : *
22 : * Example usage:
23 : *
24 : * if (index < size) {
25 : * index = k_array_index_sanitize(index, size);
26 : * data = array[index];
27 : * }
28 : *
29 : * @param index Untrusted array index which has been validated, but not used
30 : * @param array_size Size of the array
31 : * @return The original index value if < size, or 0
32 : */
33 1 : static inline uint32_t k_array_index_sanitize(uint32_t index, uint32_t array_size)
34 : {
35 : #ifdef CONFIG_BOUNDS_CHECK_BYPASS_MITIGATION
36 : int32_t signed_index = index, signed_array_size = array_size;
37 :
38 : /* Take the difference between index and max.
39 : * A proper value will result in a negative result. We also AND in
40 : * the complement of index, so that we automatically reject any large
41 : * indexes which would wrap around the difference calculation.
42 : *
43 : * Sign-extend just the sign bit to produce a mask of all 1s (accept)
44 : * or all 0s (truncate).
45 : */
46 : uint32_t mask = ((signed_index - signed_array_size) & ~signed_index) >> 31;
47 :
48 : return index & mask;
49 : #else
50 : ARG_UNUSED(array_size);
51 :
52 : return index;
53 : #endif /* CONFIG_BOUNDS_CHECK_BYPASS_MITIGATION */
54 : }
55 : #endif /* ZEPHYR_MISC_SPECULATION_H */
|