|
@@ -2818,6 +2818,32 @@ static bool lwt_is_valid_access(int off, int size,
|
|
|
return __is_valid_access(off, size, type);
|
|
|
}
|
|
|
|
|
|
+static bool sock_filter_is_valid_access(int off, int size,
|
|
|
+ enum bpf_access_type type,
|
|
|
+ enum bpf_reg_type *reg_type)
|
|
|
+{
|
|
|
+ if (type == BPF_WRITE) {
|
|
|
+ switch (off) {
|
|
|
+ case offsetof(struct bpf_sock, bound_dev_if):
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (off < 0 || off + size > sizeof(struct bpf_sock))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* The verifier guarantees that size > 0. */
|
|
|
+ if (off % size != 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (size != sizeof(__u32))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static int tc_cls_act_prologue(struct bpf_insn *insn_buf, bool direct_write,
|
|
|
const struct bpf_prog *prog)
|
|
|
{
|
|
@@ -3076,6 +3102,30 @@ static u32 sk_filter_convert_ctx_access(enum bpf_access_type type, int dst_reg,
|
|
|
return insn - insn_buf;
|
|
|
}
|
|
|
|
|
|
+static u32 sock_filter_convert_ctx_access(enum bpf_access_type type,
|
|
|
+ int dst_reg, int src_reg,
|
|
|
+ int ctx_off,
|
|
|
+ struct bpf_insn *insn_buf,
|
|
|
+ struct bpf_prog *prog)
|
|
|
+{
|
|
|
+ struct bpf_insn *insn = insn_buf;
|
|
|
+
|
|
|
+ switch (ctx_off) {
|
|
|
+ case offsetof(struct bpf_sock, bound_dev_if):
|
|
|
+ BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_bound_dev_if) != 4);
|
|
|
+
|
|
|
+ if (type == BPF_WRITE)
|
|
|
+ *insn++ = BPF_STX_MEM(BPF_W, dst_reg, src_reg,
|
|
|
+ offsetof(struct sock, sk_bound_dev_if));
|
|
|
+ else
|
|
|
+ *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
|
|
|
+ offsetof(struct sock, sk_bound_dev_if));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return insn - insn_buf;
|
|
|
+}
|
|
|
+
|
|
|
static u32 tc_cls_act_convert_ctx_access(enum bpf_access_type type, int dst_reg,
|
|
|
int src_reg, int ctx_off,
|
|
|
struct bpf_insn *insn_buf,
|
|
@@ -3162,6 +3212,12 @@ static const struct bpf_verifier_ops lwt_xmit_ops = {
|
|
|
.gen_prologue = tc_cls_act_prologue,
|
|
|
};
|
|
|
|
|
|
+static const struct bpf_verifier_ops cg_sock_ops = {
|
|
|
+ .get_func_proto = sk_filter_func_proto,
|
|
|
+ .is_valid_access = sock_filter_is_valid_access,
|
|
|
+ .convert_ctx_access = sock_filter_convert_ctx_access,
|
|
|
+};
|
|
|
+
|
|
|
static struct bpf_prog_type_list sk_filter_type __read_mostly = {
|
|
|
.ops = &sk_filter_ops,
|
|
|
.type = BPF_PROG_TYPE_SOCKET_FILTER,
|
|
@@ -3202,6 +3258,11 @@ static struct bpf_prog_type_list lwt_xmit_type __read_mostly = {
|
|
|
.type = BPF_PROG_TYPE_LWT_XMIT,
|
|
|
};
|
|
|
|
|
|
+static struct bpf_prog_type_list cg_sock_type __read_mostly = {
|
|
|
+ .ops = &cg_sock_ops,
|
|
|
+ .type = BPF_PROG_TYPE_CGROUP_SOCK
|
|
|
+};
|
|
|
+
|
|
|
static int __init register_sk_filter_ops(void)
|
|
|
{
|
|
|
bpf_register_prog_type(&sk_filter_type);
|
|
@@ -3209,6 +3270,7 @@ static int __init register_sk_filter_ops(void)
|
|
|
bpf_register_prog_type(&sched_act_type);
|
|
|
bpf_register_prog_type(&xdp_type);
|
|
|
bpf_register_prog_type(&cg_skb_type);
|
|
|
+ bpf_register_prog_type(&cg_sock_type);
|
|
|
bpf_register_prog_type(&lwt_in_type);
|
|
|
bpf_register_prog_type(&lwt_out_type);
|
|
|
bpf_register_prog_type(&lwt_xmit_type);
|