diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/filter.c | 86 | ||||
| -rw-r--r-- | net/core/sock.c | 4 | ||||
| -rw-r--r-- | net/core/sock_reuseport.c | 24 |
3 files changed, 114 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 949adc3d9abb..2014d76e0d2a 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -5695,6 +5695,46 @@ BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb) | |||
| 5695 | return INET_ECN_set_ce(skb); | 5695 | return INET_ECN_set_ce(skb); |
| 5696 | } | 5696 | } |
| 5697 | 5697 | ||
| 5698 | bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type, | ||
| 5699 | struct bpf_insn_access_aux *info) | ||
| 5700 | { | ||
| 5701 | if (off < 0 || off >= offsetofend(struct bpf_xdp_sock, queue_id)) | ||
| 5702 | return false; | ||
| 5703 | |||
| 5704 | if (off % size != 0) | ||
| 5705 | return false; | ||
| 5706 | |||
| 5707 | switch (off) { | ||
| 5708 | default: | ||
| 5709 | return size == sizeof(__u32); | ||
| 5710 | } | ||
| 5711 | } | ||
| 5712 | |||
| 5713 | u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type, | ||
| 5714 | const struct bpf_insn *si, | ||
| 5715 | struct bpf_insn *insn_buf, | ||
| 5716 | struct bpf_prog *prog, u32 *target_size) | ||
| 5717 | { | ||
| 5718 | struct bpf_insn *insn = insn_buf; | ||
| 5719 | |||
| 5720 | #define BPF_XDP_SOCK_GET(FIELD) \ | ||
| 5721 | do { \ | ||
| 5722 | BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) > \ | ||
| 5723 | FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \ | ||
| 5724 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\ | ||
| 5725 | si->dst_reg, si->src_reg, \ | ||
| 5726 | offsetof(struct xdp_sock, FIELD)); \ | ||
| 5727 | } while (0) | ||
| 5728 | |||
| 5729 | switch (si->off) { | ||
| 5730 | case offsetof(struct bpf_xdp_sock, queue_id): | ||
| 5731 | BPF_XDP_SOCK_GET(queue_id); | ||
| 5732 | break; | ||
| 5733 | } | ||
| 5734 | |||
| 5735 | return insn - insn_buf; | ||
| 5736 | } | ||
| 5737 | |||
| 5698 | static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = { | 5738 | static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = { |
| 5699 | .func = bpf_skb_ecn_set_ce, | 5739 | .func = bpf_skb_ecn_set_ce, |
| 5700 | .gpl_only = false, | 5740 | .gpl_only = false, |
| @@ -5897,6 +5937,10 @@ sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 5897 | case BPF_FUNC_skc_lookup_tcp: | 5937 | case BPF_FUNC_skc_lookup_tcp: |
| 5898 | return &bpf_sock_addr_skc_lookup_tcp_proto; | 5938 | return &bpf_sock_addr_skc_lookup_tcp_proto; |
| 5899 | #endif /* CONFIG_INET */ | 5939 | #endif /* CONFIG_INET */ |
| 5940 | case BPF_FUNC_sk_storage_get: | ||
| 5941 | return &bpf_sk_storage_get_proto; | ||
| 5942 | case BPF_FUNC_sk_storage_delete: | ||
| 5943 | return &bpf_sk_storage_delete_proto; | ||
| 5900 | default: | 5944 | default: |
| 5901 | return bpf_base_func_proto(func_id); | 5945 | return bpf_base_func_proto(func_id); |
| 5902 | } | 5946 | } |
| @@ -5934,6 +5978,10 @@ cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 5934 | return &bpf_sk_storage_get_proto; | 5978 | return &bpf_sk_storage_get_proto; |
| 5935 | case BPF_FUNC_sk_storage_delete: | 5979 | case BPF_FUNC_sk_storage_delete: |
| 5936 | return &bpf_sk_storage_delete_proto; | 5980 | return &bpf_sk_storage_delete_proto; |
| 5981 | #ifdef CONFIG_SOCK_CGROUP_DATA | ||
| 5982 | case BPF_FUNC_skb_cgroup_id: | ||
| 5983 | return &bpf_skb_cgroup_id_proto; | ||
| 5984 | #endif | ||
| 5937 | #ifdef CONFIG_INET | 5985 | #ifdef CONFIG_INET |
| 5938 | case BPF_FUNC_tcp_sock: | 5986 | case BPF_FUNC_tcp_sock: |
| 5939 | return &bpf_tcp_sock_proto; | 5987 | return &bpf_tcp_sock_proto; |
| @@ -6114,6 +6162,14 @@ sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) | |||
| 6114 | return &bpf_get_local_storage_proto; | 6162 | return &bpf_get_local_storage_proto; |
| 6115 | case BPF_FUNC_perf_event_output: | 6163 | case BPF_FUNC_perf_event_output: |
| 6116 | return &bpf_sockopt_event_output_proto; | 6164 | return &bpf_sockopt_event_output_proto; |
| 6165 | case BPF_FUNC_sk_storage_get: | ||
| 6166 | return &bpf_sk_storage_get_proto; | ||
| 6167 | case BPF_FUNC_sk_storage_delete: | ||
| 6168 | return &bpf_sk_storage_delete_proto; | ||
| 6169 | #ifdef CONFIG_INET | ||
| 6170 | case BPF_FUNC_tcp_sock: | ||
| 6171 | return &bpf_tcp_sock_proto; | ||
| 6172 | #endif /* CONFIG_INET */ | ||
| 6117 | default: | 6173 | default: |
| 6118 | return bpf_base_func_proto(func_id); | 6174 | return bpf_base_func_proto(func_id); |
| 6119 | } | 6175 | } |
| @@ -6801,6 +6857,13 @@ static bool sock_addr_is_valid_access(int off, int size, | |||
| 6801 | if (size != size_default) | 6857 | if (size != size_default) |
| 6802 | return false; | 6858 | return false; |
| 6803 | break; | 6859 | break; |
| 6860 | case offsetof(struct bpf_sock_addr, sk): | ||
| 6861 | if (type != BPF_READ) | ||
| 6862 | return false; | ||
| 6863 | if (size != sizeof(__u64)) | ||
| 6864 | return false; | ||
| 6865 | info->reg_type = PTR_TO_SOCKET; | ||
| 6866 | break; | ||
| 6804 | default: | 6867 | default: |
| 6805 | if (type == BPF_READ) { | 6868 | if (type == BPF_READ) { |
| 6806 | if (size != size_default) | 6869 | if (size != size_default) |
| @@ -6844,6 +6907,11 @@ static bool sock_ops_is_valid_access(int off, int size, | |||
| 6844 | if (size != sizeof(__u64)) | 6907 | if (size != sizeof(__u64)) |
| 6845 | return false; | 6908 | return false; |
| 6846 | break; | 6909 | break; |
| 6910 | case offsetof(struct bpf_sock_ops, sk): | ||
| 6911 | if (size != sizeof(__u64)) | ||
| 6912 | return false; | ||
| 6913 | info->reg_type = PTR_TO_SOCKET_OR_NULL; | ||
| 6914 | break; | ||
| 6847 | default: | 6915 | default: |
| 6848 | if (size != size_default) | 6916 | if (size != size_default) |
| 6849 | return false; | 6917 | return false; |
| @@ -7751,6 +7819,11 @@ static u32 sock_addr_convert_ctx_access(enum bpf_access_type type, | |||
| 7751 | struct bpf_sock_addr_kern, struct in6_addr, t_ctx, | 7819 | struct bpf_sock_addr_kern, struct in6_addr, t_ctx, |
| 7752 | s6_addr32[0], BPF_SIZE(si->code), off, tmp_reg); | 7820 | s6_addr32[0], BPF_SIZE(si->code), off, tmp_reg); |
| 7753 | break; | 7821 | break; |
| 7822 | case offsetof(struct bpf_sock_addr, sk): | ||
| 7823 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_addr_kern, sk), | ||
| 7824 | si->dst_reg, si->src_reg, | ||
| 7825 | offsetof(struct bpf_sock_addr_kern, sk)); | ||
| 7826 | break; | ||
| 7754 | } | 7827 | } |
| 7755 | 7828 | ||
| 7756 | return insn - insn_buf; | 7829 | return insn - insn_buf; |
| @@ -8010,6 +8083,19 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type, | |||
| 8010 | SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash, | 8083 | SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash, |
| 8011 | struct sock, type); | 8084 | struct sock, type); |
| 8012 | break; | 8085 | break; |
| 8086 | case offsetof(struct bpf_sock_ops, sk): | ||
| 8087 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( | ||
| 8088 | struct bpf_sock_ops_kern, | ||
| 8089 | is_fullsock), | ||
| 8090 | si->dst_reg, si->src_reg, | ||
| 8091 | offsetof(struct bpf_sock_ops_kern, | ||
| 8092 | is_fullsock)); | ||
| 8093 | *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1); | ||
| 8094 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( | ||
| 8095 | struct bpf_sock_ops_kern, sk), | ||
| 8096 | si->dst_reg, si->src_reg, | ||
| 8097 | offsetof(struct bpf_sock_ops_kern, sk)); | ||
| 8098 | break; | ||
| 8013 | } | 8099 | } |
| 8014 | return insn - insn_buf; | 8100 | return insn - insn_buf; |
| 8015 | } | 8101 | } |
diff --git a/net/core/sock.c b/net/core/sock.c index af09a23e4822..ef471f643c95 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -1039,6 +1039,10 @@ set_rcvbuf: | |||
| 1039 | } | 1039 | } |
| 1040 | break; | 1040 | break; |
| 1041 | 1041 | ||
| 1042 | case SO_DETACH_REUSEPORT_BPF: | ||
| 1043 | ret = reuseport_detach_prog(sk); | ||
| 1044 | break; | ||
| 1045 | |||
| 1042 | case SO_DETACH_FILTER: | 1046 | case SO_DETACH_FILTER: |
| 1043 | ret = sk_detach_filter(sk); | 1047 | ret = sk_detach_filter(sk); |
| 1044 | break; | 1048 | break; |
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index dc4aefdf2a08..9408f9264d05 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c | |||
| @@ -332,3 +332,27 @@ int reuseport_attach_prog(struct sock *sk, struct bpf_prog *prog) | |||
| 332 | return 0; | 332 | return 0; |
| 333 | } | 333 | } |
| 334 | EXPORT_SYMBOL(reuseport_attach_prog); | 334 | EXPORT_SYMBOL(reuseport_attach_prog); |
| 335 | |||
| 336 | int reuseport_detach_prog(struct sock *sk) | ||
| 337 | { | ||
| 338 | struct sock_reuseport *reuse; | ||
| 339 | struct bpf_prog *old_prog; | ||
| 340 | |||
| 341 | if (!rcu_access_pointer(sk->sk_reuseport_cb)) | ||
| 342 | return sk->sk_reuseport ? -ENOENT : -EINVAL; | ||
| 343 | |||
| 344 | old_prog = NULL; | ||
| 345 | spin_lock_bh(&reuseport_lock); | ||
| 346 | reuse = rcu_dereference_protected(sk->sk_reuseport_cb, | ||
| 347 | lockdep_is_held(&reuseport_lock)); | ||
| 348 | rcu_swap_protected(reuse->prog, old_prog, | ||
| 349 | lockdep_is_held(&reuseport_lock)); | ||
| 350 | spin_unlock_bh(&reuseport_lock); | ||
| 351 | |||
| 352 | if (!old_prog) | ||
| 353 | return -ENOENT; | ||
| 354 | |||
| 355 | sk_reuseport_prog_free(old_prog); | ||
| 356 | return 0; | ||
| 357 | } | ||
| 358 | EXPORT_SYMBOL(reuseport_detach_prog); | ||
