1
0
mirror of https://github.com/systemd/systemd synced 2025-09-27 15:54:47 +02:00

Compare commits

..

No commits in common. "6597686865ffcba7450b44814618b94321cfa3cf" and "6bfbfce795e42c758e3ffc4d744c8b2a9a1da2b5" have entirely different histories.

18 changed files with 148 additions and 218 deletions

4
TODO
View File

@ -135,6 +135,10 @@ Features:
o move into separate libsystemd-shared-iptables.so .so
- iptables-libs (only used by nspawn + networkd)
* seccomp: when SystemCallArchitectures=native is set then don't install any
other seccomp filters for any of the other archs, in order to reduce the
number of seccomp filters we install needlessly.
* seccomp: maybe use seccomp_merge() to merge our filters per-arch if we can.
Apparently kernel performance is much better with fewer larger seccomp
filters than with more smaller seccomp filters.

View File

@ -751,7 +751,7 @@ static int journal_file_move_to(
return -EADDRNOTAVAIL;
}
return mmap_cache_get(f->mmap, f->cache_fd, type_to_context(type), keep_always, offset, size, &f->last_stat, ret, ret_size);
return mmap_cache_get(f->mmap, f->cache_fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret, ret_size);
}
static uint64_t minimum_header_size(Object *o) {
@ -3365,6 +3365,7 @@ int journal_file_open(
.mode = mode,
.flags = flags,
.prot = prot_from_flags(flags),
.writable = (flags & O_ACCMODE) != O_RDONLY,
#if HAVE_ZSTD
@ -3463,7 +3464,7 @@ int journal_file_open(
goto fail;
}
f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd, prot_from_flags(flags));
f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd);
if (!f->cache_fd) {
r = -ENOMEM;
goto fail;
@ -3510,7 +3511,7 @@ int journal_file_open(
goto fail;
}
r = mmap_cache_get(f->mmap, f->cache_fd, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, NULL);
r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, NULL);
if (r == -EINVAL) {
/* Some file systems (jffs2 or p9fs) don't support mmap() properly (or only read-only
* mmap()), and return EINVAL in that case. Let's propagate that as a more recognizable error

View File

@ -63,6 +63,7 @@ typedef struct JournalFile {
mode_t mode;
int flags;
int prot;
bool writable:1;
bool compress_xz:1;
bool compress_lz4:1;

View File

@ -377,7 +377,7 @@ static int contains_uint64(MMapCache *m, MMapFileDescriptor *f, uint64_t n, uint
c = (a + b) / 2;
r = mmap_cache_get(m, f, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL);
r = mmap_cache_get(m, f, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL);
if (r < 0)
return r;
@ -862,19 +862,19 @@ int journal_file_verify(
goto fail;
}
cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd, PROT_READ|PROT_WRITE);
cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd);
if (!cache_data_fd) {
r = log_oom();
goto fail;
}
cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd, PROT_READ|PROT_WRITE);
cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd);
if (!cache_entry_fd) {
r = log_oom();
goto fail;
}
cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd, PROT_READ|PROT_WRITE);
cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd);
if (!cache_entry_array_fd) {
r = log_oom();
goto fail;

View File

@ -25,6 +25,7 @@ struct Window {
bool keep_always:1;
bool in_unused:1;
int prot;
void *ptr;
uint64_t offset;
size_t size;
@ -48,7 +49,6 @@ struct Context {
struct MMapFileDescriptor {
MMapCache *cache;
int fd;
int prot;
bool sigbus;
LIST_HEAD(Window, windows);
};
@ -57,7 +57,7 @@ struct MMapCache {
unsigned n_ref;
unsigned n_windows;
unsigned n_context_cache_hit, n_window_list_hit, n_missed;
unsigned n_hit, n_missed;
Hashmap *fds;
Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
@ -112,7 +112,6 @@ static void window_unlink(Window *w) {
static void window_invalidate(Window *w) {
assert(w);
assert(w->fd);
if (w->invalidated)
return;
@ -122,7 +121,7 @@ static void window_invalidate(Window *w) {
* trigger any further SIGBUS, possibly overrunning the sigbus
* queue. */
assert_se(mmap(w->ptr, w->size, w->fd->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr);
assert_se(mmap(w->ptr, w->size, w->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr);
w->invalidated = true;
}
@ -134,25 +133,27 @@ static void window_free(Window *w) {
free(w);
}
_pure_ static bool window_matches(Window *w, uint64_t offset, size_t size) {
_pure_ static bool window_matches(Window *w, int prot, uint64_t offset, size_t size) {
assert(w);
assert(size > 0);
return
prot == w->prot &&
offset >= w->offset &&
offset + size <= w->offset + w->size;
}
_pure_ static bool window_matches_fd(Window *w, MMapFileDescriptor *f, uint64_t offset, size_t size) {
_pure_ static bool window_matches_fd(Window *w, MMapFileDescriptor *f, int prot, uint64_t offset, size_t size) {
assert(w);
assert(f);
return
w->fd == f &&
window_matches(w, offset, size);
w->fd &&
f->fd == w->fd->fd &&
window_matches(w, prot, offset, size);
}
static Window *window_add(MMapCache *m, MMapFileDescriptor *f, bool keep_always, uint64_t offset, size_t size, void *ptr) {
static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) {
Window *w;
assert(m);
@ -175,6 +176,7 @@ static Window *window_add(MMapCache *m, MMapFileDescriptor *f, bool keep_always,
*w = (Window) {
.cache = m,
.fd = f,
.prot = prot,
.keep_always = keep_always,
.offset = offset,
.size = size,
@ -302,6 +304,7 @@ static int make_room(MMapCache *m) {
static int try_context(
MMapCache *m,
MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
@ -326,7 +329,7 @@ static int try_context(
if (!c->window)
return 0;
if (!window_matches_fd(c->window, f, offset, size)) {
if (!window_matches_fd(c->window, f, prot, offset, size)) {
/* Drop the reference to the window, since it's unnecessary now */
context_detach_window(c);
@ -348,6 +351,7 @@ static int try_context(
static int find_mmap(
MMapCache *m,
MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
@ -367,7 +371,7 @@ static int find_mmap(
return -EIO;
LIST_FOREACH(by_fd, w, f->windows)
if (window_matches(w, offset, size))
if (window_matches(w, prot, offset, size))
break;
if (!w)
@ -387,7 +391,7 @@ static int find_mmap(
return 1;
}
static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int flags, uint64_t offset, size_t size, void **res) {
static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int prot, int flags, uint64_t offset, size_t size, void **res) {
void *ptr;
assert(m);
@ -397,7 +401,7 @@ static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int
for (;;) {
int r;
ptr = mmap(addr, size, f->prot, flags, f->fd, offset);
ptr = mmap(addr, size, prot, flags, f->fd, offset);
if (ptr != MAP_FAILED)
break;
if (errno != ENOMEM)
@ -417,6 +421,7 @@ static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int
static int add_mmap(
MMapCache *m,
MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
@ -466,7 +471,7 @@ static int add_mmap(
wsize = PAGE_ALIGN(st->st_size - woffset);
}
r = mmap_try_harder(m, NULL, f, MAP_SHARED, woffset, wsize, &d);
r = mmap_try_harder(m, NULL, f, prot, MAP_SHARED, woffset, wsize, &d);
if (r < 0)
return r;
@ -474,7 +479,7 @@ static int add_mmap(
if (!c)
goto outofmem;
w = window_add(m, f, keep_always, woffset, wsize, d);
w = window_add(m, f, prot, keep_always, woffset, wsize, d);
if (!w)
goto outofmem;
@ -494,6 +499,7 @@ outofmem:
int mmap_cache_get(
MMapCache *m,
MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
@ -512,29 +518,29 @@ int mmap_cache_get(
assert(context < MMAP_CACHE_MAX_CONTEXTS);
/* Check whether the current context is the right one already */
r = try_context(m, f, context, keep_always, offset, size, ret, ret_size);
r = try_context(m, f, prot, context, keep_always, offset, size, ret, ret_size);
if (r != 0) {
m->n_context_cache_hit++;
m->n_hit++;
return r;
}
/* Search for a matching mmap */
r = find_mmap(m, f, context, keep_always, offset, size, ret, ret_size);
r = find_mmap(m, f, prot, context, keep_always, offset, size, ret, ret_size);
if (r != 0) {
m->n_window_list_hit++;
m->n_hit++;
return r;
}
m->n_missed++;
/* Create a new mmap */
return add_mmap(m, f, context, keep_always, offset, size, st, ret, ret_size);
return add_mmap(m, f, prot, context, keep_always, offset, size, st, ret, ret_size);
}
void mmap_cache_stats_log_debug(MMapCache *m) {
assert(m);
log_debug("mmap cache statistics: %u context cache hit, %u window list hit, %u miss", m->n_context_cache_hit, m->n_window_list_hit, m->n_missed);
log_debug("mmap cache statistics: %u hit, %u miss", m->n_hit, m->n_missed);
}
static void mmap_cache_process_sigbus(MMapCache *m) {
@ -608,7 +614,7 @@ bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f) {
return f->sigbus;
}
MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd, int prot) {
MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd) {
MMapFileDescriptor *f;
int r;
@ -629,7 +635,6 @@ MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd, int prot) {
f->cache = m;
f->fd = fd;
f->prot = prot;
r = hashmap_put(m->fds, FD_TO_PTR(fd), f);
if (r < 0)

View File

@ -17,6 +17,7 @@ MMapCache* mmap_cache_unref(MMapCache *m);
int mmap_cache_get(
MMapCache *m,
MMapFileDescriptor *f,
int prot,
unsigned context,
bool keep_always,
uint64_t offset,
@ -24,7 +25,7 @@ int mmap_cache_get(
struct stat *st,
void **ret,
size_t *ret_size);
MMapFileDescriptor * mmap_cache_add_fd(MMapCache *m, int fd, int prot);
MMapFileDescriptor * mmap_cache_add_fd(MMapCache *m, int fd);
void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f);
void mmap_cache_stats_log_debug(MMapCache *m);

View File

@ -24,7 +24,7 @@ int main(int argc, char *argv[]) {
assert_se(x >= 0);
unlink(px);
assert_se(fx = mmap_cache_add_fd(m, x, PROT_READ));
assert_se(fx = mmap_cache_add_fd(m, x));
y = mkostemp_safe(py);
assert_se(y >= 0);
@ -34,23 +34,23 @@ int main(int argc, char *argv[]) {
assert_se(z >= 0);
unlink(pz);
r = mmap_cache_get(m, fx, 0, false, 1, 2, NULL, &p, NULL);
r = mmap_cache_get(m, fx, PROT_READ, 0, false, 1, 2, NULL, &p, NULL);
assert_se(r >= 0);
r = mmap_cache_get(m, fx, 0, false, 2, 2, NULL, &q, NULL);
r = mmap_cache_get(m, fx, PROT_READ, 0, false, 2, 2, NULL, &q, NULL);
assert_se(r >= 0);
assert_se((uint8_t*) p + 1 == (uint8_t*) q);
r = mmap_cache_get(m, fx, 1, false, 3, 2, NULL, &q, NULL);
r = mmap_cache_get(m, fx, PROT_READ, 1, false, 3, 2, NULL, &q, NULL);
assert_se(r >= 0);
assert_se((uint8_t*) p + 2 == (uint8_t*) q);
r = mmap_cache_get(m, fx, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p, NULL);
r = mmap_cache_get(m, fx, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p, NULL);
assert_se(r >= 0);
r = mmap_cache_get(m, fx, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q, NULL);
r = mmap_cache_get(m, fx, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q, NULL);
assert_se(r >= 0);
assert_se((uint8_t*) p + 1 == (uint8_t*) q);

View File

@ -153,40 +153,26 @@ static bool address_may_have_broadcast(const Address *a) {
return a->family == AF_INET && in4_addr_is_null(&a->in_addr_peer.in) && a->prefixlen <= 30;
}
static uint32_t address_prefix(const Address *a) {
assert(a);
/* make sure we don't try to shift by 32.
* See ISO/IEC 9899:TC3 § 6.5.7.3. */
if (a->prefixlen == 0)
return 0;
if (a->in_addr_peer.in.s_addr != 0)
return be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
else
return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
}
void address_hash_func(const Address *a, struct siphash *state) {
assert(a);
siphash24_compress(&a->family, sizeof(a->family), state);
switch (a->family) {
case AF_INET:
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
if (!IN_SET(a->family, AF_INET, AF_INET6))
/* treat non-IPv4 or IPv6 address family as AF_UNSPEC */
return;
uint32_t prefix = address_prefix(a);
siphash24_compress(&prefix, sizeof(prefix), state);
if (a->family == AF_INET)
siphash24_compress_string(a->label, state);
_fallthrough_;
case AF_INET6:
siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
break;
default:
/* treat any other address family as AF_UNSPEC */
break;
}
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
/* local address */
siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
/* peer address */
siphash24_compress(&a->in_addr_peer, FAMILY_ADDRESS_SIZE(a->family), state);
if (address_may_have_broadcast(a))
siphash24_compress(&a->broadcast, sizeof(a->broadcast), state);
}
int address_compare_func(const Address *a1, const Address *a2) {
@ -196,25 +182,32 @@ int address_compare_func(const Address *a1, const Address *a2) {
if (r != 0)
return r;
switch (a1->family) {
case AF_INET:
/* See kernel's find_matching_ifa() in net/ipv4/devinet.c */
r = CMP(a1->prefixlen, a2->prefixlen);
if (r != 0)
return r;
r = CMP(address_prefix(a1), address_prefix(a2));
if (r != 0)
return r;
_fallthrough_;
case AF_INET6:
/* See kernel's ipv6_get_ifaddr() in net/ipv6/addrconf.c */
return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
default:
/* treat any other address family as AF_UNSPEC */
if (!IN_SET(a1->family, AF_INET, AF_INET6))
/* treat non-IPv4 or IPv6 address family as AF_UNSPEC */
return 0;
if (a1->family == AF_INET) {
r = strcmp_ptr(a1->label, a2->label);
if (r != 0)
return r;
}
r = CMP(a1->prefixlen, a2->prefixlen);
if (r != 0)
return r;
r = memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
if (r != 0)
return r;
r = memcmp(&a1->in_addr_peer, &a2->in_addr_peer, FAMILY_ADDRESS_SIZE(a1->family));
if (r != 0)
return r;
if (address_may_have_broadcast(a1))
return CMP(a1->broadcast.s_addr, a2->broadcast.s_addr);
return 0;
}
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
@ -447,23 +440,29 @@ int address_get(Link *link, const Address *in, Address **ret) {
return -ENOENT;
}
int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
_cleanup_(address_freep) Address *a = NULL;
int r;
static bool address_exists_internal(Set *addresses, int family, const union in_addr_union *in_addr) {
Address *address;
SET_FOREACH(address, addresses) {
if (address->family != family)
continue;
if (in_addr_equal(address->family, &address->in_addr, in_addr))
return true;
}
return false;
}
bool address_exists(Link *link, int family, const union in_addr_union *in_addr) {
assert(link);
assert(address);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(in_addr);
r = address_new(&a);
if (r < 0)
return r;
/* address_compare_func() only compares the local address for IPv6 case. So, it is enough to
* set only family and the address. */
a->family = AF_INET6;
a->in_addr.in6 = *address;
return address_get(link, a, NULL) >= 0;
if (address_exists_internal(link->addresses, family, in_addr))
return true;
if (address_exists_internal(link->addresses_foreign, family, in_addr))
return true;
return false;
}
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {

View File

@ -49,6 +49,7 @@ typedef struct Address {
int address_new(Address **ret);
Address *address_free(Address *address);
int address_get(Link *link, const Address *in, Address **ret);
bool address_exists(Link *link, int family, const union in_addr_union *in_addr);
int address_configure(const Address *address, Link *link, link_netlink_message_handler_t callback, bool update, Address **ret);
int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback);
bool address_equal(const Address *a1, const Address *a2);
@ -62,7 +63,6 @@ int link_set_addresses(Link *link);
int link_drop_addresses(Link *link);
int link_drop_foreign_addresses(Link *link);
bool link_address_is_dynamic(const Link *link, const Address *address);
int link_has_ipv6_address(Link *link, const struct in6_addr *address);
void ipv4_dad_unref(Link *link);
int ipv4_dad_stop(Link *link);

View File

@ -969,70 +969,6 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1;
}
static void log_dhcp6_address(Link *link, const Address *address, char **ret) {
char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL, *preferred_str = NULL;
_cleanup_free_ char *buffer = NULL;
bool by_ndisc = false;
Address *existing;
NDiscAddress *na;
int log_level, r;
assert(link);
assert(address);
(void) in_addr_to_string(address->family, &address->in_addr, &buffer);
if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
address->cinfo.ifa_valid * USEC_PER_SEC,
USEC_PER_SEC);
if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME)
preferred_str = format_timespan(preferred_buf, FORMAT_TIMESPAN_MAX,
address->cinfo.ifa_prefered * USEC_PER_SEC,
USEC_PER_SEC);
r = address_get(link, address, &existing);
if (r < 0) {
/* New address. */
log_level = LOG_INFO;
goto simple_log;
} else
log_level = LOG_DEBUG;
if (set_contains(link->dhcp6_addresses, address))
/* Already warned. */
goto simple_log;
if (address->prefixlen == existing->prefixlen)
/* Currently, only conflict in prefix length is reported. */
goto simple_log;
SET_FOREACH(na, link->ndisc_addresses)
if (address_compare_func(na->address, existing)) {
by_ndisc = true;
break;
}
log_link_warning(link, "DHCPv6 address %s/%u (valid %s%s, preferred %s%s) conflicts the existing address %s/%u%s.",
strnull(buffer), address->prefixlen,
valid_str ? "for " : "forever", strempty(valid_str),
preferred_str ? "for " : "forever", strempty(preferred_str),
strnull(buffer), existing->prefixlen,
by_ndisc ? "assigned by NDISC. Please try to use or update IPv6Token= setting "
"to change the address generated by NDISC, or disable UseAutonomousPrefix=" : "");
goto finalize;
simple_log:
log_link_full(link, log_level, "DHCPv6 address %s/%u (valid %s%s, preferred %s%s)",
strnull(buffer), address->prefixlen,
valid_str ? "for " : "forever", strempty(valid_str),
preferred_str ? "for " : "forever", strempty(preferred_str));
finalize:
if (ret)
*ret = TAKE_PTR(buffer);
}
static int dhcp6_update_address(
Link *link,
const struct in6_addr *ip6_addr,
@ -1055,19 +991,22 @@ static int dhcp6_update_address(
addr->cinfo.ifa_prefered = lifetime_preferred;
addr->cinfo.ifa_valid = lifetime_valid;
log_dhcp6_address(link, addr, &buffer);
(void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
log_link_full(link, set_contains(link->dhcp6_addresses, addr) ? LOG_DEBUG : LOG_INFO,
"DHCPv6 address %s/%u timeout preferred %d valid %d",
strna(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);
r = address_configure(addr, link, dhcp6_address_handler, true, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 address %s/%u: %m",
strnull(buffer), addr->prefixlen);
strna(buffer), addr->prefixlen);
link->dhcp6_address_messages++;
r = set_ensure_put(&link->dhcp6_addresses, &address_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 address %s/%u: %m",
strnull(buffer), addr->prefixlen);
strna(buffer), addr->prefixlen);
(void) set_remove(link->dhcp6_addresses_old, ret);

View File

@ -888,17 +888,13 @@ void manager_free(Manager *m) {
m->rules_foreign = set_free(m->rules_foreign);
set_free(m->rules_saved);
m->routes = set_free(m->routes);
m->routes_foreign = set_free(m->routes_foreign);
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
sd_resolve_unref(m->resolve);
/* reject (e.g. unreachable) type routes are managed by Manager, but may be referenced by a
* link. E.g., DHCP6 with prefix delegation creates unreachable routes, and they are referenced
* by the upstream link. And the links may be referenced by netlink slots. Hence, two
* set_free() must be called after the above sd_netlink_unref(). */
m->routes = set_free(m->routes);
m->routes_foreign = set_free(m->routes_foreign);
sd_event_source_unref(m->speed_meter_event_source);
sd_event_unref(m->event);

View File

@ -483,7 +483,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
if (r < 0)
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
if (link_has_ipv6_address(link, &gateway.in6) > 0) {
if (address_exists(link, AF_INET6, &gateway)) {
if (DEBUG_LOGGING) {
_cleanup_free_ char *buffer = NULL;

View File

@ -159,8 +159,10 @@ static void test_address_equality(void) {
assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a2->in_addr) >= 0);
assert_se(address_equal(a1, a2));
assert_se(in_addr_from_string(AF_INET, "192.168.3.10", &a1->in_addr_peer) >= 0);
assert_se(address_equal(a1, a2));
assert_se(!address_equal(a1, a2));
assert_se(in_addr_from_string(AF_INET, "192.168.3.11", &a2->in_addr_peer) >= 0);
assert_se(!address_equal(a1, a2));
a2->in_addr_peer = a1->in_addr_peer;
assert_se(address_equal(a1, a2));
a1->prefixlen = 10;
assert_se(!address_equal(a1, a2));
@ -171,10 +173,13 @@ static void test_address_equality(void) {
assert_se(!address_equal(a1, a2));
a2->family = AF_INET6;
a1->in_addr_peer = a2->in_addr_peer = IN_ADDR_NULL;
assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr) >= 0);
assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr) >= 0);
assert_se(address_equal(a1, a2));
a1->prefixlen = 8;
assert_se(!address_equal(a1, a2));
a2->prefixlen = 8;
assert_se(address_equal(a1, a2));

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.0-or-later */
/* SPDX-License-Identifier: LGPL-2+ */
/*
* initreq.h Interface to talk to init through /dev/initctl.
*

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <netinet/ether.h>

View File

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <linux/nl80211.h>

View File

@ -23,8 +23,7 @@
#include "string-util.h"
#include "strv.h"
/* This array will be modified at runtime as seccomp_restrict_archs is called. */
uint32_t seccomp_local_archs[] = {
const uint32_t seccomp_local_archs[] = {
/* Note: always list the native arch we are compiled as last, so that users can deny-list seccomp(), but our own calls to it still succeed */
@ -95,7 +94,7 @@ uint32_t seccomp_local_archs[] = {
#elif defined(__s390__)
SCMP_ARCH_S390,
#endif
SECCOMP_LOCAL_ARCH_END
(uint32_t) -1
};
const char* seccomp_arch_to_string(uint32_t c) {
@ -1759,8 +1758,8 @@ int seccomp_memory_deny_write_execute(void) {
int seccomp_restrict_archs(Set *archs) {
_cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
void *id;
int r;
bool blocked_new = false;
/* This installs a filter with no rules, but that restricts the system call architectures to the specified
* list.
@ -1776,36 +1775,24 @@ int seccomp_restrict_archs(Set *archs) {
if (!seccomp)
return -ENOMEM;
for (unsigned i = 0; seccomp_local_archs[i] != SECCOMP_LOCAL_ARCH_END; ++i) {
uint32_t arch = seccomp_local_archs[i];
/* That architecture might have already been blocked by a previous call to seccomp_restrict_archs. */
if (arch == SECCOMP_LOCAL_ARCH_BLOCKED)
continue;
bool block = !set_contains(archs, UINT32_TO_PTR(arch + 1));
/* The vdso for x32 assumes that x86-64 syscalls are available. Let's allow them, since x32
* x32 syscalls should basically match x86-64 for everything except the pointer type.
* The important thing is that you can block the old 32-bit x86 syscalls.
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850047 */
if (block && arch == SCMP_ARCH_X86_64 && seccomp_arch_native() == SCMP_ARCH_X32)
block = !set_contains(archs, UINT32_TO_PTR(SCMP_ARCH_X32 + 1));
if (block) {
seccomp_local_archs[i] = SECCOMP_LOCAL_ARCH_BLOCKED;
blocked_new = true;
} else {
r = seccomp_arch_add(seccomp, arch);
if (r < 0 && r != -EEXIST)
return r;
}
SET_FOREACH(id, archs) {
r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
if (r < 0 && r != -EEXIST)
return r;
}
/* All architectures that will be blocked by the seccomp program were
* already blocked. */
if (!blocked_new)
return 0;
/* The vdso for x32 assumes that x86-64 syscalls are available. Let's allow them, since x32
* x32 syscalls should basically match x86-64 for everything except the pointer type.
* The important thing is that you can block the old 32-bit x86 syscalls.
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850047 */
if (seccomp_arch_native() == SCMP_ARCH_X32 ||
set_contains(archs, UINT32_TO_PTR(SCMP_ARCH_X32 + 1))) {
r = seccomp_arch_add(seccomp, SCMP_ARCH_X86_64);
if (r < 0 && r != -EEXIST)
return r;
}
r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
if (r < 0)

View File

@ -100,20 +100,12 @@ int seccomp_lock_personality(unsigned long personality);
int seccomp_protect_hostname(void);
int seccomp_restrict_suid_sgid(void);
extern uint32_t seccomp_local_archs[];
#define SECCOMP_LOCAL_ARCH_END UINT32_MAX
/* Note: 0 is safe to use here because although SCMP_ARCH_NATIVE is 0, it would
* never be in the seccomp_local_archs array anyway so we can use it as a
* marker. */
#define SECCOMP_LOCAL_ARCH_BLOCKED 0
extern const uint32_t seccomp_local_archs[];
#define SECCOMP_FOREACH_LOCAL_ARCH(arch) \
for (unsigned _i = ({ (arch) = seccomp_local_archs[0]; 0; }); \
(arch) != SECCOMP_LOCAL_ARCH_END; \
(arch) = seccomp_local_archs[++_i]) \
if ((arch) != SECCOMP_LOCAL_ARCH_BLOCKED)
seccomp_local_archs[_i] != (uint32_t) -1; \
(arch) = seccomp_local_archs[++_i])
/* EACCES: does not have the CAP_SYS_ADMIN or no_new_privs == 1
* ENOMEM: out of memory, failed to allocate space for a libseccomp structure, or would exceed a defined constant