diff options
author | Edward Cree <ecree@solarflare.com> | 2017-08-07 10:26:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-08-08 20:51:34 -0400 |
commit | f1174f77b50c94eecaa658fdc56fa69b421de4b8 (patch) | |
tree | d6e11577190ab47f4c371da21cf1f0f14da66db0 /include/linux/tnum.h | |
parent | e1cb90f2b83b6b48deeba0ac9f1920693cbad7e1 (diff) |
bpf/verifier: rework value tracking
Unifies adjusted and unadjusted register value types (e.g. FRAME_POINTER is
now just a PTR_TO_STACK with zero offset).
Tracks value alignment by means of tracking known & unknown bits. This
also replaces the 'reg->imm' (leading zero bits) calculations for (what
were) UNKNOWN_VALUEs.
If pointer leaks are allowed, and adjust_ptr_min_max_vals returns -EACCES,
treat the pointer as an unknown scalar and try again, because we might be
able to conclude something about the result (e.g. pointer & 0x40 is either
0 or 0x40).
Verifier hooks in the netronome/nfp driver were changed to match the new
data structures.
Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/tnum.h')
-rw-r--r-- | include/linux/tnum.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/include/linux/tnum.h b/include/linux/tnum.h new file mode 100644 index 000000000000..a0b07bf1842b --- /dev/null +++ b/include/linux/tnum.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* tnum: tracked (or tristate) numbers | ||
2 | * | ||
3 | * A tnum tracks knowledge about the bits of a value. Each bit can be either | ||
4 | * known (0 or 1), or unknown (x). Arithmetic operations on tnums will | ||
5 | * propagate the unknown bits such that the tnum result represents all the | ||
6 | * possible results for possible values of the operands. | ||
7 | */ | ||
8 | #include <linux/types.h> | ||
9 | |||
10 | struct tnum { | ||
11 | u64 value; | ||
12 | u64 mask; | ||
13 | }; | ||
14 | |||
15 | /* Constructors */ | ||
16 | /* Represent a known constant as a tnum. */ | ||
17 | struct tnum tnum_const(u64 value); | ||
18 | /* A completely unknown value */ | ||
19 | extern const struct tnum tnum_unknown; | ||
20 | |||
21 | /* Arithmetic and logical ops */ | ||
22 | /* Shift a tnum left (by a fixed shift) */ | ||
23 | struct tnum tnum_lshift(struct tnum a, u8 shift); | ||
24 | /* Shift a tnum right (by a fixed shift) */ | ||
25 | struct tnum tnum_rshift(struct tnum a, u8 shift); | ||
26 | /* Add two tnums, return @a + @b */ | ||
27 | struct tnum tnum_add(struct tnum a, struct tnum b); | ||
28 | /* Subtract two tnums, return @a - @b */ | ||
29 | struct tnum tnum_sub(struct tnum a, struct tnum b); | ||
30 | /* Bitwise-AND, return @a & @b */ | ||
31 | struct tnum tnum_and(struct tnum a, struct tnum b); | ||
32 | /* Bitwise-OR, return @a | @b */ | ||
33 | struct tnum tnum_or(struct tnum a, struct tnum b); | ||
34 | /* Bitwise-XOR, return @a ^ @b */ | ||
35 | struct tnum tnum_xor(struct tnum a, struct tnum b); | ||
36 | /* Multiply two tnums, return @a * @b */ | ||
37 | struct tnum tnum_mul(struct tnum a, struct tnum b); | ||
38 | |||
39 | /* Return a tnum representing numbers satisfying both @a and @b */ | ||
40 | struct tnum tnum_intersect(struct tnum a, struct tnum b); | ||
41 | |||
42 | /* Return @a with all but the lowest @size bytes cleared */ | ||
43 | struct tnum tnum_cast(struct tnum a, u8 size); | ||
44 | |||
45 | /* Returns true if @a is a known constant */ | ||
46 | static inline bool tnum_is_const(struct tnum a) | ||
47 | { | ||
48 | return !a.mask; | ||
49 | } | ||
50 | |||
51 | /* Returns true if @a == tnum_const(@b) */ | ||
52 | static inline bool tnum_equals_const(struct tnum a, u64 b) | ||
53 | { | ||
54 | return tnum_is_const(a) && a.value == b; | ||
55 | } | ||
56 | |||
57 | /* Returns true if @a is completely unknown */ | ||
58 | static inline bool tnum_is_unknown(struct tnum a) | ||
59 | { | ||
60 | return !~a.mask; | ||
61 | } | ||
62 | |||
63 | /* Returns true if @a is known to be a multiple of @size. | ||
64 | * @size must be a power of two. | ||
65 | */ | ||
66 | bool tnum_is_aligned(struct tnum a, u64 size); | ||
67 | |||
68 | /* Returns true if @b represents a subset of @a. */ | ||
69 | bool tnum_in(struct tnum a, struct tnum b); | ||
70 | |||
71 | /* Formatting functions. These have snprintf-like semantics: they will write | ||
72 | * up to @size bytes (including the terminating NUL byte), and return the number | ||
73 | * of bytes (excluding the terminating NUL) which would have been written had | ||
74 | * sufficient space been available. (Thus tnum_sbin always returns 64.) | ||
75 | */ | ||
76 | /* Format a tnum as a pair of hex numbers (value; mask) */ | ||
77 | int tnum_strn(char *str, size_t size, struct tnum a); | ||
78 | /* Format a tnum as tristate binary expansion */ | ||
79 | int tnum_sbin(char *str, size_t size, struct tnum a); | ||