diff options
author | Julia Kartseva <hex@fb.com> | 2021-06-11 18:27:27 -0700 |
---|---|---|
committer | Julia Kartseva <hex@fb.com> | 2021-06-29 14:37:07 -0700 |
commit | 560d76243fab5b7809996ac353fbc79da9a3bd92 (patch) | |
tree | 6ccf3935faee6a5ef82c7de9d9e60c6e7cd631d2 | |
parent | 9fcfc0470df856c870dcfc6df78bfbc714da6bd2 (diff) | |
download | systemd-560d76243fab5b7809996ac353fbc79da9a3bd92.tar.gz |
bpf: add ip proto matching to socket-bind prog
Lookup ip protocol in a socket address to allow or deny binding a socket
to the address.
Matching rule is extended with 'protocol' field. If its value is 0
(IPPROTO_IP) ip protocol comparison is omitted and matching is passed to
the next token which is ip ports.
Documentation is updated.
-rw-r--r-- | src/core/bpf-socket-bind.c | 1 | ||||
-rw-r--r-- | src/core/bpf/socket_bind/socket-bind-api.bpf.h | 28 | ||||
-rw-r--r-- | src/core/bpf/socket_bind/socket-bind.bpf.c | 12 |
3 files changed, 27 insertions, 14 deletions
diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 66c82d5469..9983691575 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -35,6 +35,7 @@ static int update_rules_map( LIST_FOREACH(socket_bind_items, item, head) { struct socket_bind_rule val = { .address_family = (uint32_t) item->address_family, + .protocol = item->ip_protocol, .nr_ports = item->nr_ports, .port_min = item->port_min, }; diff --git a/src/core/bpf/socket_bind/socket-bind-api.bpf.h b/src/core/bpf/socket_bind/socket-bind-api.bpf.h index 418889955b..277b9bbde2 100644 --- a/src/core/bpf/socket_bind/socket-bind-api.bpf.h +++ b/src/core/bpf/socket_bind/socket-bind-api.bpf.h @@ -11,35 +11,39 @@ /* * Bind rule is matched with socket fields accessible to cgroup/bind{4,6} hook * through bpf_sock_addr struct. - * address_family is expected to be one of AF_UNSPEC, AF_INET or AF_INET6. + * 'address_family' is expected to be one of AF_UNSPEC, AF_INET or AF_INET6. * Matching by family is bypassed for rules with AF_UNSPEC set, which makes the * rest of a rule applicable for both IPv4 and IPv6 addresses. * If matching by family is either successful or bypassed, a rule and a socket - * are matched by ports. - * nr_ports and port_min fields specify a set of ports to match a user port + * are matched by ip protocol. + * If 'protocol' is 0, matching is bypassed. + * 'nr_ports' and 'port_min' fields specify a set of ports to match a user port * with. - * If nr_ports is 0, matching by port is bypassed, making that rule applicable + * If 'nr_ports' is 0, matching by port is bypassed, making that rule applicable * for all possible ports, e.g. [1, 65535] range. Thus a rule with - * address_family and nr_ports equal to AF_UNSPEC and 0 correspondingly forms - * 'allow any' or 'deny any' cases. - * For positive nr_ports, a user_port lying in a range from port_min to - * port_min + nr_ports exclusively is considered to be a match. nr_ports + * 'address_family', 'protocol' and 'nr_ports' equal to AF_UNSPEC, 0 and 0 + * correspondingly forms 'allow any' or 'deny any' cases. + * For positive 'nr_ports', a user_port lying in a range from 'port_min' to' + * 'port_min' + 'nr_ports' exclusively is considered to be a match. 'nr_ports' * equalling to 1 forms a rule for a single port. * Ports are in host order. * * Examples: - * AF_UNSPEC, 1, 7777: match IPv4 and IPv6 addresses with 7777 user port; + * AF_UNSPEC, 1, 0, 7777: match IPv4 and IPv6 addresses with 7777 user port; * - * AF_INET, 1023, 1: match IPv4 addresses with user port in [1, 1023] + * AF_INET, 1023, 0, 1: match IPv4 addresses with user port in [1, 1023] * range inclusively; * - * AF_INET6, 0, 0: match IPv6 addresses; + * AF_INET6, 0, 0, 0: match IPv6 addresses; * - * AF_UNSPEC, 0, 0: match IPv4 and IPv6 addresses. + * AF_UNSPEC, 0, 0, 0: match IPv4 and IPv6 addresses; + * + * AF_INET6, IPPROTO_TCP, 0, 0: match IPv6/TCP addresses. */ struct socket_bind_rule { __u32 address_family; + __u32 protocol; __u16 nr_ports; __u16 port_min; }; diff --git a/src/core/bpf/socket_bind/socket-bind.bpf.c b/src/core/bpf/socket_bind/socket-bind.bpf.c index 474808d824..8004400e6c 100644 --- a/src/core/bpf/socket_bind/socket-bind.bpf.c +++ b/src/core/bpf/socket_bind/socket-bind.bpf.c @@ -39,6 +39,11 @@ static __always_inline bool match_af( return r->address_family == AF_UNSPEC || address_family == r->address_family; } +static __always_inline bool match_protocol( + __u32 protocol, const struct socket_bind_rule *r) { + return r->protocol == 0 || r->protocol == protocol; +} + static __always_inline bool match_user_port( __u16 port, const struct socket_bind_rule *r) { return r->nr_ports == 0 || @@ -47,9 +52,12 @@ static __always_inline bool match_user_port( static __always_inline bool match( __u8 address_family, + __u32 protocol, __u16 port, const struct socket_bind_rule *r) { - return match_af(address_family, r) && match_user_port(port, r); + return match_af(address_family, r) && + match_protocol(protocol, r) && + match_user_port(port, r); } static __always_inline bool match_rules( @@ -67,7 +75,7 @@ static __always_inline bool match_rules( if (!rule) break; - if (match(ctx->user_family, port, rule)) + if (match(ctx->user_family, ctx->protocol, port, rule)) return true; } |