bpf: Hooks for sys_sendmsg
In addition to already existing BPF hooks for sys_bind and sys_connect, the patch provides new hooks for sys_sendmsg. It leverages existing BPF program type `BPF_PROG_TYPE_CGROUP_SOCK_ADDR` that provides access to socket itlself (properties like family, type, protocol) and user-passed `struct sockaddr *` so that BPF program can override destination IP and port for system calls such as sendto(2) or sendmsg(2) and/or assign source IP to the socket. The hooks are implemented as two new attach types: `BPF_CGROUP_UDP4_SENDMSG` and `BPF_CGROUP_UDP6_SENDMSG` for UDPv4 and UDPv6 correspondingly. UDPv4 and UDPv6 separate attach types for same reason as sys_bind and sys_connect hooks, i.e. to prevent reading from / writing to e.g. user_ip6 fields when user passes sockaddr_in since it'd be out-of-bound. The difference with already existing hooks is sys_sendmsg are implemented only for unconnected UDP. For TCP it doesn't make sense to change user-provided `struct sockaddr *` at sendto(2)/sendmsg(2) time since socket either was already connected and has source/destination set or wasn't connected and call to sendto(2)/sendmsg(2) would lead to ENOTCONN anyway. Connected UDP is already handled by sys_connect hooks that can override source/destination at connect time and use fast-path later, i.e. these hooks don't affect UDP fast-path. Rewriting source IP is implemented differently than that in sys_connect hooks. When sys_sendmsg is used with unconnected UDP it doesn't work to just bind socket to desired local IP address since source IP can be set on per-packet basis by using ancillary data (cmsg(3)). So no matter if socket is bound or not, source IP has to be rewritten on every call to sys_sendmsg. To do so two new fields are added to UAPI `struct bpf_sock_addr`; * `msg_src_ip4` to set source IPv4 for UDPv4; * `msg_src_ip6` to set source IPv6 for UDPv6. Signed-off-by: Andrey Ignatov <rdna@fb.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:

committed by
Daniel Borkmann

parent
13193b0f39
commit
1cedee13d2
@@ -1316,6 +1316,29 @@ do_udp_sendmsg:
|
||||
fl6.saddr = np->saddr;
|
||||
fl6.fl6_sport = inet->inet_sport;
|
||||
|
||||
if (cgroup_bpf_enabled && !connected) {
|
||||
err = BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk,
|
||||
(struct sockaddr *)sin6, &fl6.saddr);
|
||||
if (err)
|
||||
goto out_no_dst;
|
||||
if (sin6) {
|
||||
if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
|
||||
/* BPF program rewrote IPv6-only by IPv4-mapped
|
||||
* IPv6. It's currently unsupported.
|
||||
*/
|
||||
err = -ENOTSUPP;
|
||||
goto out_no_dst;
|
||||
}
|
||||
if (sin6->sin6_port == 0) {
|
||||
/* BPF program set invalid port. Reject it. */
|
||||
err = -EINVAL;
|
||||
goto out_no_dst;
|
||||
}
|
||||
fl6.fl6_dport = sin6->sin6_port;
|
||||
fl6.daddr = sin6->sin6_addr;
|
||||
}
|
||||
}
|
||||
|
||||
final_p = fl6_update_dst(&fl6, opt, &final);
|
||||
if (final_p)
|
||||
connected = false;
|
||||
@@ -1395,6 +1418,7 @@ do_append_data:
|
||||
|
||||
out:
|
||||
dst_release(dst);
|
||||
out_no_dst:
|
||||
fl6_sock_release(flowlabel);
|
||||
txopt_put(opt_to_free);
|
||||
if (!err)
|
||||
|
Reference in New Issue
Block a user