Skip to content

Commit 50905dd

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 847f4fe commit 50905dd

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));
@@ -488,6 +496,11 @@ void test_xdp_context_tuntap(void)
488496
skel->progs.helper_skb_vlan_push_pop,
489497
NULL, /* tc prio 2 */
490498
&skel->bss->test_pass);
499+
if (test__start_subtest("helper_skb_adjust_room"))
500+
test_tuntap(skel->progs.ing_xdp,
501+
skel->progs.helper_skb_adjust_room,
502+
NULL, /* tc prio 2 */
503+
&skel->bss->test_pass);
491504

492505
test_xdp_meta__destroy(skel);
493506
}

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

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,22 @@ enum {
2525

2626
bool test_pass;
2727

28+
static const __u8 smac_want[ETH_ALEN] = {
29+
0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF,
30+
};
31+
2832
static const __u8 meta_want[META_SIZE] = {
2933
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
3034
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
3135
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
3236
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
3337
};
3438

39+
static bool check_smac(const struct ethhdr *eth)
40+
{
41+
return !__builtin_memcmp(eth->h_source, smac_want, ETH_ALEN);
42+
}
43+
3544
static bool check_metadata(const char *file, int line, __u8 *meta_have)
3645
{
3746
if (!__builtin_memcmp(meta_have, meta_want, META_SIZE))
@@ -286,7 +295,7 @@ int ing_xdp_zalloc_meta(struct xdp_md *ctx)
286295
/* Drop any non-test packets */
287296
if (eth + 1 > ctx_ptr(ctx, data_end))
288297
return XDP_DROP;
289-
if (eth->h_proto != 0)
298+
if (!check_smac(eth))
290299
return XDP_DROP;
291300

292301
ret = bpf_xdp_adjust_meta(ctx, -META_SIZE);
@@ -326,9 +335,9 @@ int ing_xdp(struct xdp_md *ctx)
326335

327336
/* The Linux networking stack may send other packets on the test
328337
* interface that interfere with the test. Just drop them.
329-
* The test packets can be recognized by their ethertype of zero.
338+
* The test packets can be recognized by their source MAC address.
330339
*/
331-
if (eth->h_proto != 0)
340+
if (!check_smac(eth))
332341
return XDP_DROP;
333342

334343
__builtin_memcpy(data_meta, payload, META_SIZE);
@@ -348,7 +357,7 @@ int clone_data_meta_kept_on_data_write(struct __sk_buff *ctx)
348357
if (eth + 1 > ctx_ptr(ctx, data_end))
349358
goto out;
350359
/* Ignore non-test packets */
351-
if (eth->h_proto != 0)
360+
if (!check_smac(eth))
352361
goto out;
353362

354363
if (meta_have + META_SIZE > eth)
@@ -378,7 +387,7 @@ int clone_data_meta_kept_on_meta_write(struct __sk_buff *ctx)
378387
if (eth + 1 > ctx_ptr(ctx, data_end))
379388
goto out;
380389
/* Ignore non-test packets */
381-
if (eth->h_proto != 0)
390+
if (!check_smac(eth))
382391
goto out;
383392

384393
if (meta_have + META_SIZE > eth)
@@ -411,7 +420,7 @@ int clone_dynptr_kept_on_data_slice_write(struct __sk_buff *ctx)
411420
if (!eth)
412421
goto out;
413422
/* Ignore non-test packets */
414-
if (eth->h_proto != 0)
423+
if (!check_smac(eth))
415424
goto out;
416425

417426
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -440,7 +449,7 @@ int clone_dynptr_kept_on_meta_slice_write(struct __sk_buff *ctx)
440449
if (!eth)
441450
goto out;
442451
/* Ignore non-test packets */
443-
if (eth->h_proto != 0)
452+
if (!check_smac(eth))
444453
goto out;
445454

446455
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -473,7 +482,7 @@ int clone_dynptr_rdonly_before_data_dynptr_write_then_rw(struct __sk_buff *ctx)
473482
if (!eth)
474483
goto out;
475484
/* Ignore non-test packets */
476-
if (eth->h_proto != 0)
485+
if (!check_smac(eth))
477486
goto out;
478487

479488
/* Expect read-only metadata before unclone */
@@ -517,7 +526,7 @@ int clone_dynptr_rdonly_before_meta_dynptr_write(struct __sk_buff *ctx)
517526
if (!eth)
518527
goto out;
519528
/* Ignore non-test packets */
520-
if (eth->h_proto != 0)
529+
if (!check_smac(eth))
521530
goto out;
522531

523532
/* Expect read-only metadata */
@@ -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)