Skip to content

Commit f865417

Browse files
jsitnickiKernel Patches Daemon
authored andcommitted
selftests/bpf: Cover skb metadata access after bpf_skb_adjust_room
Add a test to verify that skb metadata remains accessible after calling bpf_skb_adjust_room(), which modifies the packet headroom and can trigger head reallocation. The helper expects an Ethernet frame carrying an IP packet so switch test packet identification by source MAC address since we can no longer rely on Ethernet proto being set to zero. Signed-off-by: Jakub Sitnicki <[email protected]>
1 parent 9fd1635 commit f865417

File tree

2 files changed

+71
-15
lines changed

2 files changed

+71
-15
lines changed

tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,10 @@ static int send_test_packet(int ifindex)
124124
int n, sock = -1;
125125
__u8 packet[sizeof(struct ethhdr) + TEST_PAYLOAD_LEN];
126126

127-
/* The ethernet header is not relevant for this test and doesn't need to
128-
* be meaningful.
129-
*/
130-
struct ethhdr eth = { 0 };
127+
/* We use the Ethernet header only to identify the test packet */
128+
struct ethhdr eth = {
129+
.h_source = { 0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF },
130+
};
131131

132132
memcpy(packet, &eth, sizeof(eth));
133133
memcpy(packet + sizeof(eth), test_payload, TEST_PAYLOAD_LEN);
@@ -160,8 +160,16 @@ static int write_test_packet(int tap_fd)
160160
__u8 packet[sizeof(struct ethhdr) + TEST_PAYLOAD_LEN];
161161
int n;
162162

163-
/* The ethernet header doesn't need to be valid for this test */
164-
memset(packet, 0, sizeof(struct ethhdr));
163+
/* The Ethernet header is mostly not relevant. We use it to identify the
164+
* test packet and some BPF helpers we exercise expect to operate on
165+
* Ethernet frames carrying IP packets. Pretend that's the case.
166+
*/
167+
struct ethhdr eth = {
168+
.h_source = { 0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF },
169+
.h_proto = htons(ETH_P_IP),
170+
};
171+
172+
memcpy(packet, &eth, sizeof(eth));
165173
memcpy(packet + sizeof(struct ethhdr), test_payload, TEST_PAYLOAD_LEN);
166174

167175
n = write(tap_fd, packet, sizeof(packet));
@@ -484,6 +492,11 @@ void test_xdp_context_tuntap(void)
484492
skel->progs.helper_skb_vlan_push_pop,
485493
NULL, /* tc prio 2 */
486494
&skel->bss->test_pass);
495+
if (test__start_subtest("helper_skb_adjust_room"))
496+
test_tuntap(skel->progs.ing_xdp,
497+
skel->progs.helper_skb_adjust_room,
498+
NULL, /* tc prio 2 */
499+
&skel->bss->test_pass);
487500

488501
test_xdp_meta__destroy(skel);
489502
}

tools/testing/selftests/bpf/progs/test_xdp_meta.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,22 @@
2020

2121
bool test_pass;
2222

23+
static const __u8 smac_want[ETH_ALEN] = {
24+
0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF,
25+
};
26+
2327
static const __u8 meta_want[META_SIZE] = {
2428
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2529
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
2630
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
2731
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
2832
};
2933

34+
static bool check_smac(const struct ethhdr *eth)
35+
{
36+
return !__builtin_memcmp(eth->h_source, smac_want, ETH_ALEN);
37+
}
38+
3039
static bool check_metadata(const char *file, int line, __u8 *meta_have)
3140
{
3241
if (!__builtin_memcmp(meta_have, meta_want, META_SIZE))
@@ -281,7 +290,7 @@ int ing_xdp_zalloc_meta(struct xdp_md *ctx)
281290
/* Drop any non-test packets */
282291
if (eth + 1 > ctx_ptr(ctx, data_end))
283292
return XDP_DROP;
284-
if (eth->h_proto != 0)
293+
if (!check_smac(eth))
285294
return XDP_DROP;
286295

287296
ret = bpf_xdp_adjust_meta(ctx, -META_SIZE);
@@ -321,9 +330,9 @@ int ing_xdp(struct xdp_md *ctx)
321330

322331
/* The Linux networking stack may send other packets on the test
323332
* interface that interfere with the test. Just drop them.
324-
* The test packets can be recognized by their ethertype of zero.
333+
* The test packets can be recognized by their source MAC address.
325334
*/
326-
if (eth->h_proto != 0)
335+
if (!check_smac(eth))
327336
return XDP_DROP;
328337

329338
__builtin_memcpy(data_meta, payload, META_SIZE);
@@ -343,7 +352,7 @@ int clone_data_meta_survives_data_write(struct __sk_buff *ctx)
343352
if (eth + 1 > ctx_ptr(ctx, data_end))
344353
goto out;
345354
/* Ignore non-test packets */
346-
if (eth->h_proto != 0)
355+
if (!check_smac(eth))
347356
goto out;
348357

349358
if (meta_have + META_SIZE > eth)
@@ -373,7 +382,7 @@ int clone_data_meta_survives_meta_write(struct __sk_buff *ctx)
373382
if (eth + 1 > ctx_ptr(ctx, data_end))
374383
goto out;
375384
/* Ignore non-test packets */
376-
if (eth->h_proto != 0)
385+
if (!check_smac(eth))
377386
goto out;
378387

379388
if (meta_have + META_SIZE > eth)
@@ -406,7 +415,7 @@ int clone_meta_dynptr_survives_data_slice_write(struct __sk_buff *ctx)
406415
if (!eth)
407416
goto out;
408417
/* Ignore non-test packets */
409-
if (eth->h_proto != 0)
418+
if (!check_smac(eth))
410419
goto out;
411420

412421
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -435,7 +444,7 @@ int clone_meta_dynptr_survives_meta_slice_write(struct __sk_buff *ctx)
435444
if (!eth)
436445
goto out;
437446
/* Ignore non-test packets */
438-
if (eth->h_proto != 0)
447+
if (!check_smac(eth))
439448
goto out;
440449

441450
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -469,7 +478,7 @@ int clone_meta_dynptr_rw_before_data_dynptr_write(struct __sk_buff *ctx)
469478
if (!eth)
470479
goto out;
471480
/* Ignore non-test packets */
472-
if (eth->h_proto != 0)
481+
if (!check_smac(eth))
473482
goto out;
474483

475484
/* Expect read-write metadata before unclone */
@@ -511,7 +520,7 @@ int clone_meta_dynptr_rw_before_meta_dynptr_write(struct __sk_buff *ctx)
511520
if (!eth)
512521
goto out;
513522
/* Ignore non-test packets */
514-
if (eth->h_proto != 0)
523+
if (!check_smac(eth))
515524
goto out;
516525

517526
/* Expect read-write metadata before unclone */
@@ -568,4 +577,38 @@ int helper_skb_vlan_push_pop(struct __sk_buff *ctx)
568577
return TC_ACT_SHOT;
569578
}
570579

580+
SEC("tc")
581+
int helper_skb_adjust_room(struct __sk_buff *ctx)
582+
{
583+
int err;
584+
585+
/* Grow a 1 byte hole after the MAC header */
586+
err = bpf_skb_adjust_room(ctx, 1, BPF_ADJ_ROOM_MAC, 0);
587+
if (err)
588+
goto out;
589+
590+
if (!check_skb_metadata(ctx))
591+
goto out;
592+
593+
/* Shrink a 1 byte hole after the MAC header */
594+
err = bpf_skb_adjust_room(ctx, -1, BPF_ADJ_ROOM_MAC, 0);
595+
if (err)
596+
goto out;
597+
598+
if (!check_skb_metadata(ctx))
599+
goto out;
600+
601+
/* Grow a 256 byte hole to trigger head reallocation */
602+
err = bpf_skb_adjust_room(ctx, 256, BPF_ADJ_ROOM_MAC, 0);
603+
if (err)
604+
goto out;
605+
606+
if (!check_skb_metadata(ctx))
607+
goto out;
608+
609+
test_pass = true;
610+
out:
611+
return TC_ACT_SHOT;
612+
}
613+
571614
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)