Message ID | 20230829101838.851350-4-daan.j.demeyer@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | Add cgroup sockaddr hooks for unix sockets | expand |
On Tue, Aug 29, 2023 at 3:19 AM Daan De Meyer <daan.j.demeyer@gmail.com> wrote: > > As prep for adding unix socket support to the cgroup sockaddr hooks, > let's add a kfunc bpf_sock_addr_set() that allows modifying a sockaddr > from bpf. While this is already possible for AF_INET and AF_INET6, we'll > need this kfunc when we add unix socket support since modifying the > address for those requires modifying both the address and the sockaddr > length. > > We also add the necessary hook to make the new kfunc work properly. > > Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com> > --- > kernel/bpf/btf.c | 3 +++ > net/core/filter.c | 42 +++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 44 insertions(+), 1 deletion(-) > > diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c > index 249657c466dd..157342eaa2bb 100644 > --- a/kernel/bpf/btf.c > +++ b/kernel/bpf/btf.c > @@ -217,6 +217,7 @@ enum btf_kfunc_hook { > m, > BTF_KFUNC_HOOK_LWT, > BTF_KFUNC_HOOK_NETFILTER, > + BTF_KFUNC_HOOK_SOCK_ADDR, Do we really need a new kfunc category? Can BTF_KFUNC_HOOK_CGROUP_SKB be reused here? or even BTF_KFUNC_HOOK_COMMON ? struct bpf_sock_addr_kern * type of bpf_sock_addr_set_addr() will prevent any other type being passed in here and bpf_sock_addr_kern type is local to prog run via __cgroup_bpf_run_filter_sock_addr.
On 8/29/23 3:18 AM, Daan De Meyer wrote: > +__bpf_kfunc int bpf_sock_addr_set_addr(struct bpf_sock_addr_kern *sa_kern, > + const u8 *addr, u32 addrlen__sz) > +{ > + struct sockaddr *sa = sa_kern->uaddr; > + struct sockaddr_in *sa4; > + struct sockaddr_in6 *sa6; > + struct sockaddr_un *un; > + > + switch (sa->sa_family) { The sa_family could be AF_UNSPEC here for inet addr (eg. take a look at __inet_bind checking AF_UNSPEC). Test the sa_kern->sk->sk_family instead. > + case AF_INET: > + if (addrlen__sz != 4) > + return -EINVAL; > + sa4 = (struct sockaddr_in *)sa; > + sa4->sin_addr.s_addr = *(__be32 *)addr; > + break; > + case AF_INET6: > + if (addrlen__sz != 16) > + return -EINVAL; > + sa6 = (struct sockaddr_in6 *)sa; > + memcpy(sa6->sin6_addr.s6_addr, addr, 16); > + break; > + default: > + WARN_ON_ONCE(1); The above switch case will test sk_family instead, so this WARN should never happen and should be removed. > + return -EINVAL; > + } > + > + return 0; > +} > __diag_pop();
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 249657c466dd..157342eaa2bb 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -217,6 +217,7 @@ enum btf_kfunc_hook { BTF_KFUNC_HOOK_SOCKET_FILTER, BTF_KFUNC_HOOK_LWT, BTF_KFUNC_HOOK_NETFILTER, + BTF_KFUNC_HOOK_SOCK_ADDR, BTF_KFUNC_HOOK_MAX, }; @@ -7846,6 +7847,8 @@ static int bpf_prog_type_to_kfunc_hook(enum bpf_prog_type prog_type) return BTF_KFUNC_HOOK_LWT; case BPF_PROG_TYPE_NETFILTER: return BTF_KFUNC_HOOK_NETFILTER; + case BPF_PROG_TYPE_CGROUP_SOCK_ADDR: + return BTF_KFUNC_HOOK_SOCK_ADDR; default: return BTF_KFUNC_HOOK_MAX; } diff --git a/net/core/filter.c b/net/core/filter.c index a094694899c9..c58c3cd2cd55 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -11752,6 +11752,35 @@ __bpf_kfunc int bpf_dynptr_from_xdp(struct xdp_buff *xdp, u64 flags, return 0; } + +__bpf_kfunc int bpf_sock_addr_set_addr(struct bpf_sock_addr_kern *sa_kern, + const u8 *addr, u32 addrlen__sz) +{ + struct sockaddr *sa = sa_kern->uaddr; + struct sockaddr_in *sa4; + struct sockaddr_in6 *sa6; + struct sockaddr_un *un; + + switch (sa->sa_family) { + case AF_INET: + if (addrlen__sz != 4) + return -EINVAL; + sa4 = (struct sockaddr_in *)sa; + sa4->sin_addr.s_addr = *(__be32 *)addr; + break; + case AF_INET6: + if (addrlen__sz != 16) + return -EINVAL; + sa6 = (struct sockaddr_in6 *)sa; + memcpy(sa6->sin6_addr.s6_addr, addr, 16); + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + + return 0; +} __diag_pop(); int bpf_dynptr_from_skb_rdonly(struct sk_buff *skb, u64 flags, @@ -11776,6 +11805,10 @@ BTF_SET8_START(bpf_kfunc_check_set_xdp) BTF_ID_FLAGS(func, bpf_dynptr_from_xdp) BTF_SET8_END(bpf_kfunc_check_set_xdp) +BTF_SET8_START(bpf_kfunc_check_set_sock_addr) +BTF_ID_FLAGS(func, bpf_sock_addr_set_addr) +BTF_SET8_END(bpf_kfunc_check_set_sock_addr) + static const struct btf_kfunc_id_set bpf_kfunc_set_skb = { .owner = THIS_MODULE, .set = &bpf_kfunc_check_set_skb, @@ -11786,6 +11819,11 @@ static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = { .set = &bpf_kfunc_check_set_xdp, }; +static const struct btf_kfunc_id_set bpf_kfunc_set_sock_addr = { + .owner = THIS_MODULE, + .set = &bpf_kfunc_check_set_sock_addr, +}; + static int __init bpf_kfunc_init(void) { int ret; @@ -11800,7 +11838,9 @@ static int __init bpf_kfunc_init(void) ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_XMIT, &bpf_kfunc_set_skb); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, &bpf_kfunc_set_skb); ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_NETFILTER, &bpf_kfunc_set_skb); - return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp); + ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_kfunc_set_xdp); + return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + &bpf_kfunc_set_sock_addr); } late_initcall(bpf_kfunc_init);
As prep for adding unix socket support to the cgroup sockaddr hooks, let's add a kfunc bpf_sock_addr_set() that allows modifying a sockaddr from bpf. While this is already possible for AF_INET and AF_INET6, we'll need this kfunc when we add unix socket support since modifying the address for those requires modifying both the address and the sockaddr length. We also add the necessary hook to make the new kfunc work properly. Signed-off-by: Daan De Meyer <daan.j.demeyer@gmail.com> --- kernel/bpf/btf.c | 3 +++ net/core/filter.c | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-)