forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: Add a testcase for 64-bit bounds propagation issue.
./test_progs-no_alu32 -vv -t twfw Before the 64-bit_into_32-bit fix: 19: (25) if r1 > 0x3f goto pc+6 R1_w=inv(id=0,umax_value=63,var_off=(0x0; 0xff),s32_max_value=255,u32_max_value=255) and eventually: invalid access to map value, value_size=8 off=7 size=8 R6 max value is outside of the allowed memory range libbpf: failed to load object 'no_alu32/twfw.o' After the fix: 19: (25) if r1 > 0x3f goto pc+6 R1_w=inv(id=0,umax_value=63,var_off=(0x0; 0x3f)) verif_twfw:OK Signed-off-by: Alexei Starovoitov <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
- Loading branch information
Showing
2 changed files
with
63 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2021 Facebook */ | ||
#include <linux/types.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <linux/bpf.h> | ||
#include <stdint.h> | ||
|
||
#define TWFW_MAX_TIERS (64) | ||
/* | ||
* load is successful | ||
* #define TWFW_MAX_TIERS (64u)$ | ||
*/ | ||
|
||
struct twfw_tier_value { | ||
unsigned long mask[1]; | ||
}; | ||
|
||
struct rule { | ||
uint8_t seqnum; | ||
}; | ||
|
||
struct rules_map { | ||
__uint(type, BPF_MAP_TYPE_ARRAY); | ||
__type(key, __u32); | ||
__type(value, struct rule); | ||
__uint(max_entries, 1); | ||
}; | ||
|
||
struct tiers_map { | ||
__uint(type, BPF_MAP_TYPE_ARRAY); | ||
__type(key, __u32); | ||
__type(value, struct twfw_tier_value); | ||
__uint(max_entries, 1); | ||
}; | ||
|
||
struct rules_map rules SEC(".maps"); | ||
struct tiers_map tiers SEC(".maps"); | ||
|
||
SEC("cgroup_skb/ingress") | ||
int twfw_verifier(struct __sk_buff* skb) | ||
{ | ||
const uint32_t key = 0; | ||
const struct twfw_tier_value* tier = bpf_map_lookup_elem(&tiers, &key); | ||
if (!tier) | ||
return 1; | ||
|
||
struct rule* rule = bpf_map_lookup_elem(&rules, &key); | ||
if (!rule) | ||
return 1; | ||
|
||
if (rule && rule->seqnum < TWFW_MAX_TIERS) { | ||
/* rule->seqnum / 64 should always be 0 */ | ||
unsigned long mask = tier->mask[rule->seqnum / 64]; | ||
if (mask) | ||
return 0; | ||
} | ||
return 1; | ||
} |