Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf, tnums: Warn against the usage of tnum_in(tnum_range(), ...)

Commit a657182a5c51 ("bpf: Don't use tnum_range on array range checking
for poke descriptors") has shown that using tnum_range() as argument to
tnum_in() can lead to misleading code that looks like tight bound check
when in fact the actual allowed range is much wider.

Document such behavior to warn against its usage in general, and suggest
some scenario where result can be trusted.

Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/984b37f9fdf7ac36831d2137415a4a915744c1b6.1661462653.git.daniel@iogearbox.net
Link: https://www.openwall.com/lists/oss-security/2022/08/26/1
Link: https://lore.kernel.org/bpf/20220831031907.16133-3-shung-hsi.yu@suse.com
Link: https://lore.kernel.org/bpf/20220831031907.16133-2-shung-hsi.yu@suse.com

authored by

Shung-Hsi Yu and committed by
Daniel Borkmann
dc84dbbc ef331a8d

+18 -2
+18 -2
include/linux/tnum.h
··· 21 21 struct tnum tnum_const(u64 value); 22 22 /* A completely unknown value */ 23 23 extern const struct tnum tnum_unknown; 24 - /* A value that's unknown except that @min <= value <= @max */ 24 + /* An unknown value that is a superset of @min <= value <= @max. 25 + * 26 + * Could include values outside the range of [@min, @max]. 27 + * For example tnum_range(0, 2) is represented by {0, 1, 2, *3*}, 28 + * rather than the intended set of {0, 1, 2}. 29 + */ 25 30 struct tnum tnum_range(u64 min, u64 max); 26 31 27 32 /* Arithmetic and logical ops */ ··· 78 73 */ 79 74 bool tnum_is_aligned(struct tnum a, u64 size); 80 75 81 - /* Returns true if @b represents a subset of @a. */ 76 + /* Returns true if @b represents a subset of @a. 77 + * 78 + * Note that using tnum_range() as @a requires extra cautions as tnum_in() may 79 + * return true unexpectedly due to tnum limited ability to represent tight 80 + * range, e.g. 81 + * 82 + * tnum_in(tnum_range(0, 2), tnum_const(3)) == true 83 + * 84 + * As a rule of thumb, if @a is explicitly coded rather than coming from 85 + * reg->var_off, it should be in form of tnum_const(), tnum_range(0, 2**n - 1), 86 + * or tnum_range(2**n, 2**(n+1) - 1). 87 + */ 82 88 bool tnum_in(struct tnum a, struct tnum b); 83 89 84 90 /* Formatting functions. These have snprintf-like semantics: they will write