mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-05 09:17:44 +03:00
core: replace IPAddressAccessItem with struct in_addr_prefix
Previously, if a unit file which contains n IPAddressAllow/Deny= lines, then the computational order of parsing the file was O(n^3), as ip_address_access_reduce(), whose order is O(n^2), is called for each line. By replacing in_addr_prefix related functions, now the computational order is O(n log n). Fixes #20680.
This commit is contained in:
parent
60da07ecc7
commit
84ebe6f013
@ -11,7 +11,7 @@
|
||||
#include "bus-util.h"
|
||||
#include "env-util.h"
|
||||
#include "format-table.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
#include "manager.h"
|
||||
@ -2582,10 +2582,10 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
IPAddressAccessItem *i;
|
||||
struct in_addr_prefix *i;
|
||||
bool deny_ipv4 = false, deny_ipv6 = false;
|
||||
|
||||
LIST_FOREACH(items, i, g->ip_address_deny) {
|
||||
SET_FOREACH(i, g->ip_address_deny) {
|
||||
if (i->family == AF_INET && i->prefixlen == 0)
|
||||
deny_ipv4 = true;
|
||||
else if (i->family == AF_INET6 && i->prefixlen == 0)
|
||||
@ -2594,7 +2594,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
|
||||
info->ip_address_deny_all = deny_ipv4 && deny_ipv6;
|
||||
|
||||
info->ip_address_allow_localhost = info->ip_address_allow_other = false;
|
||||
LIST_FOREACH(items, i, g->ip_address_allow) {
|
||||
SET_FOREACH(i, g->ip_address_allow) {
|
||||
if (in_addr_is_localhost(i->family, &i->address))
|
||||
info->ip_address_allow_localhost = true;
|
||||
else
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "bpf-firewall.h"
|
||||
#include "bpf-program.h"
|
||||
#include "fd-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "unit.h"
|
||||
@ -335,13 +335,13 @@ static int bpf_firewall_compile_bpf(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ipv4, size_t *n_ipv6) {
|
||||
IPAddressAccessItem *a;
|
||||
static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t *n_ipv6) {
|
||||
struct in_addr_prefix *a;
|
||||
|
||||
assert(n_ipv4);
|
||||
assert(n_ipv6);
|
||||
|
||||
LIST_FOREACH(items, a, list) {
|
||||
SET_FOREACH(a, prefixes)
|
||||
switch (a->family) {
|
||||
|
||||
case AF_INET:
|
||||
@ -355,26 +355,25 @@ static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_firewall_add_access_items(
|
||||
IPAddressAccessItem *list,
|
||||
Set *prefixes,
|
||||
int ipv4_map_fd,
|
||||
int ipv6_map_fd,
|
||||
int verdict) {
|
||||
|
||||
struct bpf_lpm_trie_key *key_ipv4, *key_ipv6;
|
||||
struct in_addr_prefix *a;
|
||||
uint64_t value = verdict;
|
||||
IPAddressAccessItem *a;
|
||||
int r;
|
||||
|
||||
key_ipv4 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t));
|
||||
key_ipv6 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t) * 4);
|
||||
|
||||
LIST_FOREACH(items, a, list) {
|
||||
SET_FOREACH(a, prefixes)
|
||||
switch (a->family) {
|
||||
|
||||
case AF_INET:
|
||||
@ -400,7 +399,6 @@ static int bpf_firewall_add_access_items(
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -414,7 +412,6 @@ static int bpf_firewall_prepare_access_maps(
|
||||
|
||||
_cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1;
|
||||
size_t n_ipv4 = 0, n_ipv6 = 0;
|
||||
IPAddressAccessItem *list;
|
||||
Unit *p;
|
||||
int r;
|
||||
|
||||
@ -424,18 +421,29 @@ static int bpf_firewall_prepare_access_maps(
|
||||
|
||||
for (p = u; p; p = UNIT_GET_SLICE(p)) {
|
||||
CGroupContext *cc;
|
||||
Set *prefixes;
|
||||
bool *reduced;
|
||||
|
||||
cc = unit_get_cgroup_context(p);
|
||||
if (!cc)
|
||||
continue;
|
||||
|
||||
list = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny;
|
||||
prefixes = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny;
|
||||
reduced = verdict == ACCESS_ALLOWED ? &cc->ip_address_allow_reduced : &cc->ip_address_deny_reduced;
|
||||
|
||||
bpf_firewall_count_access_items(list, &n_ipv4, &n_ipv6);
|
||||
if (!*reduced) {
|
||||
r = in_addr_prefixes_reduce(prefixes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*reduced = true;
|
||||
}
|
||||
|
||||
bpf_firewall_count_access_items(prefixes, &n_ipv4, &n_ipv6);
|
||||
|
||||
/* Skip making the LPM trie map in cases where we are using "any" in order to hack around
|
||||
* needing CAP_SYS_ADMIN for allocating LPM trie map. */
|
||||
if (ip_address_access_item_is_any(list)) {
|
||||
if (in_addr_prefixes_is_any(prefixes)) {
|
||||
*ret_has_any = true;
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "io-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "limits-util.h"
|
||||
@ -238,8 +239,8 @@ void cgroup_context_done(CGroupContext *c) {
|
||||
cgroup_context_remove_socket_bind(&c->socket_bind_allow);
|
||||
cgroup_context_remove_socket_bind(&c->socket_bind_deny);
|
||||
|
||||
c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
|
||||
c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
|
||||
c->ip_address_allow = set_free(c->ip_address_allow);
|
||||
c->ip_address_deny = set_free(c->ip_address_deny);
|
||||
|
||||
c->ip_filters_ingress = strv_free(c->ip_filters_ingress);
|
||||
c->ip_filters_egress = strv_free(c->ip_filters_egress);
|
||||
@ -395,7 +396,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
|
||||
CGroupDeviceAllow *a;
|
||||
CGroupContext *c;
|
||||
CGroupSocketBindItem *bi;
|
||||
IPAddressAccessItem *iaai;
|
||||
struct in_addr_prefix *iaai;
|
||||
char **path;
|
||||
|
||||
char cda[FORMAT_CGROUP_DIFF_MAX];
|
||||
@ -549,18 +550,18 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
|
||||
FORMAT_BYTES(b->wbps));
|
||||
}
|
||||
|
||||
LIST_FOREACH(items, iaai, c->ip_address_allow) {
|
||||
SET_FOREACH(iaai, c->ip_address_allow) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
(void) in_addr_to_string(iaai->family, &iaai->address, &k);
|
||||
fprintf(f, "%sIPAddressAllow: %s/%u\n", prefix, strnull(k), iaai->prefixlen);
|
||||
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k);
|
||||
fprintf(f, "%sIPAddressAllow: %s\n", prefix, strnull(k));
|
||||
}
|
||||
|
||||
LIST_FOREACH(items, iaai, c->ip_address_deny) {
|
||||
SET_FOREACH(iaai, c->ip_address_deny) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
(void) in_addr_to_string(iaai->family, &iaai->address, &k);
|
||||
fprintf(f, "%sIPAddressDeny: %s/%u\n", prefix, strnull(k), iaai->prefixlen);
|
||||
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k);
|
||||
fprintf(f, "%sIPAddressDeny: %s\n", prefix, strnull(k));
|
||||
}
|
||||
|
||||
STRV_FOREACH(path, c->ip_filters_ingress)
|
||||
@ -1555,8 +1556,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
|
||||
return false;
|
||||
|
||||
if (c->ip_accounting ||
|
||||
c->ip_address_allow ||
|
||||
c->ip_address_deny ||
|
||||
!set_isempty(c->ip_address_allow) ||
|
||||
!set_isempty(c->ip_address_deny) ||
|
||||
c->ip_filters_ingress ||
|
||||
c->ip_filters_egress)
|
||||
return true;
|
||||
@ -1567,8 +1568,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
|
||||
if (!c)
|
||||
return false;
|
||||
|
||||
if (c->ip_address_allow ||
|
||||
c->ip_address_deny)
|
||||
if (!set_isempty(c->ip_address_allow) ||
|
||||
!set_isempty(c->ip_address_deny))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "cgroup-util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "list.h"
|
||||
#include "time-util.h"
|
||||
|
||||
@ -153,8 +152,12 @@ struct CGroupContext {
|
||||
bool memory_min_set:1;
|
||||
bool memory_low_set:1;
|
||||
|
||||
LIST_HEAD(IPAddressAccessItem, ip_address_allow);
|
||||
LIST_HEAD(IPAddressAccessItem, ip_address_deny);
|
||||
Set *ip_address_allow;
|
||||
Set *ip_address_deny;
|
||||
/* These two flags indicate that redundant entries have been removed from
|
||||
* ip_address_allow/ip_address_deny, i.e. in_addr_prefixes_reduce() has already been called. */
|
||||
bool ip_address_allow_reduced;
|
||||
bool ip_address_deny_reduced;
|
||||
|
||||
char **ip_filters_ingress;
|
||||
char **ip_filters_egress;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "limits-util.h"
|
||||
#include "parse-util.h"
|
||||
@ -318,14 +319,17 @@ static int property_get_ip_address_access(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
IPAddressAccessItem** items = userdata, *i;
|
||||
Set **prefixes = userdata;
|
||||
struct in_addr_prefix *i;
|
||||
int r;
|
||||
|
||||
assert(prefixes);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(iayu)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(items, i, *items) {
|
||||
SET_FOREACH(i, *prefixes) {
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'r', "iayu");
|
||||
if (r < 0)
|
||||
@ -1745,11 +1749,9 @@ int bus_cgroup_set_property(
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
|
||||
IPAddressAccessItem **list;
|
||||
_cleanup_set_free_ Set *new_prefixes = NULL;
|
||||
size_t n = 0;
|
||||
|
||||
list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(iayu)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1789,17 +1791,16 @@ int bus_cgroup_set_property(
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
IPAddressAccessItem *item;
|
||||
struct in_addr_prefix prefix = {
|
||||
.family = family,
|
||||
.prefixlen = prefixlen,
|
||||
};
|
||||
|
||||
item = new0(IPAddressAccessItem, 1);
|
||||
if (!item)
|
||||
return -ENOMEM;
|
||||
memcpy(&prefix.address, ap, an);
|
||||
|
||||
item->family = family;
|
||||
item->prefixlen = prefixlen;
|
||||
memcpy(&item->address, ap, an);
|
||||
|
||||
LIST_PREPEND(items, *list, item);
|
||||
r = in_addr_prefix_add(&new_prefixes, &prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
@ -1813,33 +1814,46 @@ int bus_cgroup_set_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*list = ip_address_access_reduce(*list);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
IPAddressAccessItem *item;
|
||||
size_t size = 0;
|
||||
|
||||
if (n == 0)
|
||||
*list = ip_address_access_free_all(*list);
|
||||
Set **prefixes;
|
||||
bool *reduced;
|
||||
|
||||
unit_invalidate_cgroup_bpf(u);
|
||||
f = open_memstream_unlocked(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
fputs(name, f);
|
||||
fputs("=\n", f);
|
||||
prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
|
||||
reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced;
|
||||
|
||||
LIST_FOREACH(items, item, *list) {
|
||||
char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
|
||||
if (n == 0) {
|
||||
*reduced = true;
|
||||
*prefixes = set_free(*prefixes);
|
||||
fputs(name, f);
|
||||
fputs("=\n", f);
|
||||
} else {
|
||||
struct in_addr_prefix *p;
|
||||
|
||||
errno = 0;
|
||||
if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
|
||||
return errno_or_else(EINVAL);
|
||||
*reduced = false;
|
||||
|
||||
fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
|
||||
r = in_addr_prefixes_merge(prefixes, new_prefixes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FOREACH(p, new_prefixes) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
|
||||
r = in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buffer);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
fprintf(f, "%s=%s\n", name, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
|
@ -1,208 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bpf-firewall.h"
|
||||
#include "extract-word.h"
|
||||
#include "hostname-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int config_parse_ip_address_access(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
IPAddressAccessItem **list = data;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(list);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*list = ip_address_access_free_all(*list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = rvalue;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ IPAddressAccessItem *a = NULL;
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
|
||||
a = new0(IPAddressAccessItem, 1);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
if (streq(word, "any")) {
|
||||
/* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
|
||||
|
||||
a->family = AF_INET;
|
||||
LIST_APPEND(items, *list, a);
|
||||
|
||||
a = new0(IPAddressAccessItem, 1);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
a->family = AF_INET6;
|
||||
|
||||
} else if (is_localhost(word)) {
|
||||
/* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
|
||||
|
||||
a->family = AF_INET;
|
||||
a->address.in.s_addr = htobe32(0x7f000000);
|
||||
a->prefixlen = 8;
|
||||
LIST_APPEND(items, *list, a);
|
||||
|
||||
a = new0(IPAddressAccessItem, 1);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
a->family = AF_INET6;
|
||||
a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
|
||||
a->prefixlen = 128;
|
||||
|
||||
} else if (streq(word, "link-local")) {
|
||||
|
||||
/* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
|
||||
|
||||
a->family = AF_INET;
|
||||
a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
|
||||
a->prefixlen = 16;
|
||||
LIST_APPEND(items, *list, a);
|
||||
|
||||
a = new0(IPAddressAccessItem, 1);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
a->family = AF_INET6;
|
||||
a->address.in6 = (struct in6_addr) {
|
||||
.s6_addr32[0] = htobe32(0xfe800000)
|
||||
};
|
||||
a->prefixlen = 64;
|
||||
|
||||
} else if (streq(word, "multicast")) {
|
||||
|
||||
/* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
|
||||
|
||||
a->family = AF_INET;
|
||||
a->address.in.s_addr = htobe32((UINT32_C(224) << 24));
|
||||
a->prefixlen = 4;
|
||||
LIST_APPEND(items, *list, a);
|
||||
|
||||
a = new0(IPAddressAccessItem, 1);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
a->family = AF_INET6;
|
||||
a->address.in6 = (struct in6_addr) {
|
||||
.s6_addr32[0] = htobe32(0xff000000)
|
||||
};
|
||||
a->prefixlen = 8;
|
||||
|
||||
} else {
|
||||
r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LIST_APPEND(items, *list, a);
|
||||
a = NULL;
|
||||
}
|
||||
|
||||
*list = ip_address_access_reduce(*list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
|
||||
IPAddressAccessItem *next, *p = first;
|
||||
|
||||
while (p) {
|
||||
next = p->items_next;
|
||||
free(p);
|
||||
|
||||
p = next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) {
|
||||
IPAddressAccessItem *a, *b, *tmp;
|
||||
int r;
|
||||
|
||||
/* Drops all entries from the list that are covered by another entry in full, thus removing all redundant
|
||||
* entries. */
|
||||
|
||||
LIST_FOREACH_SAFE(items, a, tmp, first) {
|
||||
|
||||
/* Drop irrelevant bits */
|
||||
(void) in_addr_mask(a->family, &a->address, a->prefixlen);
|
||||
|
||||
LIST_FOREACH(items, b, first) {
|
||||
|
||||
if (a == b)
|
||||
continue;
|
||||
|
||||
if (a->family != b->family)
|
||||
continue;
|
||||
|
||||
if (b->prefixlen > a->prefixlen)
|
||||
continue;
|
||||
|
||||
r = in_addr_prefix_covers(b->family,
|
||||
&b->address,
|
||||
b->prefixlen,
|
||||
&a->address);
|
||||
if (r > 0) {
|
||||
/* b covers a fully, then let's drop a */
|
||||
LIST_REMOVE(items, first, a);
|
||||
free(a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
bool ip_address_access_item_is_any(IPAddressAccessItem *first) {
|
||||
/* Check for exactly two entries */
|
||||
if (!first || !first->items_next || first->items_next->items_next)
|
||||
return false;
|
||||
|
||||
/* Check both entries cover the full range */
|
||||
if (first->prefixlen != 0 || first->items_next->prefixlen != 0)
|
||||
return false;
|
||||
|
||||
/* Check that one of them is the IPv4 and the other IPv6 */
|
||||
if (!((first->family == AF_INET && first->items_next->family == AF_INET6) ||
|
||||
(first->family == AF_INET6 && first->items_next->family == AF_INET)))
|
||||
return false;
|
||||
|
||||
/* No need to check the actual addresses, they don't matter if the prefix is zero */
|
||||
return true;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef struct IPAddressAccessItem IPAddressAccessItem;
|
||||
|
||||
struct IPAddressAccessItem {
|
||||
int family;
|
||||
unsigned char prefixlen;
|
||||
union in_addr_union address;
|
||||
LIST_FIELDS(IPAddressAccessItem, items);
|
||||
};
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access);
|
||||
|
||||
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
|
||||
|
||||
IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first);
|
||||
|
||||
/* Returns true if a list consists of only the two items necessary for "any"
|
||||
* (0.0.0.0/0 and ::/0). */
|
||||
bool ip_address_access_item_is_any(IPAddressAccessItem *first);
|
@ -221,8 +221,8 @@
|
||||
{{type}}.Delegate, config_parse_delegate, 0, offsetof({{type}}, cgroup_context)
|
||||
{{type}}.DisableControllers, config_parse_disable_controllers, 0, offsetof({{type}}, cgroup_context)
|
||||
{{type}}.IPAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.ip_accounting)
|
||||
{{type}}.IPAddressAllow, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_allow)
|
||||
{{type}}.IPAddressDeny, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_deny)
|
||||
{{type}}.IPAddressAllow, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_allow)
|
||||
{{type}}.IPAddressDeny, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_deny)
|
||||
{{type}}.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_ingress)
|
||||
{{type}}.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_egress)
|
||||
{{type}}.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof({{type}}, cgroup_context.moom_swap)
|
||||
@ -243,6 +243,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#include <stddef.h>
|
||||
#include "all-units.h"
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "load-fragment.h"
|
||||
%}
|
||||
struct ConfigPerfItem;
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "cgroup.h"
|
||||
#include "fdset.h"
|
||||
#include "hashmap.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "list.h"
|
||||
#include "prioq.h"
|
||||
#include "ratelimit.h"
|
||||
|
@ -71,8 +71,6 @@ libcore_sources = '''
|
||||
generator-setup.h
|
||||
ima-setup.c
|
||||
ima-setup.h
|
||||
ip-address-access.c
|
||||
ip-address-access.h
|
||||
job.c
|
||||
job.h
|
||||
kill.c
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "bpf-firewall.h"
|
||||
#include "bpf-program.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "manager.h"
|
||||
#include "memory-util.h"
|
||||
@ -106,21 +107,39 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
cc->ip_accounting = true;
|
||||
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0);
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0);
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0);
|
||||
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0);
|
||||
|
||||
assert(cc->ip_address_allow);
|
||||
assert(cc->ip_address_allow->items_next);
|
||||
assert(!cc->ip_address_allow->items_next->items_next);
|
||||
assert_se(set_size(cc->ip_address_allow) == 2);
|
||||
assert_se(set_size(cc->ip_address_deny) == 4);
|
||||
|
||||
/* The deny list is defined redundantly, let's ensure it got properly reduced */
|
||||
assert(cc->ip_address_deny);
|
||||
assert(cc->ip_address_deny->items_next);
|
||||
assert(!cc->ip_address_deny->items_next->items_next);
|
||||
/* The deny list is defined redundantly, let's ensure it will be properly reduced */
|
||||
assert_se(in_addr_prefixes_reduce(cc->ip_address_allow) >= 0);
|
||||
assert_se(in_addr_prefixes_reduce(cc->ip_address_deny) >= 0);
|
||||
|
||||
assert_se(set_size(cc->ip_address_allow) == 2);
|
||||
assert_se(set_size(cc->ip_address_deny) == 2);
|
||||
|
||||
assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) {
|
||||
.family = AF_INET,
|
||||
.address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(1) << 8)),
|
||||
.prefixlen = 24 }));
|
||||
assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) {
|
||||
.family = AF_INET,
|
||||
.address.in.s_addr = htobe32(0x7f000002),
|
||||
.prefixlen = 32 }));
|
||||
assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) {
|
||||
.family = AF_INET,
|
||||
.address.in.s_addr = htobe32(0x7f000000),
|
||||
.prefixlen = 25 }));
|
||||
assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) {
|
||||
.family = AF_INET,
|
||||
.address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(3) << 8)),
|
||||
.prefixlen = 24 }));
|
||||
|
||||
assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.2 -W 5", SERVICE(u)->exec_command, u) == 0);
|
||||
assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.3 -W 5", SERVICE(u)->exec_command, u) == 0);
|
||||
|
Loading…
Reference in New Issue
Block a user