Commit 4aeba328 authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'fix-unconnected-udp'

Daniel Borkmann says:

====================
Please refer to the patch 1/6 as the main patch with the details
on the current sendmsg hook API limitations and proposal to fix
it in order to work with basic applications like DNS. Remaining
patches are the usual uapi and tooling updates as well as test
cases. Thanks a lot!

v2 -> v3:
  - Add attach types to test_section_names.c and libbpf (Andrey)
  - Added given Acks, rest as-is
v1 -> v2:
  - Split off uapi header sync and bpftool bits (Martin, Alexei)
  - Added missing bpftool doc and bash completion as well
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 1884c066 b714560f
...@@ -238,6 +238,12 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key, ...@@ -238,6 +238,12 @@ int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \ #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) \
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx) BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_SENDMSG, t_ctx)
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) \
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP4_RECVMSG, NULL)
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) \
BPF_CGROUP_RUN_SA_PROG_LOCK(sk, uaddr, BPF_CGROUP_UDP6_RECVMSG, NULL)
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) \ #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) \
({ \ ({ \
int __ret = 0; \ int __ret = 0; \
...@@ -339,6 +345,8 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map, ...@@ -339,6 +345,8 @@ static inline int bpf_percpu_cgroup_storage_update(struct bpf_map *map,
#define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; }) #define BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) #define BPF_CGROUP_RUN_PROG_UDP4_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; }) #define BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, uaddr, t_ctx) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, uaddr) ({ 0; })
#define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; }) #define BPF_CGROUP_RUN_PROG_SOCK_OPS(sock_ops) ({ 0; })
#define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; }) #define BPF_CGROUP_RUN_PROG_DEVICE_CGROUP(type,major,minor,access) ({ 0; })
#define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; }) #define BPF_CGROUP_RUN_PROG_SYSCTL(head,table,write,buf,count,pos,nbuf) ({ 0; })
......
...@@ -192,6 +192,8 @@ enum bpf_attach_type { ...@@ -192,6 +192,8 @@ enum bpf_attach_type {
BPF_LIRC_MODE2, BPF_LIRC_MODE2,
BPF_FLOW_DISSECTOR, BPF_FLOW_DISSECTOR,
BPF_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL,
BPF_CGROUP_UDP4_RECVMSG,
BPF_CGROUP_UDP6_RECVMSG,
__MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
}; };
......
...@@ -1581,6 +1581,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type, ...@@ -1581,6 +1581,8 @@ bpf_prog_load_check_attach_type(enum bpf_prog_type prog_type,
case BPF_CGROUP_INET6_CONNECT: case BPF_CGROUP_INET6_CONNECT:
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
case BPF_CGROUP_UDP4_RECVMSG:
case BPF_CGROUP_UDP6_RECVMSG:
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
...@@ -1875,6 +1877,8 @@ static int bpf_prog_attach(const union bpf_attr *attr) ...@@ -1875,6 +1877,8 @@ static int bpf_prog_attach(const union bpf_attr *attr)
case BPF_CGROUP_INET6_CONNECT: case BPF_CGROUP_INET6_CONNECT:
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
case BPF_CGROUP_UDP4_RECVMSG:
case BPF_CGROUP_UDP6_RECVMSG:
ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
break; break;
case BPF_CGROUP_SOCK_OPS: case BPF_CGROUP_SOCK_OPS:
...@@ -1960,6 +1964,8 @@ static int bpf_prog_detach(const union bpf_attr *attr) ...@@ -1960,6 +1964,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
case BPF_CGROUP_INET6_CONNECT: case BPF_CGROUP_INET6_CONNECT:
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
case BPF_CGROUP_UDP4_RECVMSG:
case BPF_CGROUP_UDP6_RECVMSG:
ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; ptype = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
break; break;
case BPF_CGROUP_SOCK_OPS: case BPF_CGROUP_SOCK_OPS:
...@@ -2011,6 +2017,8 @@ static int bpf_prog_query(const union bpf_attr *attr, ...@@ -2011,6 +2017,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
case BPF_CGROUP_INET6_CONNECT: case BPF_CGROUP_INET6_CONNECT:
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
case BPF_CGROUP_UDP4_RECVMSG:
case BPF_CGROUP_UDP6_RECVMSG:
case BPF_CGROUP_SOCK_OPS: case BPF_CGROUP_SOCK_OPS:
case BPF_CGROUP_DEVICE: case BPF_CGROUP_DEVICE:
case BPF_CGROUP_SYSCTL: case BPF_CGROUP_SYSCTL:
......
...@@ -5361,9 +5361,12 @@ static int check_return_code(struct bpf_verifier_env *env) ...@@ -5361,9 +5361,12 @@ static int check_return_code(struct bpf_verifier_env *env)
struct tnum range = tnum_range(0, 1); struct tnum range = tnum_range(0, 1);
switch (env->prog->type) { switch (env->prog->type) {
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
env->prog->expected_attach_type == BPF_CGROUP_UDP6_RECVMSG)
range = tnum_range(1, 1);
case BPF_PROG_TYPE_CGROUP_SKB: case BPF_PROG_TYPE_CGROUP_SKB:
case BPF_PROG_TYPE_CGROUP_SOCK: case BPF_PROG_TYPE_CGROUP_SOCK:
case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
case BPF_PROG_TYPE_SOCK_OPS: case BPF_PROG_TYPE_SOCK_OPS:
case BPF_PROG_TYPE_CGROUP_DEVICE: case BPF_PROG_TYPE_CGROUP_DEVICE:
case BPF_PROG_TYPE_CGROUP_SYSCTL: case BPF_PROG_TYPE_CGROUP_SYSCTL:
...@@ -5380,16 +5383,17 @@ static int check_return_code(struct bpf_verifier_env *env) ...@@ -5380,16 +5383,17 @@ static int check_return_code(struct bpf_verifier_env *env)
} }
if (!tnum_in(range, reg->var_off)) { if (!tnum_in(range, reg->var_off)) {
verbose(env, "At program exit the register R0 ");
if (!tnum_is_unknown(reg->var_off)) {
char tn_buf[48]; char tn_buf[48];
verbose(env, "At program exit the register R0 ");
if (!tnum_is_unknown(reg->var_off)) {
tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
verbose(env, "has value %s", tn_buf); verbose(env, "has value %s", tn_buf);
} else { } else {
verbose(env, "has unknown scalar value"); verbose(env, "has unknown scalar value");
} }
verbose(env, " should have been 0 or 1\n"); tnum_strn(tn_buf, sizeof(tn_buf), range);
verbose(env, " should have been in %s\n", tn_buf);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
......
...@@ -6748,6 +6748,7 @@ static bool sock_addr_is_valid_access(int off, int size, ...@@ -6748,6 +6748,7 @@ static bool sock_addr_is_valid_access(int off, int size,
case BPF_CGROUP_INET4_BIND: case BPF_CGROUP_INET4_BIND:
case BPF_CGROUP_INET4_CONNECT: case BPF_CGROUP_INET4_CONNECT:
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP4_RECVMSG:
break; break;
default: default:
return false; return false;
...@@ -6758,6 +6759,7 @@ static bool sock_addr_is_valid_access(int off, int size, ...@@ -6758,6 +6759,7 @@ static bool sock_addr_is_valid_access(int off, int size,
case BPF_CGROUP_INET6_BIND: case BPF_CGROUP_INET6_BIND:
case BPF_CGROUP_INET6_CONNECT: case BPF_CGROUP_INET6_CONNECT:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
case BPF_CGROUP_UDP6_RECVMSG:
break; break;
default: default:
return false; return false;
......
...@@ -1783,6 +1783,10 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, ...@@ -1783,6 +1783,10 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
sin->sin_addr.s_addr = ip_hdr(skb)->saddr; sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
*addr_len = sizeof(*sin); *addr_len = sizeof(*sin);
if (cgroup_bpf_enabled)
BPF_CGROUP_RUN_PROG_UDP4_RECVMSG_LOCK(sk,
(struct sockaddr *)sin);
} }
if (udp_sk(sk)->gro_enabled) if (udp_sk(sk)->gro_enabled)
......
...@@ -369,6 +369,10 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, ...@@ -369,6 +369,10 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
inet6_iif(skb)); inet6_iif(skb));
} }
*addr_len = sizeof(*sin6); *addr_len = sizeof(*sin6);
if (cgroup_bpf_enabled)
BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk,
(struct sockaddr *)sin6);
} }
if (udp_sk(sk)->gro_enabled) if (udp_sk(sk)->gro_enabled)
......
...@@ -29,7 +29,7 @@ CGROUP COMMANDS ...@@ -29,7 +29,7 @@ CGROUP COMMANDS
| *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* } | *PROG* := { **id** *PROG_ID* | **pinned** *FILE* | **tag** *PROG_TAG* }
| *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** | | *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** |
| **bind4** | **bind6** | **post_bind4** | **post_bind6** | **connect4** | **connect6** | | **bind4** | **bind6** | **post_bind4** | **post_bind6** | **connect4** | **connect6** |
| **sendmsg4** | **sendmsg6** | **sysctl** } | **sendmsg4** | **sendmsg6** | **recvmsg4** | **recvmsg6** | **sysctl** }
| *ATTACH_FLAGS* := { **multi** | **override** } | *ATTACH_FLAGS* := { **multi** | **override** }
DESCRIPTION DESCRIPTION
...@@ -86,6 +86,10 @@ DESCRIPTION ...@@ -86,6 +86,10 @@ DESCRIPTION
unconnected udp4 socket (since 4.18); unconnected udp4 socket (since 4.18);
**sendmsg6** call to sendto(2), sendmsg(2), sendmmsg(2) for an **sendmsg6** call to sendto(2), sendmsg(2), sendmmsg(2) for an
unconnected udp6 socket (since 4.18); unconnected udp6 socket (since 4.18);
**recvmsg4** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
an unconnected udp4 socket (since 5.2);
**recvmsg6** call to recvfrom(2), recvmsg(2), recvmmsg(2) for
an unconnected udp6 socket (since 5.2);
**sysctl** sysctl access (since 5.2). **sysctl** sysctl access (since 5.2).
**bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG* **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
......
...@@ -40,7 +40,7 @@ PROG COMMANDS ...@@ -40,7 +40,7 @@ PROG COMMANDS
| **lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** | | **lwt_seg6local** | **sockops** | **sk_skb** | **sk_msg** | **lirc_mode2** |
| **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** | | **cgroup/bind4** | **cgroup/bind6** | **cgroup/post_bind4** | **cgroup/post_bind6** |
| **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** | | **cgroup/connect4** | **cgroup/connect6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** |
| **cgroup/sysctl** | **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/sysctl**
| } | }
| *ATTACH_TYPE* := { | *ATTACH_TYPE* := {
| **msg_verdict** | **stream_verdict** | **stream_parser** | **flow_dissector** | **msg_verdict** | **stream_verdict** | **stream_parser** | **flow_dissector**
......
...@@ -371,6 +371,7 @@ _bpftool() ...@@ -371,6 +371,7 @@ _bpftool()
lirc_mode2 cgroup/bind4 cgroup/bind6 \ lirc_mode2 cgroup/bind4 cgroup/bind6 \
cgroup/connect4 cgroup/connect6 \ cgroup/connect4 cgroup/connect6 \
cgroup/sendmsg4 cgroup/sendmsg6 \ cgroup/sendmsg4 cgroup/sendmsg6 \
cgroup/recvmsg4 cgroup/recvmsg6 \
cgroup/post_bind4 cgroup/post_bind6 \ cgroup/post_bind4 cgroup/post_bind6 \
cgroup/sysctl" -- \ cgroup/sysctl" -- \
"$cur" ) ) "$cur" ) )
...@@ -666,7 +667,7 @@ _bpftool() ...@@ -666,7 +667,7 @@ _bpftool()
attach|detach) attach|detach)
local ATTACH_TYPES='ingress egress sock_create sock_ops \ local ATTACH_TYPES='ingress egress sock_create sock_ops \
device bind4 bind6 post_bind4 post_bind6 connect4 \ device bind4 bind6 post_bind4 post_bind6 connect4 \
connect6 sendmsg4 sendmsg6 sysctl' connect6 sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl'
local ATTACH_FLAGS='multi override' local ATTACH_FLAGS='multi override'
local PROG_TYPE='id pinned tag' local PROG_TYPE='id pinned tag'
case $prev in case $prev in
...@@ -676,7 +677,7 @@ _bpftool() ...@@ -676,7 +677,7 @@ _bpftool()
;; ;;
ingress|egress|sock_create|sock_ops|device|bind4|bind6|\ ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
post_bind4|post_bind6|connect4|connect6|sendmsg4|\ post_bind4|post_bind6|connect4|connect6|sendmsg4|\
sendmsg6|sysctl) sendmsg6|recvmsg4|recvmsg6|sysctl)
COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \ COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
"$cur" ) ) "$cur" ) )
return 0 return 0
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
" ATTACH_TYPE := { ingress | egress | sock_create |\n" \ " ATTACH_TYPE := { ingress | egress | sock_create |\n" \
" sock_ops | device | bind4 | bind6 |\n" \ " sock_ops | device | bind4 | bind6 |\n" \
" post_bind4 | post_bind6 | connect4 |\n" \ " post_bind4 | post_bind6 | connect4 |\n" \
" connect6 | sendmsg4 | sendmsg6 | sysctl }" " connect6 | sendmsg4 | sendmsg6 |\n" \
" recvmsg4 | recvmsg6 | sysctl }"
static const char * const attach_type_strings[] = { static const char * const attach_type_strings[] = {
[BPF_CGROUP_INET_INGRESS] = "ingress", [BPF_CGROUP_INET_INGRESS] = "ingress",
...@@ -42,6 +43,8 @@ static const char * const attach_type_strings[] = { ...@@ -42,6 +43,8 @@ static const char * const attach_type_strings[] = {
[BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4", [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
[BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6", [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
[BPF_CGROUP_SYSCTL] = "sysctl", [BPF_CGROUP_SYSCTL] = "sysctl",
[BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
[BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
[__MAX_BPF_ATTACH_TYPE] = NULL, [__MAX_BPF_ATTACH_TYPE] = NULL,
}; };
......
...@@ -1063,7 +1063,8 @@ static int do_help(int argc, char **argv) ...@@ -1063,7 +1063,8 @@ static int do_help(int argc, char **argv)
" sk_reuseport | flow_dissector | cgroup/sysctl |\n" " sk_reuseport | flow_dissector | cgroup/sysctl |\n"
" cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n" " cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
" cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n" " cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
" cgroup/sendmsg4 | cgroup/sendmsg6 }\n" " cgroup/sendmsg4 | cgroup/sendmsg6 | cgroup/recvmsg4 |\n"
" cgroup/recvmsg6 }\n"
" ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n" " ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n"
" flow_dissector }\n" " flow_dissector }\n"
" " HELP_SPEC_OPTIONS "\n" " " HELP_SPEC_OPTIONS "\n"
......
...@@ -192,6 +192,8 @@ enum bpf_attach_type { ...@@ -192,6 +192,8 @@ enum bpf_attach_type {
BPF_LIRC_MODE2, BPF_LIRC_MODE2,
BPF_FLOW_DISSECTOR, BPF_FLOW_DISSECTOR,
BPF_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL,
BPF_CGROUP_UDP4_RECVMSG,
BPF_CGROUP_UDP6_RECVMSG,
__MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
}; };
......
...@@ -3210,6 +3210,10 @@ static const struct { ...@@ -3210,6 +3210,10 @@ static const struct {
BPF_CGROUP_UDP4_SENDMSG), BPF_CGROUP_UDP4_SENDMSG),
BPF_EAPROG_SEC("cgroup/sendmsg6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_EAPROG_SEC("cgroup/sendmsg6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_CGROUP_UDP6_SENDMSG), BPF_CGROUP_UDP6_SENDMSG),
BPF_EAPROG_SEC("cgroup/recvmsg4", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_CGROUP_UDP4_RECVMSG),
BPF_EAPROG_SEC("cgroup/recvmsg6", BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_CGROUP_UDP6_RECVMSG),
BPF_EAPROG_SEC("cgroup/sysctl", BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_EAPROG_SEC("cgroup/sysctl", BPF_PROG_TYPE_CGROUP_SYSCTL,
BPF_CGROUP_SYSCTL), BPF_CGROUP_SYSCTL),
}; };
......
...@@ -119,6 +119,16 @@ static struct sec_name_test tests[] = { ...@@ -119,6 +119,16 @@ static struct sec_name_test tests[] = {
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG}, {0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_SENDMSG},
{0, BPF_CGROUP_UDP6_SENDMSG}, {0, BPF_CGROUP_UDP6_SENDMSG},
}, },
{
"cgroup/recvmsg4",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP4_RECVMSG},
{0, BPF_CGROUP_UDP4_RECVMSG},
},
{
"cgroup/recvmsg6",
{0, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_UDP6_RECVMSG},
{0, BPF_CGROUP_UDP6_RECVMSG},
},
{ {
"cgroup/sysctl", "cgroup/sysctl",
{0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL}, {0, BPF_PROG_TYPE_CGROUP_SYSCTL, BPF_CGROUP_SYSCTL},
......
...@@ -76,6 +76,7 @@ struct sock_addr_test { ...@@ -76,6 +76,7 @@ struct sock_addr_test {
enum { enum {
LOAD_REJECT, LOAD_REJECT,
ATTACH_REJECT, ATTACH_REJECT,
ATTACH_OKAY,
SYSCALL_EPERM, SYSCALL_EPERM,
SYSCALL_ENOTSUPP, SYSCALL_ENOTSUPP,
SUCCESS, SUCCESS,
...@@ -88,9 +89,13 @@ static int connect4_prog_load(const struct sock_addr_test *test); ...@@ -88,9 +89,13 @@ static int connect4_prog_load(const struct sock_addr_test *test);
static int connect6_prog_load(const struct sock_addr_test *test); static int connect6_prog_load(const struct sock_addr_test *test);
static int sendmsg_allow_prog_load(const struct sock_addr_test *test); static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
static int sendmsg_deny_prog_load(const struct sock_addr_test *test); static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test); static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test); static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test); static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test); static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test); static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test); static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
...@@ -507,6 +512,92 @@ static struct sock_addr_test tests[] = { ...@@ -507,6 +512,92 @@ static struct sock_addr_test tests[] = {
SRC6_REWRITE_IP, SRC6_REWRITE_IP,
SYSCALL_EPERM, SYSCALL_EPERM,
}, },
/* recvmsg */
{
"recvmsg4: return code ok",
recvmsg_allow_prog_load,
BPF_CGROUP_UDP4_RECVMSG,
BPF_CGROUP_UDP4_RECVMSG,
AF_INET,
SOCK_DGRAM,
NULL,
0,
NULL,
0,
NULL,
ATTACH_OKAY,
},
{
"recvmsg4: return code !ok",
recvmsg_deny_prog_load,
BPF_CGROUP_UDP4_RECVMSG,
BPF_CGROUP_UDP4_RECVMSG,
AF_INET,
SOCK_DGRAM,
NULL,
0,
NULL,
0,
NULL,
LOAD_REJECT,
},
{
"recvmsg6: return code ok",
recvmsg_allow_prog_load,
BPF_CGROUP_UDP6_RECVMSG,
BPF_CGROUP_UDP6_RECVMSG,
AF_INET6,
SOCK_DGRAM,
NULL,
0,
NULL,
0,
NULL,
ATTACH_OKAY,
},
{
"recvmsg6: return code !ok",
recvmsg_deny_prog_load,
BPF_CGROUP_UDP6_RECVMSG,
BPF_CGROUP_UDP6_RECVMSG,
AF_INET6,
SOCK_DGRAM,
NULL,
0,
NULL,
0,
NULL,
LOAD_REJECT,
},
{
"recvmsg4: rewrite IP & port (asm)",
recvmsg4_rw_asm_prog_load,
BPF_CGROUP_UDP4_RECVMSG,
BPF_CGROUP_UDP4_RECVMSG,
AF_INET,
SOCK_DGRAM,
SERV4_REWRITE_IP,
SERV4_REWRITE_PORT,
SERV4_REWRITE_IP,
SERV4_REWRITE_PORT,
SERV4_IP,
SUCCESS,
},
{
"recvmsg6: rewrite IP & port (asm)",
recvmsg6_rw_asm_prog_load,
BPF_CGROUP_UDP6_RECVMSG,
BPF_CGROUP_UDP6_RECVMSG,
AF_INET6,
SOCK_DGRAM,
SERV6_REWRITE_IP,
SERV6_REWRITE_PORT,
SERV6_REWRITE_IP,
SERV6_REWRITE_PORT,
SERV6_IP,
SUCCESS,
},
}; };
static int mk_sockaddr(int domain, const char *ip, unsigned short port, static int mk_sockaddr(int domain, const char *ip, unsigned short port,
...@@ -765,7 +856,7 @@ static int connect6_prog_load(const struct sock_addr_test *test) ...@@ -765,7 +856,7 @@ static int connect6_prog_load(const struct sock_addr_test *test)
return load_path(test, CONNECT6_PROG_PATH); return load_path(test, CONNECT6_PROG_PATH);
} }
static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test, static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
int32_t rc) int32_t rc)
{ {
struct bpf_insn insns[] = { struct bpf_insn insns[] = {
...@@ -778,12 +869,22 @@ static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test, ...@@ -778,12 +869,22 @@ static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
static int sendmsg_allow_prog_load(const struct sock_addr_test *test) static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
{ {
return sendmsg_ret_only_prog_load(test, /*rc*/ 1); return xmsg_ret_only_prog_load(test, /*rc*/ 1);
} }
static int sendmsg_deny_prog_load(const struct sock_addr_test *test) static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
{ {
return sendmsg_ret_only_prog_load(test, /*rc*/ 0); return xmsg_ret_only_prog_load(test, /*rc*/ 0);
}
static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
{
return xmsg_ret_only_prog_load(test, /*rc*/ 1);
}
static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
{
return xmsg_ret_only_prog_load(test, /*rc*/ 0);
} }
static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
...@@ -838,6 +939,47 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) ...@@ -838,6 +939,47 @@ static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
} }
static int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
{
struct sockaddr_in src4_rw_addr;
if (mk_sockaddr(AF_INET, SERV4_IP, SERV4_PORT,
(struct sockaddr *)&src4_rw_addr,
sizeof(src4_rw_addr)) == -1)
return -1;
struct bpf_insn insns[] = {
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
/* if (sk.family == AF_INET && */
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock_addr, family)),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 6),
/* sk.type == SOCK_DGRAM) { */
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock_addr, type)),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 4),
/* user_ip4 = src4_rw_addr.sin_addr */
BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_addr.s_addr),
BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
offsetof(struct bpf_sock_addr, user_ip4)),
/* user_port = src4_rw_addr.sin_port */
BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_port),
BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
offsetof(struct bpf_sock_addr, user_port)),
/* } */
/* return 1 */
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_EXIT_INSN(),
};
return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
}
static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test) static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
{ {
return load_path(test, SENDMSG4_PROG_PATH); return load_path(test, SENDMSG4_PROG_PATH);
...@@ -901,6 +1043,39 @@ static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test) ...@@ -901,6 +1043,39 @@ static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP); return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
} }
static int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
{
struct sockaddr_in6 src6_rw_addr;
if (mk_sockaddr(AF_INET6, SERV6_IP, SERV6_PORT,
(struct sockaddr *)&src6_rw_addr,
sizeof(src6_rw_addr)) == -1)
return -1;
struct bpf_insn insns[] = {
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
/* if (sk.family == AF_INET6) { */
BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
offsetof(struct bpf_sock_addr, family)),
BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 10),
STORE_IPV6(user_ip6, src6_rw_addr.sin6_addr.s6_addr32),
/* user_port = dst6_rw_addr.sin6_port */
BPF_MOV32_IMM(BPF_REG_7, src6_rw_addr.sin6_port),
BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
offsetof(struct bpf_sock_addr, user_port)),
/* } */
/* return 1 */
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_EXIT_INSN(),
};
return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
}
static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test) static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
{ {
return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP); return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
...@@ -1282,13 +1457,13 @@ static int run_connect_test_case(const struct sock_addr_test *test) ...@@ -1282,13 +1457,13 @@ static int run_connect_test_case(const struct sock_addr_test *test)
return err; return err;
} }
static int run_sendmsg_test_case(const struct sock_addr_test *test) static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
{ {
socklen_t addr_len = sizeof(struct sockaddr_storage); socklen_t addr_len = sizeof(struct sockaddr_storage);
struct sockaddr_storage expected_src_addr;
struct sockaddr_storage requested_addr;
struct sockaddr_storage expected_addr; struct sockaddr_storage expected_addr;
struct sockaddr_storage real_src_addr; struct sockaddr_storage server_addr;
struct sockaddr_storage sendmsg_addr;
struct sockaddr_storage recvmsg_addr;
int clientfd = -1; int clientfd = -1;
int servfd = -1; int servfd = -1;
int set_cmsg; int set_cmsg;
...@@ -1297,20 +1472,19 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test) ...@@ -1297,20 +1472,19 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
if (test->type != SOCK_DGRAM) if (test->type != SOCK_DGRAM)
goto err; goto err;
if (init_addrs(test, &requested_addr, &expected_addr, if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
&expected_src_addr))
goto err; goto err;
/* Prepare server to sendmsg to */ /* Prepare server to sendmsg to */
servfd = start_server(test->type, &expected_addr, addr_len); servfd = start_server(test->type, &server_addr, addr_len);
if (servfd == -1) if (servfd == -1)
goto err; goto err;
for (set_cmsg = 0; set_cmsg <= 1; ++set_cmsg) { for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
if (clientfd >= 0) if (clientfd >= 0)
close(clientfd); close(clientfd);
clientfd = sendmsg_to_server(test->type, &requested_addr, clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
addr_len, set_cmsg, /*flags*/0, addr_len, set_cmsg, /*flags*/0,
&err); &err);
if (err) if (err)
...@@ -1330,10 +1504,10 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test) ...@@ -1330,10 +1504,10 @@ static int run_sendmsg_test_case(const struct sock_addr_test *test)
* specific packet may differ from the one used by default and * specific packet may differ from the one used by default and
* returned by getsockname(2). * returned by getsockname(2).
*/ */
if (recvmsg_from_client(servfd, &real_src_addr) == -1) if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
goto err; goto err;
if (cmp_addr(&real_src_addr, &expected_src_addr, /*cmp_port*/0)) if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
goto err; goto err;
} }
...@@ -1366,6 +1540,9 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test) ...@@ -1366,6 +1540,9 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
goto out; goto out;
} else if (test->expected_result == ATTACH_REJECT || err) { } else if (test->expected_result == ATTACH_REJECT || err) {
goto err; goto err;
} else if (test->expected_result == ATTACH_OKAY) {
err = 0;
goto out;
} }
switch (test->attach_type) { switch (test->attach_type) {
...@@ -1379,7 +1556,11 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test) ...@@ -1379,7 +1556,11 @@ static int run_test_case(int cgfd, const struct sock_addr_test *test)
break; break;
case BPF_CGROUP_UDP4_SENDMSG: case BPF_CGROUP_UDP4_SENDMSG:
case BPF_CGROUP_UDP6_SENDMSG: case BPF_CGROUP_UDP6_SENDMSG:
err = run_sendmsg_test_case(test); err = run_xmsg_test_case(test, 1);
break;
case BPF_CGROUP_UDP4_RECVMSG:
case BPF_CGROUP_UDP6_RECVMSG:
err = run_xmsg_test_case(test, 0);
break; break;
default: default:
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment