Skip to content

Commit 21594c4

Browse files
zeilborkmann
authored andcommitted
bpf: Allow to specify ifindex for skb in bpf_prog_test_run_skb
Now skb->dev is unconditionally set to the loopback device in current net namespace. But if we want to test bpf program which contains code branch based on ifindex condition (eg filters out localhost packets) it is useful to allow specifying of ifindex from userspace. This patch adds such option through ctx_in (__sk_buff) parameter. Signed-off-by: Dmitry Yakunin <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent fa5cb54 commit 21594c4

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

net/bpf/test_run.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,12 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb)
327327
/* priority is allowed */
328328

329329
if (!range_is_zero(__skb, offsetofend(struct __sk_buff, priority),
330+
offsetof(struct __sk_buff, ifindex)))
331+
return -EINVAL;
332+
333+
/* ifindex is allowed */
334+
335+
if (!range_is_zero(__skb, offsetofend(struct __sk_buff, ifindex),
330336
offsetof(struct __sk_buff, cb)))
331337
return -EINVAL;
332338

@@ -381,6 +387,7 @@ static void convert_skb_to___skb(struct sk_buff *skb, struct __sk_buff *__skb)
381387

382388
__skb->mark = skb->mark;
383389
__skb->priority = skb->priority;
390+
__skb->ifindex = skb->dev->ifindex;
384391
__skb->tstamp = skb->tstamp;
385392
memcpy(__skb->cb, &cb->data, QDISC_CB_PRIV_LEN);
386393
__skb->wire_len = cb->pkt_len;
@@ -391,6 +398,8 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
391398
union bpf_attr __user *uattr)
392399
{
393400
bool is_l2 = false, is_direct_pkt_access = false;
401+
struct net *net = current->nsproxy->net_ns;
402+
struct net_device *dev = net->loopback_dev;
394403
u32 size = kattr->test.data_size_in;
395404
u32 repeat = kattr->test.repeat;
396405
struct __sk_buff *ctx = NULL;
@@ -432,7 +441,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
432441
kfree(ctx);
433442
return -ENOMEM;
434443
}
435-
sock_net_set(sk, current->nsproxy->net_ns);
444+
sock_net_set(sk, net);
436445
sock_init_data(NULL, sk);
437446

438447
skb = build_skb(data, 0);
@@ -446,7 +455,14 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
446455

447456
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
448457
__skb_put(skb, size);
449-
skb->protocol = eth_type_trans(skb, current->nsproxy->net_ns->loopback_dev);
458+
if (ctx && ctx->ifindex > 1) {
459+
dev = dev_get_by_index(net, ctx->ifindex);
460+
if (!dev) {
461+
ret = -ENODEV;
462+
goto out;
463+
}
464+
}
465+
skb->protocol = eth_type_trans(skb, dev);
450466
skb_reset_network_header(skb);
451467

452468
switch (skb->protocol) {
@@ -502,6 +518,8 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr,
502518
ret = bpf_ctx_finish(kattr, uattr, ctx,
503519
sizeof(struct __sk_buff));
504520
out:
521+
if (dev && dev != net->loopback_dev)
522+
dev_put(dev);
505523
kfree_skb(skb);
506524
bpf_sk_storage_free(sk);
507525
kfree(sk);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ void test_skb_ctx(void)
1111
.cb[3] = 4,
1212
.cb[4] = 5,
1313
.priority = 6,
14+
.ifindex = 1,
1415
.tstamp = 7,
1516
.wire_len = 100,
1617
.gso_segs = 8,
@@ -92,6 +93,10 @@ void test_skb_ctx(void)
9293
"ctx_out_priority",
9394
"skb->priority == %d, expected %d\n",
9495
skb.priority, 7);
96+
CHECK_ATTR(skb.ifindex != 1,
97+
"ctx_out_ifindex",
98+
"skb->ifindex == %d, expected %d\n",
99+
skb.ifindex, 1);
95100
CHECK_ATTR(skb.tstamp != 8,
96101
"ctx_out_tstamp",
97102
"skb->tstamp == %lld, expected %d\n",

0 commit comments

Comments
 (0)