Skip to content

Commit f11216b

Browse files
vladumAlexei Starovoitov
authored andcommitted
bpf: add skb->tstamp r/w access from tc clsact and cg skb progs
This could be used to rate limit egress traffic in concert with a qdisc which supports Earliest Departure Time, such as FQ. Write access from cg skb progs only with CAP_SYS_ADMIN, since the value will be used by downstream qdiscs. It might make sense to relax this. Changes v1 -> v2: - allow access from cg skb, write only with CAP_SYS_ADMIN Signed-off-by: Vlad Dumitrescu <[email protected]> Acked-by: Eric Dumazet <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent ab85b01 commit f11216b

4 files changed

Lines changed: 60 additions & 0 deletions

File tree

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,6 +2468,7 @@ struct __sk_buff {
24682468

24692469
__u32 data_meta;
24702470
struct bpf_flow_keys *flow_keys;
2471+
__u64 tstamp;
24712472
};
24722473

24732474
struct bpf_tunnel_key {

net/core/filter.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5573,6 +5573,10 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
55735573
if (size != sizeof(struct bpf_flow_keys *))
55745574
return false;
55755575
break;
5576+
case bpf_ctx_range(struct __sk_buff, tstamp):
5577+
if (size != sizeof(__u64))
5578+
return false;
5579+
break;
55765580
default:
55775581
/* Only narrow read access allowed for now. */
55785582
if (type == BPF_WRITE) {
@@ -5600,6 +5604,7 @@ static bool sk_filter_is_valid_access(int off, int size,
56005604
case bpf_ctx_range(struct __sk_buff, data_end):
56015605
case bpf_ctx_range(struct __sk_buff, flow_keys):
56025606
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
5607+
case bpf_ctx_range(struct __sk_buff, tstamp):
56035608
return false;
56045609
}
56055610

@@ -5638,6 +5643,10 @@ static bool cg_skb_is_valid_access(int off, int size,
56385643
case bpf_ctx_range(struct __sk_buff, priority):
56395644
case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
56405645
break;
5646+
case bpf_ctx_range(struct __sk_buff, tstamp):
5647+
if (!capable(CAP_SYS_ADMIN))
5648+
return false;
5649+
break;
56415650
default:
56425651
return false;
56435652
}
@@ -5665,6 +5674,7 @@ static bool lwt_is_valid_access(int off, int size,
56655674
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
56665675
case bpf_ctx_range(struct __sk_buff, data_meta):
56675676
case bpf_ctx_range(struct __sk_buff, flow_keys):
5677+
case bpf_ctx_range(struct __sk_buff, tstamp):
56685678
return false;
56695679
}
56705680

@@ -5874,6 +5884,7 @@ static bool tc_cls_act_is_valid_access(int off, int size,
58745884
case bpf_ctx_range(struct __sk_buff, priority):
58755885
case bpf_ctx_range(struct __sk_buff, tc_classid):
58765886
case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
5887+
case bpf_ctx_range(struct __sk_buff, tstamp):
58775888
break;
58785889
default:
58795890
return false;
@@ -6093,6 +6104,7 @@ static bool sk_skb_is_valid_access(int off, int size,
60936104
case bpf_ctx_range(struct __sk_buff, tc_classid):
60946105
case bpf_ctx_range(struct __sk_buff, data_meta):
60956106
case bpf_ctx_range(struct __sk_buff, flow_keys):
6107+
case bpf_ctx_range(struct __sk_buff, tstamp):
60966108
return false;
60976109
}
60986110

@@ -6179,6 +6191,7 @@ static bool flow_dissector_is_valid_access(int off, int size,
61796191
case bpf_ctx_range(struct __sk_buff, tc_classid):
61806192
case bpf_ctx_range(struct __sk_buff, data_meta):
61816193
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
6194+
case bpf_ctx_range(struct __sk_buff, tstamp):
61826195
return false;
61836196
}
61846197

@@ -6488,6 +6501,22 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
64886501
*insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
64896502
si->src_reg, off);
64906503
break;
6504+
6505+
case offsetof(struct __sk_buff, tstamp):
6506+
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tstamp) != 8);
6507+
6508+
if (type == BPF_WRITE)
6509+
*insn++ = BPF_STX_MEM(BPF_DW,
6510+
si->dst_reg, si->src_reg,
6511+
bpf_target_off(struct sk_buff,
6512+
tstamp, 8,
6513+
target_size));
6514+
else
6515+
*insn++ = BPF_LDX_MEM(BPF_DW,
6516+
si->dst_reg, si->src_reg,
6517+
bpf_target_off(struct sk_buff,
6518+
tstamp, 8,
6519+
target_size));
64916520
}
64926521

64936522
return insn - insn_buf;

tools/include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2468,6 +2468,7 @@ struct __sk_buff {
24682468

24692469
__u32 data_meta;
24702470
struct bpf_flow_keys *flow_keys;
2471+
__u64 tstamp;
24712472
};
24722473

24732474
struct bpf_tunnel_key {

tools/testing/selftests/bpf/test_verifier.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,6 +2446,10 @@ static struct bpf_test tests[] = {
24462446
offsetof(struct __sk_buff, tc_index)),
24472447
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
24482448
offsetof(struct __sk_buff, cb[3])),
2449+
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
2450+
offsetof(struct __sk_buff, tstamp)),
2451+
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
2452+
offsetof(struct __sk_buff, tstamp)),
24492453
BPF_EXIT_INSN(),
24502454
},
24512455
.errstr_unpriv = "",
@@ -5297,6 +5301,31 @@ static struct bpf_test tests[] = {
52975301
.errstr_unpriv = "R2 leaks addr into helper function",
52985302
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
52995303
},
5304+
{
5305+
"write tstamp from CGROUP_SKB",
5306+
.insns = {
5307+
BPF_MOV64_IMM(BPF_REG_0, 0),
5308+
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
5309+
offsetof(struct __sk_buff, tstamp)),
5310+
BPF_MOV64_IMM(BPF_REG_0, 0),
5311+
BPF_EXIT_INSN(),
5312+
},
5313+
.result = ACCEPT,
5314+
.result_unpriv = REJECT,
5315+
.errstr_unpriv = "invalid bpf_context access off=152 size=8",
5316+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5317+
},
5318+
{
5319+
"read tstamp from CGROUP_SKB",
5320+
.insns = {
5321+
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
5322+
offsetof(struct __sk_buff, tstamp)),
5323+
BPF_MOV64_IMM(BPF_REG_0, 0),
5324+
BPF_EXIT_INSN(),
5325+
},
5326+
.result = ACCEPT,
5327+
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
5328+
},
53005329
{
53015330
"multiple registers share map_lookup_elem result",
53025331
.insns = {

0 commit comments

Comments
 (0)