mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
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.
This commit is contained in:
parent
9fcfc0470d
commit
560d76243f
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user