Skip to content

Commit 05c74e5

Browse files
borkmanndavem330
authored andcommitted
bpf: add bpf_skb_load_bytes helper
When hacking tc programs with eBPF, one of the issues that come up from time to time is to load addresses from headers. In eBPF as in classic BPF, we have BPF_LD | BPF_ABS | BPF_{B,H,W} instructions that extract a byte, half-word or word out of the skb data though helpers such as bpf_load_pointer() (interpreter case). F.e. extracting a whole IPv6 address could possibly look like ... union v6addr { struct { __u32 p1; __u32 p2; __u32 p3; __u32 p4; }; __u8 addr[16]; }; [...] a.p1 = htonl(load_word(skb, off)); a.p2 = htonl(load_word(skb, off + 4)); a.p3 = htonl(load_word(skb, off + 8)); a.p4 = htonl(load_word(skb, off + 12)); [...] /* access to a.addr[...] */ This work adds a complementary helper bpf_skb_load_bytes() (we also have bpf_skb_store_bytes()) as an alternative where the same call would look like from an eBPF program: ret = bpf_skb_load_bytes(skb, off, addr, sizeof(addr)); Same verifier restrictions apply as in ffeedaf ("bpf: introduce current->pid, tgid, uid, gid, comm accessors") case, where stack memory access needs to be statically verified and thus guaranteed to be initialized in first use (otherwise verifier cannot tell whether a subsequent access to it is valid or not as it's runtime dependent). Signed-off-by: Daniel Borkmann <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 59ce967 commit 05c74e5

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

Diff for: include/uapi/linux/bpf.h

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ enum bpf_func_id {
269269
* Return: 0 on success
270270
*/
271271
BPF_FUNC_perf_event_output,
272+
BPF_FUNC_skb_load_bytes,
272273
__BPF_FUNC_MAX_ID,
273274
};
274275

Diff for: net/core/filter.c

+34-1
Original file line numberDiff line numberDiff line change
@@ -1245,14 +1245,15 @@ int sk_attach_bpf(u32 ufd, struct sock *sk)
12451245
}
12461246

12471247
#define BPF_RECOMPUTE_CSUM(flags) ((flags) & 1)
1248+
#define BPF_LDST_LEN 16U
12481249

12491250
static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
12501251
{
12511252
struct sk_buff *skb = (struct sk_buff *) (long) r1;
12521253
int offset = (int) r2;
12531254
void *from = (void *) (long) r3;
12541255
unsigned int len = (unsigned int) r4;
1255-
char buf[16];
1256+
char buf[BPF_LDST_LEN];
12561257
void *ptr;
12571258

12581259
/* bpf verifier guarantees that:
@@ -1299,6 +1300,36 @@ const struct bpf_func_proto bpf_skb_store_bytes_proto = {
12991300
.arg5_type = ARG_ANYTHING,
13001301
};
13011302

1303+
static u64 bpf_skb_load_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
1304+
{
1305+
const struct sk_buff *skb = (const struct sk_buff *)(unsigned long) r1;
1306+
int offset = (int) r2;
1307+
void *to = (void *)(unsigned long) r3;
1308+
unsigned int len = (unsigned int) r4;
1309+
void *ptr;
1310+
1311+
if (unlikely((u32) offset > 0xffff || len > BPF_LDST_LEN))
1312+
return -EFAULT;
1313+
1314+
ptr = skb_header_pointer(skb, offset, len, to);
1315+
if (unlikely(!ptr))
1316+
return -EFAULT;
1317+
if (ptr != to)
1318+
memcpy(to, ptr, len);
1319+
1320+
return 0;
1321+
}
1322+
1323+
const struct bpf_func_proto bpf_skb_load_bytes_proto = {
1324+
.func = bpf_skb_load_bytes,
1325+
.gpl_only = false,
1326+
.ret_type = RET_INTEGER,
1327+
.arg1_type = ARG_PTR_TO_CTX,
1328+
.arg2_type = ARG_ANYTHING,
1329+
.arg3_type = ARG_PTR_TO_STACK,
1330+
.arg4_type = ARG_CONST_STACK_SIZE,
1331+
};
1332+
13021333
#define BPF_HEADER_FIELD_SIZE(flags) ((flags) & 0x0f)
13031334
#define BPF_IS_PSEUDO_HEADER(flags) ((flags) & 0x10)
13041335

@@ -1654,6 +1685,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
16541685
switch (func_id) {
16551686
case BPF_FUNC_skb_store_bytes:
16561687
return &bpf_skb_store_bytes_proto;
1688+
case BPF_FUNC_skb_load_bytes:
1689+
return &bpf_skb_load_bytes_proto;
16571690
case BPF_FUNC_l3_csum_replace:
16581691
return &bpf_l3_csum_replace_proto;
16591692
case BPF_FUNC_l4_csum_replace:

0 commit comments

Comments
 (0)