Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Alexei Starovoitov says: ==================== pull-request: bpf-next 2019-04-22 The following pull-request contains BPF updates for your *net-next* tree. The main changes are: 1) allow stack/queue helpers from more bpf program types, from Alban. 2) allow parallel verification of root bpf programs, from Alexei. 3) introduce bpf sysctl hook for trusted root cases, from Andrey. 4) recognize var/datasec in btf deduplication, from Andrii. 5) cpumap performance optimizations, from Jesper. 6) verifier prep for alu32 optimization, from Jiong. 7) libbpf xsk cleanup, from Magnus. 8) other various fixes and cleanups. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -23,7 +23,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test
|
||||
test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
|
||||
test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \
|
||||
test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \
|
||||
test_netcnt test_tcpnotify_user test_sock_fields
|
||||
test_netcnt test_tcpnotify_user test_sock_fields test_sysctl
|
||||
|
||||
BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c)))
|
||||
TEST_GEN_FILES = $(BPF_OBJ_FILES)
|
||||
@@ -93,6 +93,7 @@ $(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c
|
||||
$(OUTPUT)/test_cgroup_storage: cgroup_helpers.c
|
||||
$(OUTPUT)/test_netcnt: cgroup_helpers.c
|
||||
$(OUTPUT)/test_sock_fields: cgroup_helpers.c
|
||||
$(OUTPUT)/test_sysctl: cgroup_helpers.c
|
||||
|
||||
.PHONY: force
|
||||
|
||||
|
@@ -192,6 +192,25 @@ static int (*bpf_skb_ecn_set_ce)(void *ctx) =
|
||||
static int (*bpf_tcp_check_syncookie)(struct bpf_sock *sk,
|
||||
void *ip, int ip_len, void *tcp, int tcp_len) =
|
||||
(void *) BPF_FUNC_tcp_check_syncookie;
|
||||
static int (*bpf_sysctl_get_name)(void *ctx, char *buf,
|
||||
unsigned long long buf_len,
|
||||
unsigned long long flags) =
|
||||
(void *) BPF_FUNC_sysctl_get_name;
|
||||
static int (*bpf_sysctl_get_current_value)(void *ctx, char *buf,
|
||||
unsigned long long buf_len) =
|
||||
(void *) BPF_FUNC_sysctl_get_current_value;
|
||||
static int (*bpf_sysctl_get_new_value)(void *ctx, char *buf,
|
||||
unsigned long long buf_len) =
|
||||
(void *) BPF_FUNC_sysctl_get_new_value;
|
||||
static int (*bpf_sysctl_set_new_value)(void *ctx, const char *buf,
|
||||
unsigned long long buf_len) =
|
||||
(void *) BPF_FUNC_sysctl_set_new_value;
|
||||
static int (*bpf_strtol)(const char *buf, unsigned long long buf_len,
|
||||
unsigned long long flags, long *res) =
|
||||
(void *) BPF_FUNC_strtol;
|
||||
static int (*bpf_strtoul)(const char *buf, unsigned long long buf_len,
|
||||
unsigned long long flags, unsigned long *res) =
|
||||
(void *) BPF_FUNC_strtoul;
|
||||
|
||||
/* llvm builtin functions that eBPF C program may use to
|
||||
* emit BPF_LD_ABS and BPF_LD_IND instructions
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#include <test_progs.h>
|
||||
|
||||
#define CHECK_FLOW_KEYS(desc, got, expected) \
|
||||
CHECK(memcmp(&got, &expected, sizeof(got)) != 0, \
|
||||
CHECK_ATTR(memcmp(&got, &expected, sizeof(got)) != 0, \
|
||||
desc, \
|
||||
"nhoff=%u/%u " \
|
||||
"thoff=%u/%u " \
|
||||
@@ -10,6 +10,7 @@
|
||||
"is_frag=%u/%u " \
|
||||
"is_first_frag=%u/%u " \
|
||||
"is_encap=%u/%u " \
|
||||
"ip_proto=0x%x/0x%x " \
|
||||
"n_proto=0x%x/0x%x " \
|
||||
"sport=%u/%u " \
|
||||
"dport=%u/%u\n", \
|
||||
@@ -19,53 +20,32 @@
|
||||
got.is_frag, expected.is_frag, \
|
||||
got.is_first_frag, expected.is_first_frag, \
|
||||
got.is_encap, expected.is_encap, \
|
||||
got.ip_proto, expected.ip_proto, \
|
||||
got.n_proto, expected.n_proto, \
|
||||
got.sport, expected.sport, \
|
||||
got.dport, expected.dport)
|
||||
|
||||
static struct bpf_flow_keys pkt_v4_flow_keys = {
|
||||
.nhoff = 0,
|
||||
.thoff = sizeof(struct iphdr),
|
||||
.addr_proto = ETH_P_IP,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
};
|
||||
struct ipv4_pkt {
|
||||
struct ethhdr eth;
|
||||
struct iphdr iph;
|
||||
struct tcphdr tcp;
|
||||
} __packed;
|
||||
|
||||
static struct bpf_flow_keys pkt_v6_flow_keys = {
|
||||
.nhoff = 0,
|
||||
.thoff = sizeof(struct ipv6hdr),
|
||||
.addr_proto = ETH_P_IPV6,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IPV6),
|
||||
};
|
||||
|
||||
#define VLAN_HLEN 4
|
||||
|
||||
static struct {
|
||||
struct svlan_ipv4_pkt {
|
||||
struct ethhdr eth;
|
||||
__u16 vlan_tci;
|
||||
__u16 vlan_proto;
|
||||
struct iphdr iph;
|
||||
struct tcphdr tcp;
|
||||
} __packed pkt_vlan_v4 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_8021Q),
|
||||
.vlan_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
.iph.ihl = 5,
|
||||
.iph.protocol = IPPROTO_TCP,
|
||||
.iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.urg_ptr = 123,
|
||||
.tcp.doff = 5,
|
||||
};
|
||||
} __packed;
|
||||
|
||||
static struct bpf_flow_keys pkt_vlan_v4_flow_keys = {
|
||||
.nhoff = VLAN_HLEN,
|
||||
.thoff = VLAN_HLEN + sizeof(struct iphdr),
|
||||
.addr_proto = ETH_P_IP,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
};
|
||||
struct ipv6_pkt {
|
||||
struct ethhdr eth;
|
||||
struct ipv6hdr iph;
|
||||
struct tcphdr tcp;
|
||||
} __packed;
|
||||
|
||||
static struct {
|
||||
struct dvlan_ipv6_pkt {
|
||||
struct ethhdr eth;
|
||||
__u16 vlan_tci;
|
||||
__u16 vlan_proto;
|
||||
@@ -73,31 +53,97 @@ static struct {
|
||||
__u16 vlan_proto2;
|
||||
struct ipv6hdr iph;
|
||||
struct tcphdr tcp;
|
||||
} __packed pkt_vlan_v6 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_8021AD),
|
||||
.vlan_proto = __bpf_constant_htons(ETH_P_8021Q),
|
||||
.vlan_proto2 = __bpf_constant_htons(ETH_P_IPV6),
|
||||
.iph.nexthdr = IPPROTO_TCP,
|
||||
.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.urg_ptr = 123,
|
||||
.tcp.doff = 5,
|
||||
} __packed;
|
||||
|
||||
struct test {
|
||||
const char *name;
|
||||
union {
|
||||
struct ipv4_pkt ipv4;
|
||||
struct svlan_ipv4_pkt svlan_ipv4;
|
||||
struct ipv6_pkt ipv6;
|
||||
struct dvlan_ipv6_pkt dvlan_ipv6;
|
||||
} pkt;
|
||||
struct bpf_flow_keys keys;
|
||||
};
|
||||
|
||||
static struct bpf_flow_keys pkt_vlan_v6_flow_keys = {
|
||||
.nhoff = VLAN_HLEN * 2,
|
||||
.thoff = VLAN_HLEN * 2 + sizeof(struct ipv6hdr),
|
||||
.addr_proto = ETH_P_IPV6,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IPV6),
|
||||
#define VLAN_HLEN 4
|
||||
|
||||
struct test tests[] = {
|
||||
{
|
||||
.name = "ipv4",
|
||||
.pkt.ipv4 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
.iph.ihl = 5,
|
||||
.iph.protocol = IPPROTO_TCP,
|
||||
.iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.doff = 5,
|
||||
},
|
||||
.keys = {
|
||||
.nhoff = 0,
|
||||
.thoff = sizeof(struct iphdr),
|
||||
.addr_proto = ETH_P_IP,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "ipv6",
|
||||
.pkt.ipv6 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
|
||||
.iph.nexthdr = IPPROTO_TCP,
|
||||
.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.doff = 5,
|
||||
},
|
||||
.keys = {
|
||||
.nhoff = 0,
|
||||
.thoff = sizeof(struct ipv6hdr),
|
||||
.addr_proto = ETH_P_IPV6,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IPV6),
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "802.1q-ipv4",
|
||||
.pkt.svlan_ipv4 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_8021Q),
|
||||
.vlan_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
.iph.ihl = 5,
|
||||
.iph.protocol = IPPROTO_TCP,
|
||||
.iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.doff = 5,
|
||||
},
|
||||
.keys = {
|
||||
.nhoff = VLAN_HLEN,
|
||||
.thoff = VLAN_HLEN + sizeof(struct iphdr),
|
||||
.addr_proto = ETH_P_IP,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IP),
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "802.1ad-ipv6",
|
||||
.pkt.dvlan_ipv6 = {
|
||||
.eth.h_proto = __bpf_constant_htons(ETH_P_8021AD),
|
||||
.vlan_proto = __bpf_constant_htons(ETH_P_8021Q),
|
||||
.vlan_proto2 = __bpf_constant_htons(ETH_P_IPV6),
|
||||
.iph.nexthdr = IPPROTO_TCP,
|
||||
.iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
|
||||
.tcp.doff = 5,
|
||||
},
|
||||
.keys = {
|
||||
.nhoff = VLAN_HLEN * 2,
|
||||
.thoff = VLAN_HLEN * 2 + sizeof(struct ipv6hdr),
|
||||
.addr_proto = ETH_P_IPV6,
|
||||
.ip_proto = IPPROTO_TCP,
|
||||
.n_proto = __bpf_constant_htons(ETH_P_IPV6),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
void test_flow_dissector(void)
|
||||
{
|
||||
struct bpf_flow_keys flow_keys;
|
||||
struct bpf_object *obj;
|
||||
__u32 duration, retval;
|
||||
int err, prog_fd;
|
||||
__u32 size;
|
||||
int i, err, prog_fd;
|
||||
|
||||
err = bpf_flow_load(&obj, "./bpf_flow.o", "flow_dissector",
|
||||
"jmp_table", &prog_fd);
|
||||
@@ -106,35 +152,24 @@ void test_flow_dissector(void)
|
||||
return;
|
||||
}
|
||||
|
||||
err = bpf_prog_test_run(prog_fd, 10, &pkt_v4, sizeof(pkt_v4),
|
||||
&flow_keys, &size, &retval, &duration);
|
||||
CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv4",
|
||||
"err %d errno %d retval %d duration %d size %u/%lu\n",
|
||||
err, errno, retval, duration, size, sizeof(flow_keys));
|
||||
CHECK_FLOW_KEYS("ipv4_flow_keys", flow_keys, pkt_v4_flow_keys);
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
struct bpf_flow_keys flow_keys;
|
||||
struct bpf_prog_test_run_attr tattr = {
|
||||
.prog_fd = prog_fd,
|
||||
.data_in = &tests[i].pkt,
|
||||
.data_size_in = sizeof(tests[i].pkt),
|
||||
.data_out = &flow_keys,
|
||||
};
|
||||
|
||||
err = bpf_prog_test_run(prog_fd, 10, &pkt_v6, sizeof(pkt_v6),
|
||||
&flow_keys, &size, &retval, &duration);
|
||||
CHECK(size != sizeof(flow_keys) || err || retval != 1, "ipv6",
|
||||
"err %d errno %d retval %d duration %d size %u/%lu\n",
|
||||
err, errno, retval, duration, size, sizeof(flow_keys));
|
||||
CHECK_FLOW_KEYS("ipv6_flow_keys", flow_keys, pkt_v6_flow_keys);
|
||||
|
||||
err = bpf_prog_test_run(prog_fd, 10, &pkt_vlan_v4, sizeof(pkt_vlan_v4),
|
||||
&flow_keys, &size, &retval, &duration);
|
||||
CHECK(size != sizeof(flow_keys) || err || retval != 1, "vlan_ipv4",
|
||||
"err %d errno %d retval %d duration %d size %u/%lu\n",
|
||||
err, errno, retval, duration, size, sizeof(flow_keys));
|
||||
CHECK_FLOW_KEYS("vlan_ipv4_flow_keys", flow_keys,
|
||||
pkt_vlan_v4_flow_keys);
|
||||
|
||||
err = bpf_prog_test_run(prog_fd, 10, &pkt_vlan_v6, sizeof(pkt_vlan_v6),
|
||||
&flow_keys, &size, &retval, &duration);
|
||||
CHECK(size != sizeof(flow_keys) || err || retval != 1, "vlan_ipv6",
|
||||
"err %d errno %d retval %d duration %d size %u/%lu\n",
|
||||
err, errno, retval, duration, size, sizeof(flow_keys));
|
||||
CHECK_FLOW_KEYS("vlan_ipv6_flow_keys", flow_keys,
|
||||
pkt_vlan_v6_flow_keys);
|
||||
err = bpf_prog_test_run_xattr(&tattr);
|
||||
CHECK_ATTR(tattr.data_size_out != sizeof(flow_keys) ||
|
||||
err || tattr.retval != 1,
|
||||
tests[i].name,
|
||||
"err %d errno %d retval %d duration %d size %u/%lu\n",
|
||||
err, errno, tattr.retval, tattr.duration,
|
||||
tattr.data_size_out, sizeof(flow_keys));
|
||||
CHECK_FLOW_KEYS(tests[i].name, flow_keys, tests[i].keys);
|
||||
}
|
||||
|
||||
bpf_object__close(obj);
|
||||
}
|
||||
|
70
tools/testing/selftests/bpf/progs/test_sysctl_prog.c
Normal file
70
tools/testing/selftests/bpf/progs/test_sysctl_prog.c
Normal file
@@ -0,0 +1,70 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2019 Facebook
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/bpf.h>
|
||||
|
||||
#include "bpf_helpers.h"
|
||||
#include "bpf_util.h"
|
||||
|
||||
/* Max supported length of a string with unsigned long in base 10 (pow2 - 1). */
|
||||
#define MAX_ULONG_STR_LEN 0xF
|
||||
|
||||
/* Max supported length of sysctl value string (pow2). */
|
||||
#define MAX_VALUE_STR_LEN 0x40
|
||||
|
||||
static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx)
|
||||
{
|
||||
char tcp_mem_name[] = "net/ipv4/tcp_mem";
|
||||
unsigned char i;
|
||||
char name[64];
|
||||
int ret;
|
||||
|
||||
memset(name, 0, sizeof(name));
|
||||
ret = bpf_sysctl_get_name(ctx, name, sizeof(name), 0);
|
||||
if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
|
||||
return 0;
|
||||
|
||||
#pragma clang loop unroll(full)
|
||||
for (i = 0; i < sizeof(tcp_mem_name); ++i)
|
||||
if (name[i] != tcp_mem_name[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SEC("cgroup/sysctl")
|
||||
int sysctl_tcp_mem(struct bpf_sysctl *ctx)
|
||||
{
|
||||
unsigned long tcp_mem[3] = {0, 0, 0};
|
||||
char value[MAX_VALUE_STR_LEN];
|
||||
unsigned char i, off = 0;
|
||||
int ret;
|
||||
|
||||
if (ctx->write)
|
||||
return 0;
|
||||
|
||||
if (!is_tcp_mem(ctx))
|
||||
return 0;
|
||||
|
||||
ret = bpf_sysctl_get_current_value(ctx, value, MAX_VALUE_STR_LEN);
|
||||
if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
|
||||
return 0;
|
||||
|
||||
#pragma clang loop unroll(full)
|
||||
for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
|
||||
ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
|
||||
tcp_mem + i);
|
||||
if (ret <= 0 || ret > MAX_ULONG_STR_LEN)
|
||||
return 0;
|
||||
off += ret & MAX_ULONG_STR_LEN;
|
||||
}
|
||||
|
||||
|
||||
return tcp_mem[0] < tcp_mem[1] && tcp_mem[1] < tcp_mem[2];
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
@@ -157,7 +157,7 @@ static __always_inline int encap_ipv4(struct __sk_buff *skb, __u8 encap_proto,
|
||||
bpf_ntohs(h_outer.ip.tot_len));
|
||||
h_outer.ip.protocol = encap_proto;
|
||||
|
||||
set_ipv4_csum(&h_outer.ip);
|
||||
set_ipv4_csum((void *)&h_outer.ip);
|
||||
|
||||
/* store new outer network header */
|
||||
if (bpf_skb_store_bytes(skb, ETH_HLEN, &h_outer, olen,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
@@ -9,7 +10,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#include "bpf_helpers.h"
|
||||
#include "bpf_endian.h"
|
||||
#include "test_tcpbpf.h"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
@@ -9,7 +10,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#include "bpf_helpers.h"
|
||||
#include "bpf_endian.h"
|
||||
#include "test_tcpnotify.h"
|
||||
|
@@ -6642,6 +6642,51 @@ const struct btf_dedup_test dedup_tests[] = {
|
||||
.dont_resolve_fwds = false,
|
||||
},
|
||||
},
|
||||
{
|
||||
.descr = "dedup: datasec and vars pass-through",
|
||||
.input = {
|
||||
.raw_types = {
|
||||
/* int */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
/* static int t */
|
||||
BTF_VAR_ENC(NAME_NTH(2), 1, 0), /* [2] */
|
||||
/* .bss section */ /* [3] */
|
||||
BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
|
||||
BTF_VAR_SECINFO_ENC(2, 0, 4),
|
||||
/* int, referenced from [5] */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [4] */
|
||||
/* another static int t */
|
||||
BTF_VAR_ENC(NAME_NTH(2), 4, 0), /* [5] */
|
||||
/* another .bss section */ /* [6] */
|
||||
BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
|
||||
BTF_VAR_SECINFO_ENC(5, 0, 4),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0.bss\0t"),
|
||||
},
|
||||
.expect = {
|
||||
.raw_types = {
|
||||
/* int */
|
||||
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
|
||||
/* static int t */
|
||||
BTF_VAR_ENC(NAME_NTH(2), 1, 0), /* [2] */
|
||||
/* .bss section */ /* [3] */
|
||||
BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
|
||||
BTF_VAR_SECINFO_ENC(2, 0, 4),
|
||||
/* another static int t */
|
||||
BTF_VAR_ENC(NAME_NTH(2), 1, 0), /* [4] */
|
||||
/* another .bss section */ /* [5] */
|
||||
BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
|
||||
BTF_VAR_SECINFO_ENC(4, 0, 4),
|
||||
BTF_END_RAW,
|
||||
},
|
||||
BTF_STR_SEC("\0.bss\0t"),
|
||||
},
|
||||
.opts = {
|
||||
.dont_resolve_fwds = false,
|
||||
.dedup_table_size = 1
|
||||
},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
@@ -6671,6 +6716,10 @@ static int btf_type_size(const struct btf_type *t)
|
||||
return base_size + vlen * sizeof(struct btf_member);
|
||||
case BTF_KIND_FUNC_PROTO:
|
||||
return base_size + vlen * sizeof(struct btf_param);
|
||||
case BTF_KIND_VAR:
|
||||
return base_size + sizeof(struct btf_var);
|
||||
case BTF_KIND_DATASEC:
|
||||
return base_size + vlen * sizeof(struct btf_var_secinfo);
|
||||
default:
|
||||
fprintf(stderr, "Unsupported BTF_KIND:%u\n", kind);
|
||||
return -EINVAL;
|
||||
|
@@ -129,6 +129,24 @@ setup()
|
||||
ip link set veth7 netns ${NS2}
|
||||
ip link set veth8 netns ${NS3}
|
||||
|
||||
if [ ! -z "${VRF}" ] ; then
|
||||
ip -netns ${NS1} link add red type vrf table 1001
|
||||
ip -netns ${NS1} link set red up
|
||||
ip -netns ${NS1} route add table 1001 unreachable default metric 8192
|
||||
ip -netns ${NS1} -6 route add table 1001 unreachable default metric 8192
|
||||
ip -netns ${NS1} link set veth1 vrf red
|
||||
ip -netns ${NS1} link set veth5 vrf red
|
||||
|
||||
ip -netns ${NS2} link add red type vrf table 1001
|
||||
ip -netns ${NS2} link set red up
|
||||
ip -netns ${NS2} route add table 1001 unreachable default metric 8192
|
||||
ip -netns ${NS2} -6 route add table 1001 unreachable default metric 8192
|
||||
ip -netns ${NS2} link set veth2 vrf red
|
||||
ip -netns ${NS2} link set veth3 vrf red
|
||||
ip -netns ${NS2} link set veth6 vrf red
|
||||
ip -netns ${NS2} link set veth7 vrf red
|
||||
fi
|
||||
|
||||
# configure addesses: the top route (1-2-3-4)
|
||||
ip -netns ${NS1} addr add ${IPv4_1}/24 dev veth1
|
||||
ip -netns ${NS2} addr add ${IPv4_2}/24 dev veth2
|
||||
@@ -163,29 +181,29 @@ setup()
|
||||
|
||||
# NS1
|
||||
# top route
|
||||
ip -netns ${NS1} route add ${IPv4_2}/32 dev veth1
|
||||
ip -netns ${NS1} route add default dev veth1 via ${IPv4_2} # go top by default
|
||||
ip -netns ${NS1} -6 route add ${IPv6_2}/128 dev veth1
|
||||
ip -netns ${NS1} -6 route add default dev veth1 via ${IPv6_2} # go top by default
|
||||
ip -netns ${NS1} route add ${IPv4_2}/32 dev veth1 ${VRF}
|
||||
ip -netns ${NS1} route add default dev veth1 via ${IPv4_2} ${VRF} # go top by default
|
||||
ip -netns ${NS1} -6 route add ${IPv6_2}/128 dev veth1 ${VRF}
|
||||
ip -netns ${NS1} -6 route add default dev veth1 via ${IPv6_2} ${VRF} # go top by default
|
||||
# bottom route
|
||||
ip -netns ${NS1} route add ${IPv4_6}/32 dev veth5
|
||||
ip -netns ${NS1} route add ${IPv4_7}/32 dev veth5 via ${IPv4_6}
|
||||
ip -netns ${NS1} route add ${IPv4_8}/32 dev veth5 via ${IPv4_6}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_6}/128 dev veth5
|
||||
ip -netns ${NS1} -6 route add ${IPv6_7}/128 dev veth5 via ${IPv6_6}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_8}/128 dev veth5 via ${IPv6_6}
|
||||
ip -netns ${NS1} route add ${IPv4_6}/32 dev veth5 ${VRF}
|
||||
ip -netns ${NS1} route add ${IPv4_7}/32 dev veth5 via ${IPv4_6} ${VRF}
|
||||
ip -netns ${NS1} route add ${IPv4_8}/32 dev veth5 via ${IPv4_6} ${VRF}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_6}/128 dev veth5 ${VRF}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_7}/128 dev veth5 via ${IPv6_6} ${VRF}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_8}/128 dev veth5 via ${IPv6_6} ${VRF}
|
||||
|
||||
# NS2
|
||||
# top route
|
||||
ip -netns ${NS2} route add ${IPv4_1}/32 dev veth2
|
||||
ip -netns ${NS2} route add ${IPv4_4}/32 dev veth3
|
||||
ip -netns ${NS2} -6 route add ${IPv6_1}/128 dev veth2
|
||||
ip -netns ${NS2} -6 route add ${IPv6_4}/128 dev veth3
|
||||
ip -netns ${NS2} route add ${IPv4_1}/32 dev veth2 ${VRF}
|
||||
ip -netns ${NS2} route add ${IPv4_4}/32 dev veth3 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_1}/128 dev veth2 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_4}/128 dev veth3 ${VRF}
|
||||
# bottom route
|
||||
ip -netns ${NS2} route add ${IPv4_5}/32 dev veth6
|
||||
ip -netns ${NS2} route add ${IPv4_8}/32 dev veth7
|
||||
ip -netns ${NS2} -6 route add ${IPv6_5}/128 dev veth6
|
||||
ip -netns ${NS2} -6 route add ${IPv6_8}/128 dev veth7
|
||||
ip -netns ${NS2} route add ${IPv4_5}/32 dev veth6 ${VRF}
|
||||
ip -netns ${NS2} route add ${IPv4_8}/32 dev veth7 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_5}/128 dev veth6 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_8}/128 dev veth7 ${VRF}
|
||||
|
||||
# NS3
|
||||
# top route
|
||||
@@ -207,16 +225,16 @@ setup()
|
||||
ip -netns ${NS3} tunnel add gre_dev mode gre remote ${IPv4_1} local ${IPv4_GRE} ttl 255
|
||||
ip -netns ${NS3} link set gre_dev up
|
||||
ip -netns ${NS3} addr add ${IPv4_GRE} dev gre_dev
|
||||
ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6}
|
||||
ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8}
|
||||
ip -netns ${NS1} route add ${IPv4_GRE}/32 dev veth5 via ${IPv4_6} ${VRF}
|
||||
ip -netns ${NS2} route add ${IPv4_GRE}/32 dev veth7 via ${IPv4_8} ${VRF}
|
||||
|
||||
|
||||
# configure IPv6 GRE device in NS3, and a route to it via the "bottom" route
|
||||
ip -netns ${NS3} -6 tunnel add name gre6_dev mode ip6gre remote ${IPv6_1} local ${IPv6_GRE} ttl 255
|
||||
ip -netns ${NS3} link set gre6_dev up
|
||||
ip -netns ${NS3} -6 addr add ${IPv6_GRE} nodad dev gre6_dev
|
||||
ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF}
|
||||
|
||||
# rp_filter gets confused by what these tests are doing, so disable it
|
||||
ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
||||
@@ -244,18 +262,18 @@ trap cleanup EXIT
|
||||
|
||||
remove_routes_to_gredev()
|
||||
{
|
||||
ip -netns ${NS1} route del ${IPv4_GRE} dev veth5
|
||||
ip -netns ${NS2} route del ${IPv4_GRE} dev veth7
|
||||
ip -netns ${NS1} -6 route del ${IPv6_GRE}/128 dev veth5
|
||||
ip -netns ${NS2} -6 route del ${IPv6_GRE}/128 dev veth7
|
||||
ip -netns ${NS1} route del ${IPv4_GRE} dev veth5 ${VRF}
|
||||
ip -netns ${NS2} route del ${IPv4_GRE} dev veth7 ${VRF}
|
||||
ip -netns ${NS1} -6 route del ${IPv6_GRE}/128 dev veth5 ${VRF}
|
||||
ip -netns ${NS2} -6 route del ${IPv6_GRE}/128 dev veth7 ${VRF}
|
||||
}
|
||||
|
||||
add_unreachable_routes_to_gredev()
|
||||
{
|
||||
ip -netns ${NS1} route add unreachable ${IPv4_GRE}/32
|
||||
ip -netns ${NS2} route add unreachable ${IPv4_GRE}/32
|
||||
ip -netns ${NS1} -6 route add unreachable ${IPv6_GRE}/128
|
||||
ip -netns ${NS2} -6 route add unreachable ${IPv6_GRE}/128
|
||||
ip -netns ${NS1} route add unreachable ${IPv4_GRE}/32 ${VRF}
|
||||
ip -netns ${NS2} route add unreachable ${IPv4_GRE}/32 ${VRF}
|
||||
ip -netns ${NS1} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
|
||||
ip -netns ${NS2} -6 route add unreachable ${IPv6_GRE}/128 ${VRF}
|
||||
}
|
||||
|
||||
test_ping()
|
||||
@@ -265,10 +283,10 @@ test_ping()
|
||||
local RET=0
|
||||
|
||||
if [ "${PROTO}" == "IPv4" ] ; then
|
||||
ip netns exec ${NS1} ping -c 1 -W 1 -I ${IPv4_SRC} ${IPv4_DST} 2>&1 > /dev/null
|
||||
ip netns exec ${NS1} ping -c 1 -W 1 -I veth1 ${IPv4_DST} 2>&1 > /dev/null
|
||||
RET=$?
|
||||
elif [ "${PROTO}" == "IPv6" ] ; then
|
||||
ip netns exec ${NS1} ping6 -c 1 -W 6 -I ${IPv6_SRC} ${IPv6_DST} 2>&1 > /dev/null
|
||||
ip netns exec ${NS1} ping6 -c 1 -W 6 -I veth1 ${IPv6_DST} 2>&1 > /dev/null
|
||||
RET=$?
|
||||
else
|
||||
echo " test_ping: unknown PROTO: ${PROTO}"
|
||||
@@ -328,7 +346,7 @@ test_gso()
|
||||
test_egress()
|
||||
{
|
||||
local readonly ENCAP=$1
|
||||
echo "starting egress ${ENCAP} encap test"
|
||||
echo "starting egress ${ENCAP} encap test ${VRF}"
|
||||
setup
|
||||
|
||||
# by default, pings work
|
||||
@@ -336,26 +354,35 @@ test_egress()
|
||||
test_ping IPv6 0
|
||||
|
||||
# remove NS2->DST routes, ping fails
|
||||
ip -netns ${NS2} route del ${IPv4_DST}/32 dev veth3
|
||||
ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3
|
||||
ip -netns ${NS2} route del ${IPv4_DST}/32 dev veth3 ${VRF}
|
||||
ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
|
||||
test_ping IPv4 1
|
||||
test_ping IPv6 1
|
||||
|
||||
# install replacement routes (LWT/eBPF), pings succeed
|
||||
if [ "${ENCAP}" == "IPv4" ] ; then
|
||||
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj test_lwt_ip_encap.o sec encap_gre dev veth1
|
||||
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj test_lwt_ip_encap.o sec encap_gre dev veth1
|
||||
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
|
||||
test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
|
||||
test_lwt_ip_encap.o sec encap_gre dev veth1 ${VRF}
|
||||
elif [ "${ENCAP}" == "IPv6" ] ; then
|
||||
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj test_lwt_ip_encap.o sec encap_gre6 dev veth1
|
||||
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj test_lwt_ip_encap.o sec encap_gre6 dev veth1
|
||||
ip -netns ${NS1} route add ${IPv4_DST} encap bpf xmit obj \
|
||||
test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
|
||||
ip -netns ${NS1} -6 route add ${IPv6_DST} encap bpf xmit obj \
|
||||
test_lwt_ip_encap.o sec encap_gre6 dev veth1 ${VRF}
|
||||
else
|
||||
echo " unknown encap ${ENCAP}"
|
||||
TEST_STATUS=1
|
||||
fi
|
||||
test_ping IPv4 0
|
||||
test_ping IPv6 0
|
||||
test_gso IPv4
|
||||
test_gso IPv6
|
||||
|
||||
# skip GSO tests with VRF: VRF routing needs properly assigned
|
||||
# source IP/device, which is easy to do with ping and hard with dd/nc.
|
||||
if [ -z "${VRF}" ] ; then
|
||||
test_gso IPv4
|
||||
test_gso IPv6
|
||||
fi
|
||||
|
||||
# a negative test: remove routes to GRE devices: ping fails
|
||||
remove_routes_to_gredev
|
||||
@@ -374,7 +401,7 @@ test_egress()
|
||||
test_ingress()
|
||||
{
|
||||
local readonly ENCAP=$1
|
||||
echo "starting ingress ${ENCAP} encap test"
|
||||
echo "starting ingress ${ENCAP} encap test ${VRF}"
|
||||
setup
|
||||
|
||||
# need to wait a bit for IPv6 to autoconf, otherwise
|
||||
@@ -385,18 +412,22 @@ test_ingress()
|
||||
test_ping IPv6 0
|
||||
|
||||
# remove NS2->DST routes, pings fail
|
||||
ip -netns ${NS2} route del ${IPv4_DST}/32 dev veth3
|
||||
ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3
|
||||
ip -netns ${NS2} route del ${IPv4_DST}/32 dev veth3 ${VRF}
|
||||
ip -netns ${NS2} -6 route del ${IPv6_DST}/128 dev veth3 ${VRF}
|
||||
test_ping IPv4 1
|
||||
test_ping IPv6 1
|
||||
|
||||
# install replacement routes (LWT/eBPF), pings succeed
|
||||
if [ "${ENCAP}" == "IPv4" ] ; then
|
||||
ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj test_lwt_ip_encap.o sec encap_gre dev veth2
|
||||
ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj test_lwt_ip_encap.o sec encap_gre dev veth2
|
||||
ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
|
||||
test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
|
||||
test_lwt_ip_encap.o sec encap_gre dev veth2 ${VRF}
|
||||
elif [ "${ENCAP}" == "IPv6" ] ; then
|
||||
ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj test_lwt_ip_encap.o sec encap_gre6 dev veth2
|
||||
ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj test_lwt_ip_encap.o sec encap_gre6 dev veth2
|
||||
ip -netns ${NS2} route add ${IPv4_DST} encap bpf in obj \
|
||||
test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
|
||||
ip -netns ${NS2} -6 route add ${IPv6_DST} encap bpf in obj \
|
||||
test_lwt_ip_encap.o sec encap_gre6 dev veth2 ${VRF}
|
||||
else
|
||||
echo "FAIL: unknown encap ${ENCAP}"
|
||||
TEST_STATUS=1
|
||||
@@ -418,6 +449,13 @@ test_ingress()
|
||||
process_test_results
|
||||
}
|
||||
|
||||
VRF=""
|
||||
test_egress IPv4
|
||||
test_egress IPv6
|
||||
test_ingress IPv4
|
||||
test_ingress IPv6
|
||||
|
||||
VRF="vrf red"
|
||||
test_egress IPv4
|
||||
test_egress IPv6
|
||||
test_ingress IPv4
|
||||
|
@@ -119,6 +119,11 @@ static struct sec_name_test tests[] = {
|
||||
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
|
||||
{0, BPF_CGROUP_UDP6_SENDMSG},
|
||||
},
|
||||
{
|
||||
"cgroup/sysctl",
|
||||
{0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
|
||||
{0, BPF_CGROUP_SYSCTL},
|
||||
},
|
||||
};
|
||||
|
||||
static int test_prog_type_by_name(const struct sec_name_test *test)
|
||||
|
1567
tools/testing/selftests/bpf/test_sysctl.c
Normal file
1567
tools/testing/selftests/bpf/test_sysctl.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -52,7 +52,7 @@
|
||||
#define MAX_INSNS BPF_MAXINSNS
|
||||
#define MAX_TEST_INSNS 1000000
|
||||
#define MAX_FIXUPS 8
|
||||
#define MAX_NR_MAPS 16
|
||||
#define MAX_NR_MAPS 17
|
||||
#define MAX_TEST_RUNS 8
|
||||
#define POINTER_VALUE 0xcafe4all
|
||||
#define TEST_DATA_LEN 64
|
||||
@@ -208,6 +208,76 @@ static void bpf_fill_rand_ld_dw(struct bpf_test *self)
|
||||
self->retval = (uint32_t)res;
|
||||
}
|
||||
|
||||
/* test the sequence of 1k jumps */
|
||||
static void bpf_fill_scale1(struct bpf_test *self)
|
||||
{
|
||||
struct bpf_insn *insn = self->fill_insns;
|
||||
int i = 0, k = 0;
|
||||
|
||||
insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1);
|
||||
/* test to check that the sequence of 1024 jumps is acceptable */
|
||||
while (k++ < 1024) {
|
||||
insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
|
||||
BPF_FUNC_get_prandom_u32);
|
||||
insn[i++] = BPF_JMP_IMM(BPF_JGT, BPF_REG_0, bpf_semi_rand_get(), 2);
|
||||
insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_10);
|
||||
insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
|
||||
-8 * (k % 64 + 1));
|
||||
}
|
||||
/* every jump adds 1024 steps to insn_processed, so to stay exactly
|
||||
* within 1m limit add MAX_TEST_INSNS - 1025 MOVs and 1 EXIT
|
||||
*/
|
||||
while (i < MAX_TEST_INSNS - 1025)
|
||||
insn[i++] = BPF_ALU32_IMM(BPF_MOV, BPF_REG_0, 42);
|
||||
insn[i] = BPF_EXIT_INSN();
|
||||
self->prog_len = i + 1;
|
||||
self->retval = 42;
|
||||
}
|
||||
|
||||
/* test the sequence of 1k jumps in inner most function (function depth 8)*/
|
||||
static void bpf_fill_scale2(struct bpf_test *self)
|
||||
{
|
||||
struct bpf_insn *insn = self->fill_insns;
|
||||
int i = 0, k = 0;
|
||||
|
||||
#define FUNC_NEST 7
|
||||
for (k = 0; k < FUNC_NEST; k++) {
|
||||
insn[i++] = BPF_CALL_REL(1);
|
||||
insn[i++] = BPF_EXIT_INSN();
|
||||
}
|
||||
insn[i++] = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1);
|
||||
/* test to check that the sequence of 1024 jumps is acceptable */
|
||||
while (k++ < 1024) {
|
||||
insn[i++] = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
|
||||
BPF_FUNC_get_prandom_u32);
|
||||
insn[i++] = BPF_JMP_IMM(BPF_JGT, BPF_REG_0, bpf_semi_rand_get(), 2);
|
||||
insn[i++] = BPF_MOV64_REG(BPF_REG_1, BPF_REG_10);
|
||||
insn[i++] = BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_6,
|
||||
-8 * (k % (64 - 4 * FUNC_NEST) + 1));
|
||||
}
|
||||
/* every jump adds 1024 steps to insn_processed, so to stay exactly
|
||||
* within 1m limit add MAX_TEST_INSNS - 1025 MOVs and 1 EXIT
|
||||
*/
|
||||
while (i < MAX_TEST_INSNS - 1025)
|
||||
insn[i++] = BPF_ALU32_IMM(BPF_MOV, BPF_REG_0, 42);
|
||||
insn[i] = BPF_EXIT_INSN();
|
||||
self->prog_len = i + 1;
|
||||
self->retval = 42;
|
||||
}
|
||||
|
||||
static void bpf_fill_scale(struct bpf_test *self)
|
||||
{
|
||||
switch (self->retval) {
|
||||
case 1:
|
||||
return bpf_fill_scale1(self);
|
||||
case 2:
|
||||
return bpf_fill_scale2(self);
|
||||
default:
|
||||
self->prog_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* BPF_SK_LOOKUP contains 13 instructions, if you need to fix up maps */
|
||||
#define BPF_SK_LOOKUP(func) \
|
||||
/* struct bpf_sock_tuple tuple = {} */ \
|
||||
|
160
tools/testing/selftests/bpf/verifier/int_ptr.c
Normal file
160
tools/testing/selftests/bpf/verifier/int_ptr.c
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"ARG_PTR_TO_LONG uninitialized",
|
||||
.insns = {
|
||||
/* bpf_strtoul arg1 (buf) */
|
||||
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0x00303036),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul arg2 (buf_len) */
|
||||
BPF_MOV64_IMM(BPF_REG_2, 4),
|
||||
|
||||
/* bpf_strtoul arg3 (flags) */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
|
||||
/* bpf_strtoul arg4 (res) */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_strtoul),
|
||||
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = REJECT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
.errstr = "invalid indirect read from stack off -16+0 size 8",
|
||||
},
|
||||
{
|
||||
"ARG_PTR_TO_LONG half-uninitialized",
|
||||
.insns = {
|
||||
/* bpf_strtoul arg1 (buf) */
|
||||
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0x00303036),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul arg2 (buf_len) */
|
||||
BPF_MOV64_IMM(BPF_REG_2, 4),
|
||||
|
||||
/* bpf_strtoul arg3 (flags) */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
|
||||
/* bpf_strtoul arg4 (res) */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
|
||||
BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_strtoul),
|
||||
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = REJECT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
.errstr = "invalid indirect read from stack off -16+4 size 8",
|
||||
},
|
||||
{
|
||||
"ARG_PTR_TO_LONG misaligned",
|
||||
.insns = {
|
||||
/* bpf_strtoul arg1 (buf) */
|
||||
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0x00303036),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul arg2 (buf_len) */
|
||||
BPF_MOV64_IMM(BPF_REG_2, 4),
|
||||
|
||||
/* bpf_strtoul arg3 (flags) */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
|
||||
/* bpf_strtoul arg4 (res) */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -12),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 4),
|
||||
BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_strtoul),
|
||||
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = REJECT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
.errstr = "misaligned stack access off (0x0; 0x0)+-20+0 size 8",
|
||||
},
|
||||
{
|
||||
"ARG_PTR_TO_LONG size < sizeof(long)",
|
||||
.insns = {
|
||||
/* bpf_strtoul arg1 (buf) */
|
||||
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0x00303036),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul arg2 (buf_len) */
|
||||
BPF_MOV64_IMM(BPF_REG_2, 4),
|
||||
|
||||
/* bpf_strtoul arg3 (flags) */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
|
||||
/* bpf_strtoul arg4 (res) */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, 12),
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
|
||||
BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_strtoul),
|
||||
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = REJECT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
.errstr = "invalid stack type R4 off=-4 access_size=8",
|
||||
},
|
||||
{
|
||||
"ARG_PTR_TO_LONG initialized",
|
||||
.insns = {
|
||||
/* bpf_strtoul arg1 (buf) */
|
||||
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0x00303036),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul arg2 (buf_len) */
|
||||
BPF_MOV64_IMM(BPF_REG_2, 4),
|
||||
|
||||
/* bpf_strtoul arg3 (flags) */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
|
||||
/* bpf_strtoul arg4 (res) */
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
|
||||
BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
|
||||
|
||||
/* bpf_strtoul() */
|
||||
BPF_EMIT_CALL(BPF_FUNC_strtoul),
|
||||
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = ACCEPT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
|
||||
},
|
18
tools/testing/selftests/bpf/verifier/scale.c
Normal file
18
tools/testing/selftests/bpf/verifier/scale.c
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"scale: scale test 1",
|
||||
.insns = { },
|
||||
.data = { },
|
||||
.fill_helper = bpf_fill_scale,
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
.result = ACCEPT,
|
||||
.retval = 1,
|
||||
},
|
||||
{
|
||||
"scale: scale test 2",
|
||||
.insns = { },
|
||||
.data = { },
|
||||
.fill_helper = bpf_fill_scale,
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
.result = ACCEPT,
|
||||
.retval = 2,
|
||||
},
|
Reference in New Issue
Block a user