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 <vladum@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Родитель
ab85b01434
Коммит
f11216b242
|
@ -2468,6 +2468,7 @@ struct __sk_buff {
|
|||
|
||||
__u32 data_meta;
|
||||
struct bpf_flow_keys *flow_keys;
|
||||
__u64 tstamp;
|
||||
};
|
||||
|
||||
struct bpf_tunnel_key {
|
||||
|
|
|
@ -5573,6 +5573,10 @@ static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type
|
|||
if (size != sizeof(struct bpf_flow_keys *))
|
||||
return false;
|
||||
break;
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
if (size != sizeof(__u64))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
/* Only narrow read access allowed for now. */
|
||||
if (type == BPF_WRITE) {
|
||||
|
@ -5600,6 +5604,7 @@ static bool sk_filter_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct __sk_buff, data_end):
|
||||
case bpf_ctx_range(struct __sk_buff, flow_keys):
|
||||
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5638,6 +5643,10 @@ static bool cg_skb_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct __sk_buff, priority):
|
||||
case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
|
||||
break;
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -5665,6 +5674,7 @@ static bool lwt_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
|
||||
case bpf_ctx_range(struct __sk_buff, data_meta):
|
||||
case bpf_ctx_range(struct __sk_buff, flow_keys):
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5874,6 +5884,7 @@ static bool tc_cls_act_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct __sk_buff, priority):
|
||||
case bpf_ctx_range(struct __sk_buff, tc_classid):
|
||||
case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -6093,6 +6104,7 @@ static bool sk_skb_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct __sk_buff, tc_classid):
|
||||
case bpf_ctx_range(struct __sk_buff, data_meta):
|
||||
case bpf_ctx_range(struct __sk_buff, flow_keys):
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6179,6 +6191,7 @@ static bool flow_dissector_is_valid_access(int off, int size,
|
|||
case bpf_ctx_range(struct __sk_buff, tc_classid):
|
||||
case bpf_ctx_range(struct __sk_buff, data_meta):
|
||||
case bpf_ctx_range_till(struct __sk_buff, family, local_port):
|
||||
case bpf_ctx_range(struct __sk_buff, tstamp):
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6488,6 +6501,22 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
|
|||
*insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
|
||||
si->src_reg, off);
|
||||
break;
|
||||
|
||||
case offsetof(struct __sk_buff, tstamp):
|
||||
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tstamp) != 8);
|
||||
|
||||
if (type == BPF_WRITE)
|
||||
*insn++ = BPF_STX_MEM(BPF_DW,
|
||||
si->dst_reg, si->src_reg,
|
||||
bpf_target_off(struct sk_buff,
|
||||
tstamp, 8,
|
||||
target_size));
|
||||
else
|
||||
*insn++ = BPF_LDX_MEM(BPF_DW,
|
||||
si->dst_reg, si->src_reg,
|
||||
bpf_target_off(struct sk_buff,
|
||||
tstamp, 8,
|
||||
target_size));
|
||||
}
|
||||
|
||||
return insn - insn_buf;
|
||||
|
|
|
@ -2468,6 +2468,7 @@ struct __sk_buff {
|
|||
|
||||
__u32 data_meta;
|
||||
struct bpf_flow_keys *flow_keys;
|
||||
__u64 tstamp;
|
||||
};
|
||||
|
||||
struct bpf_tunnel_key {
|
||||
|
|
|
@ -2446,6 +2446,10 @@ static struct bpf_test tests[] = {
|
|||
offsetof(struct __sk_buff, tc_index)),
|
||||
BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[3])),
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, tstamp)),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, tstamp)),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.errstr_unpriv = "",
|
||||
|
@ -5297,6 +5301,31 @@ static struct bpf_test tests[] = {
|
|||
.errstr_unpriv = "R2 leaks addr into helper function",
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
|
||||
},
|
||||
{
|
||||
"write tstamp from CGROUP_SKB",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, tstamp)),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = ACCEPT,
|
||||
.result_unpriv = REJECT,
|
||||
.errstr_unpriv = "invalid bpf_context access off=152 size=8",
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
|
||||
},
|
||||
{
|
||||
"read tstamp from CGROUP_SKB",
|
||||
.insns = {
|
||||
BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, tstamp)),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.result = ACCEPT,
|
||||
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
|
||||
},
|
||||
{
|
||||
"multiple registers share map_lookup_elem result",
|
||||
.insns = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче