diff options
author | Andrey Ignatov <rdna@fb.com> | 2018-05-25 11:55:23 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-05-28 11:41:02 -0400 |
commit | 1cedee13d25ab118d325f95588c1a084e9317229 (patch) | |
tree | 63f5cd82b008d63091bac31168253e3af6a1ba6c /kernel/bpf/syscall.c | |
parent | 13193b0f392f5a65d0d54185cb95ed5e99c0a5bf (diff) |
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>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 388d4feda348..e254526d6744 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -1249,6 +1249,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type, | |||
1249 | case BPF_CGROUP_INET6_BIND: | 1249 | case BPF_CGROUP_INET6_BIND: |
1250 | case BPF_CGROUP_INET4_CONNECT: | 1250 | case BPF_CGROUP_INET4_CONNECT: |
1251 | case BPF_CGROUP_INET6_CONNECT: | 1251 | case BPF_CGROUP_INET6_CONNECT: |
1252 | case BPF_CGROUP_UDP4_SENDMSG: | ||
1253 | case BPF_CGROUP_UDP6_SENDMSG: | ||
1252 | return 0; | 1254 | return 0; |
1253 | default: | 1255 | default: |
1254 | return -EINVAL; | 1256 | return -EINVAL; |
@@ -1565,6 +1567,8 @@ static int bpf_prog_attach(const union bpf_attr *attr) | |||
1565 | case BPF_CGROUP_INET6_BIND: | 1567 | case BPF_CGROUP_INET6_BIND: |
1566 | case BPF_CGROUP_INET4_CONNECT: | 1568 | case BPF_CGROUP_INET4_CONNECT: |
1567 | case BPF_CGROUP_INET6_CONNECT: | 1569 | case BPF_CGROUP_INET6_CONNECT: |
1570 | case BPF_CGROUP_UDP4_SENDMSG: | ||
1571 | case BPF_CGROUP_UDP6_SENDMSG: | ||
1568 | ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; | 1572 | ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; |
1569 | break; | 1573 | break; |
1570 | case BPF_CGROUP_SOCK_OPS: | 1574 | case BPF_CGROUP_SOCK_OPS: |
@@ -1635,6 +1639,8 @@ static int bpf_prog_detach(const union bpf_attr *attr) | |||
1635 | case BPF_CGROUP_INET6_BIND: | 1639 | case BPF_CGROUP_INET6_BIND: |
1636 | case BPF_CGROUP_INET4_CONNECT: | 1640 | case BPF_CGROUP_INET4_CONNECT: |
1637 | case BPF_CGROUP_INET6_CONNECT: | 1641 | case BPF_CGROUP_INET6_CONNECT: |
1642 | case BPF_CGROUP_UDP4_SENDMSG: | ||
1643 | case BPF_CGROUP_UDP6_SENDMSG: | ||
1638 | ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; | 1644 | ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; |
1639 | break; | 1645 | break; |
1640 | case BPF_CGROUP_SOCK_OPS: | 1646 | case BPF_CGROUP_SOCK_OPS: |
@@ -1692,6 +1698,8 @@ static int bpf_prog_query(const union bpf_attr *attr, | |||
1692 | case BPF_CGROUP_INET6_POST_BIND: | 1698 | case BPF_CGROUP_INET6_POST_BIND: |
1693 | case BPF_CGROUP_INET4_CONNECT: | 1699 | case BPF_CGROUP_INET4_CONNECT: |
1694 | case BPF_CGROUP_INET6_CONNECT: | 1700 | case BPF_CGROUP_INET6_CONNECT: |
1701 | case BPF_CGROUP_UDP4_SENDMSG: | ||
1702 | case BPF_CGROUP_UDP6_SENDMSG: | ||
1695 | case BPF_CGROUP_SOCK_OPS: | 1703 | case BPF_CGROUP_SOCK_OPS: |
1696 | case BPF_CGROUP_DEVICE: | 1704 | case BPF_CGROUP_DEVICE: |
1697 | break; | 1705 | break; |