OSDN Git Service

bpf: export bpf_sock for BPF_PROG_TYPE_SOCK_OPS prog type
authorStanislav Fomichev <sdf@google.com>
Wed, 12 Jun 2019 17:30:38 +0000 (10:30 -0700)
committerDaniel Borkmann <daniel@iogearbox.net>
Fri, 14 Jun 2019 23:21:57 +0000 (01:21 +0200)
And let it use bpf_sk_storage_{get,delete} helpers to access socket
storage. Kernel context (struct bpf_sock_ops_kern) already has sk
member, so I just expose it to the BPF hooks. I use
PTR_TO_SOCKET_OR_NULL and return NULL in !is_fullsock case.

I also export bpf_tcp_sock to make it possible to access tcp socket stats.

Cc: Martin Lau <kafai@fb.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
include/uapi/linux/bpf.h
net/core/filter.c

index 8815fc4..d0a2347 100644 (file)
@@ -3299,6 +3299,7 @@ struct bpf_sock_ops {
        __u32 sk_txhash;
        __u64 bytes_received;
        __u64 bytes_acked;
+       __bpf_md_ptr(struct bpf_sock *, sk);
 };
 
 /* Definitions for bpf_sock_ops_cb_flags */
index 37c4a2f..8c18f27 100644 (file)
@@ -6147,6 +6147,14 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_local_storage_proto;
        case BPF_FUNC_perf_event_output:
                return &bpf_sockopt_event_output_proto;
+       case BPF_FUNC_sk_storage_get:
+               return &bpf_sk_storage_get_proto;
+       case BPF_FUNC_sk_storage_delete:
+               return &bpf_sk_storage_delete_proto;
+#ifdef CONFIG_INET
+       case BPF_FUNC_tcp_sock:
+               return &bpf_tcp_sock_proto;
+#endif /* CONFIG_INET */
        default:
                return bpf_base_func_proto(func_id);
        }
@@ -6882,6 +6890,11 @@ static bool sock_ops_is_valid_access(int off, int size,
                        if (size != sizeof(__u64))
                                return false;
                        break;
+               case offsetof(struct bpf_sock_ops, sk):
+                       if (size != sizeof(__u64))
+                               return false;
+                       info->reg_type = PTR_TO_SOCKET_OR_NULL;
+                       break;
                default:
                        if (size != size_default)
                                return false;
@@ -8053,6 +8066,19 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash,
                                          struct sock, type);
                break;
+       case offsetof(struct bpf_sock_ops, sk):
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+                                               struct bpf_sock_ops_kern,
+                                               is_fullsock),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern,
+                                              is_fullsock));
+               *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1);
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+                                               struct bpf_sock_ops_kern, sk),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern, sk));
+               break;
        }
        return insn - insn_buf;
 }