Skip to content

Commit 72c6d6e

Browse files
anakryikoKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
bpf: generalize reg_set_min_max() to handle non-const register comparisons
Generalize bounds adjustment logic of reg_set_min_max() to handle not just register vs constant case, but in general any register vs any register cases. For most of the operations it's trivial extension based on range vs range comparison logic, we just need to properly pick min/max of a range to compare against min/max of the other range. For BPF_JSET we keep the original capabilities, just make sure JSET is integrated in the common framework. This is manifested in the internal-only BPF_JSET + BPF_X "opcode" to allow for simpler and more uniform rev_opcode() handling. See the code for details. This allows to reuse the same code exactly both for TRUE and FALSE branches without explicitly handling both conditions with custom code. Note also that now we don't need a special handling of BPF_JEQ/BPF_JNE case none of the registers are constants. This is now just a normal generic case handled by reg_set_min_max(). To make tnum handling cleaner, tnum_with_subreg() helper is added, as that's a common operator when dealing with 32-bit subregister bounds. This keeps the overall logic much less noisy when it comes to tnums. Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]>
1 parent ccfd26f commit 72c6d6e

File tree

3 files changed

+146
-179
lines changed

3 files changed

+146
-179
lines changed

include/linux/tnum.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ int tnum_sbin(char *str, size_t size, struct tnum a);
106106
struct tnum tnum_subreg(struct tnum a);
107107
/* Returns the tnum with the lower 32-bit subreg cleared */
108108
struct tnum tnum_clear_subreg(struct tnum a);
109+
/* Returns the tnum with the lower 32-bit subreg in *reg* set to the lower
110+
* 32-bit subreg in *subreg*
111+
*/
112+
struct tnum tnum_with_subreg(struct tnum reg, struct tnum subreg);
109113
/* Returns the tnum with the lower 32-bit subreg set to value */
110114
struct tnum tnum_const_subreg(struct tnum a, u32 value);
111115
/* Returns true if 32-bit subreg @a is a known constant*/

kernel/bpf/tnum.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,12 @@ struct tnum tnum_clear_subreg(struct tnum a)
208208
return tnum_lshift(tnum_rshift(a, 32), 32);
209209
}
210210

211+
struct tnum tnum_with_subreg(struct tnum reg, struct tnum subreg)
212+
{
213+
return tnum_or(tnum_clear_subreg(reg), tnum_subreg(subreg));
214+
}
215+
211216
struct tnum tnum_const_subreg(struct tnum a, u32 value)
212217
{
213-
return tnum_or(tnum_clear_subreg(a), tnum_const(value));
218+
return tnum_with_subreg(a, tnum_const(value));
214219
}

0 commit comments

Comments
 (0)