1
0
mirror of https://github.com/systemd/systemd synced 2025-10-01 09:44:46 +02:00

Compare commits

...

53 Commits

Author SHA1 Message Date
Lennart Poettering
b1b4e9204c
Merge pull request #18007 from fw-strlen/ipv6_masq_and_dnat
Support ipv6 for masquerade and dnat in nspawn and networkd
2021-02-16 23:41:35 +01:00
Vito Caputo
bb1296b55a journal-file: fix archiving offline journals
The existing set_offline() short-circuit erroneously included
when f->archive was true and header->state was STATE_OFFLINE.

This commit makes the short-circuit f->archive aware, so it will
only catch scenarios where there's not an offlining in progress
and the header state matches the target state of either archived
or offline.

Fixes https://github.com/systemd/systemd/issues/17770
2021-02-16 23:09:41 +01:00
Lennart Poettering
356b7a58f3
Merge pull request #18601 from keszybz/env-assign-cleanup
Envvar assignment cleanup
2021-02-16 22:36:48 +01:00
Yu Watanabe
3b4e3ebb51 netlink: introduce sd_netlink_message_has_flag() 2021-02-16 22:36:24 +01:00
Lennart Poettering
0a5393ad68
Merge pull request #18631 from yuwata/sd-netlink-fix-assertions
sd-netlink: update assertions and drop unused functions
2021-02-16 22:36:06 +01:00
Zbigniew Jędrzejewski-Szmek
9a9ca40803 systemd: don't try to run as user manager when called without any arguments
It's better for users if programs don't do "significant" things too easily, and
should be especially conservative when called without any arguments whatsoever.
So far systemd would would try to launch itself as a user manager and fail on
some cgroup permission stuff. systemd --user is run execlusively from user@.service
and there we call it with --user. Calls to the binary without any arguments as
non-pid1 are almost always a mistake.

https://github.com/systemd/systemd/issues/18419#issuecomment-779422571
2021-02-16 22:35:49 +01:00
Lennart Poettering
696e5a8a73 man: make clear that sd-journal notifications always come with extra latency
Replaces: #17699
2021-02-16 22:16:17 +01:00
Lennart Poettering
a9a43d8aa2
Merge pull request #18636 from poettering/resolved-different-server
resolved: tweaks for switching to different DNS servers
2021-02-16 20:27:09 +01:00
Lennart Poettering
23220d8a00
Merge pull request #18620 from bluca/mount_images_fixes
MountImages and core tmpfs fixes
2021-02-16 20:26:06 +01:00
Lennart Poettering
0addd9ba9c
Merge pull request #18616 from keszybz/argv-fuzzer-quick-fix
fuzz-systemctl-parse-argv: avoid "leak" of bus object
2021-02-16 20:25:37 +01:00
Joshua Watt
7820a56ccb logind: Restore chvt as non-root user without polkit
4acf0cfd2f ("logind: check PolicyKit before allowing VT switch") broke
the ability to write user sessions that run graphical sessions (e.g.
weston/X11). This was partially amended in 19bb87fbfa ("login: allow
non-console sessions to change vt") by changing the default PolicyKit
policy so that non-root users with a session are again allowed to switch
the VT. This makes the policy when PolKit is not enabled (as on many
embedded systems) closer the default PolKit policy and allows launching
graphical sessions as a non-root user.

Closes #17473

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
2021-02-16 20:24:53 +01:00
Luca Boccassi
b8f762f2fe stat-util: fix dir_is_empty_at without path
Use the right FD, and do a fd_reopen instead of a dup, since the
latter will still share the internal pointer which then gets
moved by FOREACH_DIRENT, affecting the caller's FD.
2021-02-16 20:24:27 +01:00
Lennart Poettering
42b23010b9
Merge pull request #18624 from poettering/resolved-feature-level-tweak
resolved: three tweaks to server feature level tracking
2021-02-16 20:24:05 +01:00
Yu Watanabe
955b11ffd3
Merge pull request #18629 from yuwata/sd-netlink-nexthop-types
sd-netlink: add nexthop related types
2021-02-17 04:06:15 +09:00
Lennart Poettering
9147b591a1 resolved: unify code for trying a different DNS server
Let's unify some code, and add a common implementation of a function
that checks whether we have tried all DNS servers yet, and retries the
transaction if we don't. We already use this same code twice. Let's use
it at some other places too now — basically all cases where we switch to
a new server — with the one case of packet loss, where we too switch
servers, but don#t care how many times we already tried to switch.
2021-02-16 18:54:33 +01:00
Lennart Poettering
7ef863a76a resolved: improve log message when retrying a transaction with a different server 2021-02-16 18:53:33 +01:00
Lennart Poettering
fba3e94df5 resolved: never go below DNSSEC feature level in DNSSEC strict mode
This adjusts our feature level handling: when DNSSEC strict mode is on,
let's never lower the feature level below the lowest DNSSEC mode.

Also, when asking whether DNSSEC is supproted, always say yes in strict
mode. This means that error reporting about transactions that fail
because of missing DNSSEC RRs will not report "incompatible-server" but
instead "missing-signature" or suchlike.

The main difference here is that DNSSEC failures become local to a
transaction, instead of propagating into the feature level we reuse for
future transactions. This is beneficial with routers that implement
"mostly a DNS proxy", i.e. that propagate most DNS requests 1:1 to their
upstream servers, but synthesize local answers for a select few domains.
For example, AVM Fritz!Boxes operate that way: they proxy most traffic
1:1 upstream in an DNSSEC-compatible fashion, but synthesize the
"fritz.box" locally, so that it can be used to configure the router.
This local domain cannot be DNSSEC verified, it comes without
signatures. Previously this would mean once that domain was resolved
feature level would be downgraded, and we'd thus fail all future DNSSEC
attempts. With this change, the immediate lookup for "fritz.box" will
fail validation, but for all other unrelated future ones that comes
without prejudice.

(While we are at it, also make a couple of other downgrade paths a bit
tighter.)

Fixes: #10570 #14435 #6490
2021-02-16 18:44:01 +01:00
Lennart Poettering
d8592a4e2f resolved: make feature level checks a bit more discriptive
The levels have an order, but the order is sometimes a bit arbitrary.
Hence add simple macros to check for specific features and use those, so
that the ordering leaks a bit less into all files.
2021-02-16 18:41:08 +01:00
Lennart Poettering
2c42a217a2 resolved: when we can't parse a packet, downgrade feature level
So far we didn't really handle the case where we can't parse a reply
packet. Since this apparently happens in real-life though, let's add
some minimal logic, to downgrade/restart if we see this.
2021-02-16 18:41:08 +01:00
Yu Watanabe
8900c05e6e netlink: drop sd_rtnl_message_{route,nexthop}_set_family()
The family is already set when the message is created.
2021-02-17 02:06:26 +09:00
Yu Watanabe
fc80ed5f97 network: drop unnecessary family setting
It is already set in sd_rtnl_message_new_nexthop().
2021-02-17 02:06:26 +09:00
Yu Watanabe
735a3d73b7 netlink: fix assertions 2021-02-17 01:21:03 +09:00
Yu Watanabe
4684ec5e3d netlink: add nexthop related types 2021-02-17 01:16:42 +09:00
Yu Watanabe
f5b7deb969 sd-netlink: add RTA_NH_ID attribute support 2021-02-17 01:16:10 +09:00
Zbigniew Jędrzejewski-Szmek
15567b3a73 Rename unit_times_free to unit_times_free_array
It frees the whole array and the type is UnitTimes not UnitTime.
2021-02-16 17:15:11 +01:00
Zbigniew Jędrzejewski-Szmek
cfb1a0e555 Rename strbuf_cleanup to strbuf_free
It frees the whole object.
2021-02-16 17:15:11 +01:00
Zbigniew Jędrzejewski-Szmek
425ac7a253 fuzz-systemctl-parse-argv: call static destuctors
With all the preparatory work in previous PRs, we can now call static destructors
repeatedly without issue. We need to do it here so that global variables allocated
during parsing are properly freed.
2021-02-16 17:15:11 +01:00
Zbigniew Jędrzejewski-Szmek
36556f6e51 systemctl: use free_and_replace on global variable
In normal usage we cannot set it multiple times, but from a fuzzer we
may. Doing it this way is nicer anyway.
2021-02-16 17:15:11 +01:00
Zbigniew Jędrzejewski-Szmek
fd421c4adc tree-wide: reset the cleaned-up variable in cleanup functions
If the cleanup function returns the appropriate type, use that to reset the
variable. For other functions (usually the foreign ones which return void), add
an explicit value to reset to.

This causes a bit of code churn, but I think it might be worth it. In a
following patch static destructors will be called from a fuzzer, and this
change allows them to be called multiple times. But I think such a change might
help with detecting unitialized code reuse too. We hit various bugs like this,
and things are more obvious when a pointer has been set to NULL.

I was worried whether this change increases text size, but it doesn't seem to:

-Dbuildtype=debug:
before "tree-wide: return NULL from freeing functions":
-rwxrwxr-x 1 zbyszek zbyszek 4117672 Feb 16 14:36 build/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 4494520 Feb 16 15:06 build/systemd*
after "tree-wide: return NULL from freeing functions":
-rwxrwxr-x 1 zbyszek zbyszek 4117672 Feb 16 14:36 build/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 4494576 Feb 16 15:10 build/systemd*
now:
-rwxrwxr-x 1 zbyszek zbyszek 4117672 Feb 16 14:36 build/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 4494640 Feb 16 15:15 build/systemd*

-Dbuildtype=release:
before "tree-wide: return NULL from freeing functions":
-rwxrwxr-x 1 zbyszek zbyszek 5252256 Feb 14 14:47 build-rawhide/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 1834184 Feb 16 15:09 build-rawhide/systemd*
after "tree-wide: return NULL from freeing functions":
-rwxrwxr-x 1 zbyszek zbyszek 5252256 Feb 14 14:47 build-rawhide/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 1834184 Feb 16 15:10 build-rawhide/systemd*
now:
-rwxrwxr-x 1 zbyszek zbyszek 5252256 Feb 14 14:47 build-rawhide/libsystemd.so.0.30.0*
-rwxrwxr-x 1 zbyszek zbyszek 1834184 Feb 16 15:16 build-rawhide/systemd*

I would expect that the compiler would be able to elide the setting of a
variable if the variable is never used again. And this seems to be the case:
in optimized builds there is no change in size whatsoever. And the change in
size in unoptimized build is negligible.

Something strange is happening with size of libsystemd: it's bigger in
optimized builds. Something to figure out, but unrelated to this patch.
2021-02-16 17:15:11 +01:00
Zbigniew Jędrzejewski-Szmek
75db809ae5 tree-wide: return NULL from freeing functions
I started working on this because I wanted to change how
DEFINE_TRIVIAL_CLEANUP_FUNC is defined. Even independently of that change, it's
nice to make make things more consistent and predictable.
2021-02-16 17:15:10 +01:00
Zbigniew Jędrzejewski-Szmek
13734c75b5 Refactor strv_env_replace() into strv_env_replace_consume()
All callers of strv_env_replace() would free the argument on error.
So let's follow the same pattern as with strv_consume (and similar
naming) and unconditionally "use up" the argument.
2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
b230baaeb7 shared/exec-util: fix minor memleak
p was not freed on error.
2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
73c8cc7164 test-env-util: add tests for the two new functions 2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
99bfce1080 basic/env-util: drop now-unused strv_env_set() 2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
f08231fe07 basic/env-util: add strv_env_assign() helper 2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
6f8f8688e1 shared/user-record: inline iterator variable declarations 2021-02-16 16:10:14 +01:00
Zbigniew Jędrzejewski-Szmek
ab4ab13c74 locale: inline iterator variable declarations 2021-02-16 16:10:14 +01:00
Luca Boccassi
809ceb8217 namespace: store and use original MountEntry paths when prefixing
Some paths (eg: mount_tmpfs) simply assumed that prefixing always
happens and it always stores the original path in path_const, and
the prefixed path in path_malloc.
But if a MountEntry is set up in a helper function and thus uses
only _malloc struct members, this assumption doesn't hold and there's
a crash.

Refactor so that prefixing is done with a helper which stores the
original path in a separate struct member, and accessing it also
uses a helper which does the right thing.
2021-02-16 14:33:23 +00:00
Luca Boccassi
b850a9b29f MountImages: actually support optional paths
ENOENT did not cause an image mount to be skipped, fix it
2021-02-16 14:33:23 +00:00
Zbigniew Jędrzejewski-Szmek
5d160a2304 networkd: make network_config_section_free() inline 2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
1f38830153 resolved: make dns_transaction_gc return a pointer
_gc() does cleanup if it is possible. So far it returned a bool to
signal if it succeeded (false on success). When working on the resolved
code I had to look at the definition every time, because the (arguably
reversed) calling convention is unobvious. So let's return a pointer
(non-NULL: gc has not been done, NULL: gc has been done).

This fits nicely with the standard to return a pointer from all free
functions obviously.
2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
d3b56a0cad networkd-ndisc: drop confused freepp function
The function to cleanup IPv6Token was defined using freep, i.e. the macro
generated a freepp function. The correct way would be to do something like
  #define ipv6_token_free mfree
  DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6Token *, ipv6_token_free);
which would create ipv6_token_freep().
But since the cleanup function is unused, let's just drop it.
2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
450918d111 coredump: add typedef for struct 2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
a779cf30d2 basic/capability-util: add missing initialization
There was no error, because the pointer is unconditionally set below.
2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
6aa601c56c analyze: use typedefs for structs and inline iterator variable decls 2021-02-16 14:27:59 +01:00
Zbigniew Jędrzejewski-Szmek
a16d732a51 fuzz-systemctl-parse-argv: avoid "leak" of bus object
Memory sanitizer would report leaked memory from --boot-load-entry=help.

Maybe we should disable all bus connections from the fuzzer? It seems not
appropriate to communicate with logind. OTOH, in a real fuzzing environment
this call should just fail, so maybe that's OK.
2021-02-16 08:57:12 +01:00
Zbigniew Jędrzejewski-Szmek
b70935ac65 manager: fix memleak on repeated systemd.setenv keys 2021-02-15 20:44:06 +01:00
Zbigniew Jędrzejewski-Szmek
aaf057c4bb basic/env-util: add variant of strv_env_replace() that does strdup internally 2021-02-15 20:43:41 +01:00
Florian Westphal
79dd224093 add ipv6 range element creation test cases
The nft set backend doesn't support network masks, it works with
ranges.  Inputs like dead::/64 thus need to be translated to two
'start' and 'end' elements.

The 'start' element is the first element in the range (i.e., dead::).
The 'stop' element is the first element *past* the range, (dead:0:0100::
in the example).

This adds a few test cases.
2021-01-19 16:38:56 +01:00
Florian Westphal
f4fca22ad4 firewall-util-nft: clear previous address on replay
In case external entity wiped the ruleset, we need to clear the
'previous' address -- its already gone.

This prevents the transaction from succeeding: the delete operation fails.
2021-01-19 16:38:56 +01:00
Florian Westphal
48ed276647 networkd: extend IPMasquerade to cover ipv6
Extend IPMasquerade to also cover ipv6.
For compatibility reasons with earlier releases IPMasquerade=yes
is identical to IPMasquerade=ipv4.

Use IPMasquerade=both to cover ipv6 as well as ipv4.

IPForward will now also enable ipv6 forwarding if IPMasquerade for ipv6 is enabled.
2021-01-19 16:38:53 +01:00
Florian Westphal
deff68e718 nspawn: expose container ipv6 address too
Extend nspawn so it can keep track of one ipv4 and one ipv6 address.
2021-01-19 16:22:58 +01:00
Florian Westphal
0e544221c9 firewall-util: add ipv6 support to nftables backend
closely mirrors the existing ipv4 ruleset:
table ip6 io.systemd.nat {
        set masq_saddr {
                type ipv6_addr
                flags interval
        }

        map map_port_ipport {
                type inet_proto . inet_service : ipv6_addr . inet_service
        }

        chain prerouting {
                type nat hook prerouting priority dstnat + 1; policy accept;
                fib daddr type local dnat ip6 addr . port to meta l4proto . th dport map @map_port_ipport
        }

        chain output {
                type nat hook output priority -99; policy accept;
                ip6 daddr != ::1 oif "lo" dnat ip6 addr . port to meta l4proto . th dport map @map_port_ipport
        }

        chain postrouting {
                type nat hook postrouting priority srcnat + 1; policy accept;
                ip6 saddr @masq_saddr masquerade
        }
}

Only difference is the use of ipv6 addresses instead of ipv4 ones.

Currently has no effect: all in-tree callers pass AF_INET exclusively.
Followup patches will make nspawn expose ipv6 too and rework
IPMasquerade option to support both/v4/v6.
2021-01-19 16:22:58 +01:00
135 changed files with 1101 additions and 772 deletions

View File

@ -151,18 +151,18 @@ else {
<function>poll()</function> and
<function>sd_journal_process()</function> into one.</para>
<para><function>sd_journal_reliable_fd()</function> may be used to
check whether the wakeup events from the file descriptor returned
by <function>sd_journal_get_fd()</function> are known to be
immediately triggered. On certain file systems where file change
events from the OS are not available (such as NFS) changes need to
be polled for repeatedly, and hence are detected only with a
certain latency. This call will return a positive value if the
journal changes are detected immediately and zero when they need
to be polled for and hence might be noticed only with a certain
latency. Note that there is usually no need to invoke this function
directly as <function>sd_journal_get_timeout()</function> on these
file systems will ask for timeouts explicitly anyway.</para>
<para><function>sd_journal_reliable_fd()</function> may be used to check whether the wake-up events from
the file descriptor returned by <function>sd_journal_get_fd()</function> are known to be quickly
triggered. On certain file systems where file change events from the OS are not available (such as NFS)
changes need to be polled for repeatedly, and hence are detected only with a considerable latency. This
call will return a positive value if the journal changes are detected quickly and zero when they need to
be polled for. Note that there is usually no need to invoke this function directly as
<function>sd_journal_get_timeout()</function> will request appropriate timeouts anyway.</para>
<para>Note that all of the above change notification interfaces do not report changes
instantly. Latencies are introduced for multiple reasons: as mentioned certain storage backends require
time-based polling, in other cases wake-ups are optimized by coalescing events, and the OS introduces
additional IO/CPU scheduling latencies.</para>
</refsect1>
<refsect1>

View File

@ -744,9 +744,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<listitem><para>Configures IP masquerading for the network
interface. If enabled, packets forwarded from the network
interface will be appear as coming from the local host.
Takes a boolean argument. Implies
<varname>IPForward=ipv4</varname>. Defaults to
<literal>no</literal>.</para></listitem>
Takes one of <literal>ipv4</literal>, <literal>ipv6</literal>,
<literal>both</literal>, <literal>no</literal>.
The setting <literal>yes</literal> is the same as <literal>ipv4</literal> and not as
<literal>both</literal>!
Defaults to <literal>no</literal>.
If enabled, this automatically sets <varname>IPForward</varname> to one of
<literal>ipv4</literal>, <literal>ipv6</literal> or <literal>both</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv6PrivacyExtensions=</varname></term>

View File

@ -92,7 +92,7 @@ static usec_t arg_base_time = USEC_INFINITY;
STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
struct boot_times {
typedef struct BootTimes {
usec_t firmware_time;
usec_t loader_time;
usec_t kernel_time;
@ -124,9 +124,9 @@ struct boot_times {
* (so it is stored here for reference).
*/
usec_t reverse_offset;
};
} BootTimes;
struct unit_times {
typedef struct UnitTimes {
bool has_data;
char *name;
usec_t activating;
@ -134,9 +134,9 @@ struct unit_times {
usec_t deactivated;
usec_t deactivating;
usec_t time;
};
} UnitTimes;
struct host_info {
typedef struct HostInfo {
char *hostname;
char *kernel_name;
char *kernel_release;
@ -144,7 +144,7 @@ struct host_info {
char *os_pretty_name;
char *virtualization;
char *architecture;
};
} HostInfo;
static int acquire_bus(sd_bus **bus, bool *use_full_bus) {
bool user = arg_scope != UNIT_FILE_SYSTEM;
@ -209,19 +209,16 @@ static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char
return 0;
}
static int compare_unit_start(const struct unit_times *a, const struct unit_times *b) {
static int compare_unit_start(const UnitTimes *a, const UnitTimes *b) {
return CMP(a->activating, b->activating);
}
static void unit_times_free(struct unit_times *t) {
struct unit_times *p;
for (p = t; p->has_data; p++)
static UnitTimes* unit_times_free_array(UnitTimes *t) {
for (UnitTimes *p = t; p && p->has_data; p++)
free(p->name);
free(t);
return mfree(t);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct unit_times *, unit_times_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(UnitTimes*, unit_times_free_array);
static void subtract_timestamp(usec_t *a, usec_t b) {
assert(a);
@ -232,30 +229,30 @@ static void subtract_timestamp(usec_t *a, usec_t b) {
}
}
static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
static int acquire_boot_times(sd_bus *bus, BootTimes **bt) {
static const struct bus_properties_map property_map[] = {
{ "FirmwareTimestampMonotonic", "t", NULL, offsetof(struct boot_times, firmware_time) },
{ "LoaderTimestampMonotonic", "t", NULL, offsetof(struct boot_times, loader_time) },
{ "KernelTimestamp", "t", NULL, offsetof(struct boot_times, kernel_time) },
{ "InitRDTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_time) },
{ "UserspaceTimestampMonotonic", "t", NULL, offsetof(struct boot_times, userspace_time) },
{ "FinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, finish_time) },
{ "SecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_start_time) },
{ "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_finish_time) },
{ "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_start_time) },
{ "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_finish_time) },
{ "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_start_time) },
{ "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_finish_time) },
{ "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_start_time) },
{ "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_finish_time) },
{ "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_start_time) },
{ "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_finish_time) },
{ "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_start_time) },
{ "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_finish_time) },
{ "FirmwareTimestampMonotonic", "t", NULL, offsetof(BootTimes, firmware_time) },
{ "LoaderTimestampMonotonic", "t", NULL, offsetof(BootTimes, loader_time) },
{ "KernelTimestamp", "t", NULL, offsetof(BootTimes, kernel_time) },
{ "InitRDTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_time) },
{ "UserspaceTimestampMonotonic", "t", NULL, offsetof(BootTimes, userspace_time) },
{ "FinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, finish_time) },
{ "SecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_start_time) },
{ "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, security_finish_time) },
{ "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_start_time) },
{ "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, generators_finish_time) },
{ "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_start_time) },
{ "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, unitsload_finish_time) },
{ "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_start_time) },
{ "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_security_finish_time) },
{ "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_start_time) },
{ "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_generators_finish_time) },
{ "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_start_time) },
{ "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(BootTimes, initrd_unitsload_finish_time) },
{},
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static struct boot_times times;
static BootTimes times;
static bool cached = false;
int r;
@ -293,7 +290,7 @@ static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) {
} else {
/*
* User-instance-specific or container-system-specific timestamps processing
* (see comment to reverse_offset in struct boot_times).
* (see comment to reverse_offset in BootTimes).
*/
times.reverse_offset = times.userspace_time;
@ -316,9 +313,9 @@ finish:
return 0;
}
static void free_host_info(struct host_info *hi) {
static HostInfo* free_host_info(HostInfo *hi) {
if (!hi)
return;
return NULL;
free(hi->hostname);
free(hi->kernel_name);
@ -327,23 +324,23 @@ static void free_host_info(struct host_info *hi) {
free(hi->os_pretty_name);
free(hi->virtualization);
free(hi->architecture);
free(hi);
return mfree(hi);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info *, free_host_info);
DEFINE_TRIVIAL_CLEANUP_FUNC(HostInfo *, free_host_info);
static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
static int acquire_time_data(sd_bus *bus, UnitTimes **out) {
static const struct bus_properties_map property_map[] = {
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activating) },
{ "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activated) },
{ "ActiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivating) },
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivated) },
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activating) },
{ "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, activated) },
{ "ActiveExitTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivating) },
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(UnitTimes, deactivated) },
{},
};
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(unit_times_freep) struct unit_times *unit_times = NULL;
struct boot_times *boot_times = NULL;
_cleanup_(unit_times_free_arrayp) UnitTimes *unit_times = NULL;
BootTimes *boot_times = NULL;
size_t allocated = 0, c = 0;
UnitInfo u;
int r;
@ -361,7 +358,7 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
return bus_log_parse_error(r);
while ((r = bus_parse_unit_info(reply, &u)) > 0) {
struct unit_times *t;
UnitTimes *t;
if (!GREEDY_REALLOC(unit_times, allocated, c + 2))
return log_oom();
@ -414,28 +411,28 @@ static int acquire_time_data(sd_bus *bus, struct unit_times **out) {
return c;
}
static int acquire_host_info(sd_bus *bus, struct host_info **hi) {
static int acquire_host_info(sd_bus *bus, HostInfo **hi) {
static const struct bus_properties_map hostname_map[] = {
{ "Hostname", "s", NULL, offsetof(struct host_info, hostname) },
{ "KernelName", "s", NULL, offsetof(struct host_info, kernel_name) },
{ "KernelRelease", "s", NULL, offsetof(struct host_info, kernel_release) },
{ "KernelVersion", "s", NULL, offsetof(struct host_info, kernel_version) },
{ "OperatingSystemPrettyName", "s", NULL, offsetof(struct host_info, os_pretty_name) },
{ "Hostname", "s", NULL, offsetof(HostInfo, hostname) },
{ "KernelName", "s", NULL, offsetof(HostInfo, kernel_name) },
{ "KernelRelease", "s", NULL, offsetof(HostInfo, kernel_release) },
{ "KernelVersion", "s", NULL, offsetof(HostInfo, kernel_version) },
{ "OperatingSystemPrettyName", "s", NULL, offsetof(HostInfo, os_pretty_name) },
{}
};
static const struct bus_properties_map manager_map[] = {
{ "Virtualization", "s", NULL, offsetof(struct host_info, virtualization) },
{ "Architecture", "s", NULL, offsetof(struct host_info, architecture) },
{ "Virtualization", "s", NULL, offsetof(HostInfo, virtualization) },
{ "Architecture", "s", NULL, offsetof(HostInfo, architecture) },
{}
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL;
_cleanup_(free_host_infop) struct host_info *host;
_cleanup_(free_host_infop) HostInfo *host = NULL;
int r;
host = new0(struct host_info, 1);
host = new0(HostInfo, 1);
if (!host)
return log_oom();
@ -482,7 +479,7 @@ manager:
static int pretty_boot_time(sd_bus *bus, char **_buf) {
char ts[FORMAT_TIMESPAN_MAX];
struct boot_times *t;
BootTimes *t;
static char buf[4096];
size_t size;
char *ptr;
@ -559,14 +556,12 @@ static int pretty_boot_time(sd_bus *bus, char **_buf) {
}
static void svg_graph_box(double height, double begin, double end) {
long long i;
/* outside box, fill */
svg("<rect class=\"box\" x=\"0\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n",
SCALE_X * (end - begin),
SCALE_Y * height);
for (i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
for (long long i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) {
/* lines for each second */
if (i % 5000000 == 0)
svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n"
@ -594,7 +589,7 @@ static void svg_graph_box(double height, double begin, double end) {
}
}
static int plot_unit_times(struct unit_times *u, double width, int y) {
static int plot_unit_times(UnitTimes *u, double width, int y) {
char ts[FORMAT_TIMESPAN_MAX];
bool b;
@ -617,13 +612,13 @@ static int plot_unit_times(struct unit_times *u, double width, int y) {
}
static int analyze_plot(int argc, char *argv[], void *userdata) {
_cleanup_(free_host_infop) struct host_info *host = NULL;
_cleanup_(free_host_infop) HostInfo *host = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
_cleanup_free_ char *pretty_times = NULL;
bool use_full_bus = arg_scope == UNIT_FILE_SYSTEM;
struct boot_times *boot;
struct unit_times *u;
BootTimes *boot;
UnitTimes *u;
int n, m = 1, y = 0, r;
double width;
@ -837,13 +832,12 @@ static int list_dependencies_print(
unsigned level,
unsigned branches,
bool last,
struct unit_times *times,
struct boot_times *boot) {
UnitTimes *times,
BootTimes *boot) {
unsigned i;
char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX];
for (i = level; i != 0; i--)
for (unsigned i = level; i != 0; i--)
printf("%s", special_glyph(branches & (1 << (i-1)) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE));
printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH));
@ -882,7 +876,7 @@ static Hashmap *unit_times_hashmap;
static int list_dependencies_compare(char *const *a, char *const *b) {
usec_t usa = 0, usb = 0;
struct unit_times *times;
UnitTimes *times;
times = hashmap_get(unit_times_hashmap, *a);
if (times)
@ -894,7 +888,7 @@ static int list_dependencies_compare(char *const *a, char *const *b) {
return CMP(usb, usa);
}
static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) {
static bool times_in_range(const UnitTimes *times, const BootTimes *boot) {
return times && times->activated > 0 && times->activated <= boot->finish_time;
}
@ -904,8 +898,8 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
int r;
usec_t service_longest = 0;
int to_print = 0;
struct unit_times *times;
struct boot_times *boot;
UnitTimes *times;
BootTimes *boot;
if (strv_extend(units, name))
return log_oom();
@ -970,13 +964,13 @@ static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level,
static int list_dependencies(sd_bus *bus, const char *name) {
_cleanup_strv_free_ char **units = NULL;
char ts[FORMAT_TIMESPAN_MAX];
struct unit_times *times;
UnitTimes *times;
int r;
const char *id;
_cleanup_free_ char *path = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
struct boot_times *boot;
BootTimes *boot;
assert(bus);
@ -1021,7 +1015,7 @@ static int list_dependencies(sd_bus *bus, const char *name) {
static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
Hashmap *h;
int n, r;
@ -1037,7 +1031,7 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
if (!h)
return log_oom();
for (struct unit_times *u = times; u->has_data; u++) {
for (UnitTimes *u = times; u->has_data; u++) {
r = hashmap_put(h, u->name, u);
if (r < 0)
return log_error_errno(r, "Failed to add entry to hashmap: %m");
@ -1062,7 +1056,7 @@ static int analyze_critical_chain(int argc, char *argv[], void *userdata) {
static int analyze_blame(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(unit_times_freep) struct unit_times *times = NULL;
_cleanup_(unit_times_free_arrayp) UnitTimes *times = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
TableCell *cell;
int n, r;
@ -1103,7 +1097,7 @@ static int analyze_blame(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
for (struct unit_times *u = times; u->has_data; u++) {
for (UnitTimes *u = times; u->has_data; u++) {
if (u->time <= 0)
continue;
@ -1716,7 +1710,7 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
if (strv_isempty(strv_skip(argv, 1))) {
_cleanup_set_free_ Set *kernel = NULL, *known = NULL;
const char *sys;
int i, k;
int k;
NULSTR_FOREACH(sys, syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].value)
if (set_put_strdup(&known, sys) < 0)
@ -1724,7 +1718,7 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
k = load_kernel_syscalls(&kernel);
for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
for (int i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
const SyscallFilterSet *set = syscall_filter_sets + i;
if (!first)
puts("");

View File

@ -18,7 +18,7 @@
#include "util.h"
int have_effective_cap(int value) {
_cleanup_cap_free_ cap_t cap;
_cleanup_cap_free_ cap_t cap = NULL;
cap_flag_value_t fv;
cap = cap_get_proc();

View File

@ -25,7 +25,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities);
int drop_capability(cap_value_t cv);
DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(cap_t, cap_free, NULL);
#define _cleanup_cap_free_ _cleanup_(cap_freep)
static inline void cap_free_charpp(char **p) {

View File

@ -5,7 +5,7 @@
#include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(void*, dlclose);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(void*, dlclose, NULL);
int dlsym_many_and_warn(void *dl, int level, ...);

View File

@ -385,11 +385,9 @@ static int load_env_file_push(
if (!p)
return -ENOMEM;
r = strv_env_replace(m, p);
if (r < 0) {
free(p);
r = strv_env_replace_consume(m, p);
if (r < 0)
return r;
}
if (n_pushed)
(*n_pushed)++;

View File

@ -363,20 +363,23 @@ char **strv_env_unset_many(char **l, ...) {
return l;
}
int strv_env_replace(char ***l, char *p) {
int strv_env_replace_consume(char ***l, char *p) {
const char *t, *name;
char **f;
int r;
assert(p);
/* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits
* in-place. Does not copy p. p must be a valid key=value assignment.
*/
/* Replace first occurrence of the env var or add a new one in the string list. Drop other
* occurrences. Edits in-place. Does not copy p and CONSUMES p EVEN ON FAILURE.
*
* p must be a valid key=value assignment. */
t = strchr(p, '=');
if (!t)
if (!t) {
free(p);
return -EINVAL;
}
name = strndupa(p, t - p);
@ -388,39 +391,39 @@ int strv_env_replace(char ***l, char *p) {
}
/* We didn't find a match, we need to append p or create a new strv */
r = strv_push(l, p);
r = strv_consume(l, p);
if (r < 0)
return r;
return 1;
}
char **strv_env_set(char **x, const char *p) {
_cleanup_strv_free_ char **ret = NULL;
size_t n, m;
char **k;
int strv_env_replace_strdup(char ***l, const char *assignment) {
/* Like strv_env_replace_consume(), but copies the argument. */
/* Overrides the env var setting of p, returns a new copy */
char *p = strdup(assignment);
if (!p)
return -ENOMEM;
n = strv_length(x);
m = n + 2;
if (m < n) /* overflow? */
return NULL;
return strv_env_replace_consume(l, p);
}
ret = new(char*, m);
if (!ret)
return NULL;
int strv_env_assign(char ***l, const char *key, const char *value) {
if (!env_name_is_valid(key))
return -EINVAL;
*ret = NULL;
k = ret;
/* NULL removes assignment, "" creates an empty assignment. */
if (env_append(ret, &k, x) < 0)
return NULL;
if (!value) {
strv_env_unset(*l, key);
return 0;
}
if (env_append(ret, &k, STRV_MAKE(p)) < 0)
return NULL;
char *p = strjoin(key, "=", value);
if (!p)
return -ENOMEM;
return TAKE_PTR(ret);
return strv_env_replace_consume(l, p);
}
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) {

View File

@ -42,10 +42,11 @@ bool strv_env_name_or_assignment_is_valid(char **l);
char **strv_env_merge(size_t n_lists, ...);
char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
char **strv_env_set(char **x, const char *p); /* New copy ... */
char **strv_env_unset(char **l, const char *p); /* In place ... */
char **strv_env_unset_many(char **l, ...) _sentinel_;
int strv_env_replace(char ***l, char *p); /* In place ... */
int strv_env_replace_consume(char ***l, char *p); /* In place ... */
int strv_env_replace_strdup(char ***l, const char *assignment);
int strv_env_assign(char ***l, const char *key, const char *value);
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
char *strv_env_get(char **x, const char *n) _pure_;

View File

@ -41,8 +41,8 @@ static inline void fclosep(FILE **f) {
safe_fclose(*f);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, pclose, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(DIR*, closedir, NULL);
#define _cleanup_close_ _cleanup_(closep)
#define _cleanup_fclose_ _cleanup_(fclosep)

View File

@ -1146,7 +1146,7 @@ static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) {
return EOL_NONE;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(FILE*, funlockfile, NULL);
int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
size_t n = 0, allocated = 0, count = 0;

View File

@ -14,7 +14,7 @@
void initialize_libgcrypt(bool secmem);
int string_hashsum(const char *s, size_t len, int md_algorithm, char **out);
DEFINE_TRIVIAL_CLEANUP_FUNC(gcry_md_hd_t, gcry_md_close);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gcry_md_hd_t, gcry_md_close, NULL);
#endif
static inline int string_hashsum_sha224(const char *s, size_t len, char **out) {

View File

@ -405,10 +405,20 @@ static inline int __coverity_check_and_return__(int condition) {
func(p); \
}
/* When func() returns the void value (NULL, -1, …) of the appropriate type */
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
static inline void func##p(type *p) { \
if (*p) \
*p = func(*p); \
}
/* When func() doesn't return the appropriate type, set variable to empty afterwards */
#define DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(type, func, empty) \
static inline void func##p(type *p) { \
if (*p != (empty)) { \
func(*p); \
*p = (empty); \
} \
}
#define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \

View File

@ -29,7 +29,7 @@
#include "time-util.h"
#if HAVE_SELINUX
DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(context_t, context_free, NULL);
#define _cleanup_context_free_ _cleanup_(context_freep)
static int mac_selinux_reload(int seqno);

View File

@ -11,7 +11,7 @@
#if HAVE_SELINUX
#include <selinux/selinux.h>
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, freecon, NULL);
#define _cleanup_freecon_ _cleanup_(freeconp)
#endif

View File

@ -72,12 +72,17 @@ int dir_is_empty_at(int dir_fd, const char *path) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
if (path)
if (path) {
fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
else
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0)
return -errno;
if (fd < 0)
return -errno;
} else {
/* Note that DUPing is not enough, as the internal pointer
* would still be shared and moved by FOREACH_DIRENT. */
fd = fd_reopen(dir_fd, O_CLOEXEC);
if (fd < 0)
return fd;
}
d = take_fdopendir(&fd);
if (!d)

View File

@ -26,7 +26,7 @@
* ...
*/
struct strbuf *strbuf_new(void) {
struct strbuf* strbuf_new(void) {
struct strbuf *str;
str = new(struct strbuf, 1);
@ -65,13 +65,13 @@ void strbuf_complete(struct strbuf *str) {
}
/* clean up everything */
void strbuf_cleanup(struct strbuf *str) {
struct strbuf* strbuf_free(struct strbuf *str) {
if (!str)
return;
return NULL;
strbuf_complete(str);
free(str->buf);
free(str);
return mfree(str);
}
static int strbuf_children_cmp(const struct strbuf_child_entry *n1,

View File

@ -32,8 +32,8 @@ struct strbuf_child_entry {
struct strbuf_node *child;
};
struct strbuf *strbuf_new(void);
struct strbuf* strbuf_new(void);
ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len);
void strbuf_complete(struct strbuf *str);
void strbuf_cleanup(struct strbuf *str);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup);
struct strbuf* strbuf_free(struct strbuf *str);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_free);

View File

@ -780,24 +780,22 @@ static int member_compare_funcp(Member * const *a, Member * const *b) {
return member_compare_func(*a, *b);
}
static void member_free(Member *m) {
static Member* member_free(Member *m) {
if (!m)
return;
return NULL;
free(m->interface);
free(m->name);
free(m->signature);
free(m->result);
free(m->value);
free(m);
return mfree(m);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free);
static void member_set_free(Set *s) {
set_free_with_destructor(s, member_free);
static Set* member_set_free(Set *s) {
return set_free_with_destructor(s, member_free);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free);
static int on_interface(const char *interface, uint64_t flags, void *userdata) {

View File

@ -16,17 +16,17 @@
#include "strv.h"
#if HAVE_APPARMOR
DEFINE_TRIVIAL_CLEANUP_FUNC(aa_policy_cache *, aa_policy_cache_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(aa_features *, aa_features_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_policy_cache *, aa_policy_cache_unref, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(aa_features *, aa_features_unref, NULL);
#endif
int mac_apparmor_setup(void) {
#if HAVE_APPARMOR
int r;
_cleanup_(aa_policy_cache_unrefp) aa_policy_cache *policy_cache = NULL;
_cleanup_(aa_features_unrefp) aa_features *features = NULL;
const char *current_file;
_cleanup_free_ char *current_profile = NULL, *cache_dir_path = NULL;
int r;
if (!mac_apparmor_use()) {
log_debug("AppArmor either not supported by the kernel or disabled.");

View File

@ -48,13 +48,13 @@ struct expire_data {
int ioctl_fd;
};
static void expire_data_free(struct expire_data *data) {
static struct expire_data* expire_data_free(struct expire_data *data) {
if (!data)
return;
return NULL;
safe_close(data->dev_autofs_fd);
safe_close(data->ioctl_fd);
free(data);
return mfree(data);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free);

View File

@ -2636,7 +2636,7 @@ int config_parse_environ(
}
for (const char *p = rvalue;; ) {
_cleanup_free_ char *word = NULL, *k = NULL;
_cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
@ -2650,26 +2650,24 @@ int config_parse_environ(
}
if (u) {
r = unit_full_printf(u, word, &k);
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in %s, ignoring: %m", word);
continue;
}
} else
k = TAKE_PTR(word);
resolved = TAKE_PTR(word);
if (!env_assignment_is_valid(k)) {
if (!env_assignment_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid environment assignment, ignoring: %s", k);
"Invalid environment assignment, ignoring: %s", resolved);
continue;
}
r = strv_env_replace(env, k);
r = strv_env_replace_consume(env, TAKE_PTR(resolved));
if (r < 0)
return log_oom();
k = NULL;
return log_error_errno(r, "Failed to update environment: %m");
}
}

View File

@ -453,16 +453,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
if (proc_cmdline_value_missing(key, value))
return 0;
if (env_assignment_is_valid(value)) {
char **env;
env = strv_env_set(arg_default_environment, value);
if (!env)
if (!env_assignment_is_valid(value))
log_warning("Environment variable assignment '%s' is not valid. Ignoring.", value);
else {
r = strv_env_replace_strdup(&arg_default_environment, value);
if (r < 0)
return log_oom();
arg_default_environment = env;
} else
log_warning("Environment variable name '%s' is not valid. Ignoring.", value);
}
} else if (proc_cmdline_key_streq(key, "systemd.machine_id")) {
@ -821,6 +818,7 @@ static int parse_argv(int argc, char *argv[]) {
};
int c, r;
bool user_arg_seen = false;
assert(argc >= 1);
assert(argv);
@ -910,6 +908,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_USER:
arg_system = false;
user_arg_seen = true;
break;
case ARG_TEST:
@ -1066,10 +1065,12 @@ static int parse_argv(int argc, char *argv[]) {
}
if (optind < argc && getpid_cached() != 1)
/* Hmm, when we aren't run as init system
* let's complain about excess arguments */
/* Hmm, when we aren't run as init system let's complain about excess arguments */
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Excess arguments.");
if (arg_action == ACTION_RUN && !arg_system && !user_arg_seen)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Excess arguments.");
"Explicit --user argument required to run as user manager.");
return 0;
}

View File

@ -642,22 +642,14 @@ int manager_default_environment(Manager *m) {
/* Import locale variables LC_*= from configuration */
(void) locale_setup(&m->transient_environment);
} else {
_cleanup_free_ char *k = NULL;
/* The user manager passes its own environment
* along to its children, except for $PATH. */
/* The user manager passes its own environment along to its children, except for $PATH. */
m->transient_environment = strv_copy(environ);
if (!m->transient_environment)
return log_oom();
k = strdup("PATH=" DEFAULT_USER_PATH);
if (!k)
return log_oom();
r = strv_env_replace(&m->transient_environment, k);
r = strv_env_replace_strdup(&m->transient_environment, "PATH=" DEFAULT_USER_PATH);
if (r < 0)
return log_oom();
TAKE_PTR(k);
}
sanitize_environment(m->transient_environment);

View File

@ -72,6 +72,8 @@ typedef struct MountEntry {
bool exec:1; /* Shall clear MS_NOEXEC on the mount itself */
bool applied:1; /* Already applied */
char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */
const char *unprefixed_path_const; /* If the path was amended with a prefix, these will save the original */
char *unprefixed_path_malloc;
const char *source_const; /* The source path, for bind mounts or images */
char *source_malloc;
const char *options_const;/* Mount options for tmpfs */
@ -231,6 +233,29 @@ static const char *mount_entry_path(const MountEntry *p) {
return p->path_malloc ?: p->path_const;
}
static const char *mount_entry_unprefixed_path(const MountEntry *p) {
assert(p);
/* Returns the unprefixed path (ie: before prefix_where_needed() ran), if any */
return p->unprefixed_path_malloc ?: p->unprefixed_path_const ?: mount_entry_path(p);
}
static void mount_entry_consume_prefix(MountEntry *p, char *new_path) {
assert(p);
assert(p->path_malloc || p->path_const);
assert(new_path);
/* Saves current path in unprefixed_ variable, and takes over new_path */
free_and_replace(p->unprefixed_path_malloc, p->path_malloc);
/* If we didn't have a path on the heap, then it's a static one */
if (!p->unprefixed_path_malloc)
p->unprefixed_path_const = p->path_const;
p->path_malloc = new_path;
p->has_prefix = true;
}
static bool mount_entry_read_only(const MountEntry *p) {
assert(p);
@ -265,6 +290,7 @@ static void mount_entry_done(MountEntry *p) {
assert(p);
p->path_malloc = mfree(p->path_malloc);
p->unprefixed_path_malloc = mfree(p->unprefixed_path_malloc);
p->source_malloc = mfree(p->source_malloc);
p->options_malloc = mfree(p->options_malloc);
p->image_options = mount_options_free_all(p->image_options);
@ -492,8 +518,7 @@ static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directo
if (!s)
return -ENOMEM;
free_and_replace(m[i].path_malloc, s);
m[i].has_prefix = true;
mount_entry_consume_prefix(&m[i], s);
}
return 0;
@ -946,7 +971,7 @@ static int mount_tmpfs(const MountEntry *m) {
assert(m);
entry_path = mount_entry_path(m);
inner_path = m->path_const;
inner_path = mount_entry_unprefixed_path(m);
/* First, get rid of everything that is below if there is anything. Then, overmount with our new tmpfs */
@ -984,6 +1009,8 @@ static int mount_images(const MountEntry *m) {
assert(m);
r = verity_dissect_and_mount(mount_entry_source(m), mount_entry_path(m), m->image_options);
if (r == -ENOENT && m->ignore)
return 0;
if (r < 0)
return log_debug_errno(r, "Failed to mount image %s on %s: %m", mount_entry_source(m), mount_entry_path(m));
@ -1015,8 +1042,7 @@ static int follow_symlink(
log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target);
free_and_replace(m->path_malloc, target);
m->has_prefix = true;
mount_entry_consume_prefix(m, TAKE_PTR(target));
m->n_followed ++;

View File

@ -137,11 +137,11 @@ int setup_namespace(
#define RUN_SYSTEMD_EMPTY "/run/systemd/empty"
static inline void namespace_cleanup_tmpdir(char *p) {
static inline char* namespace_cleanup_tmpdir(char *p) {
PROTECT_ERRNO;
if (!streq_ptr(p, RUN_SYSTEMD_EMPTY))
(void) rmdir(p);
free(p);
return mfree(p);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, namespace_cleanup_tmpdir);

View File

@ -969,6 +969,8 @@ static void socket_close_fds(Socket *s) {
if (s->remove_on_stop)
STRV_FOREACH(i, s->symlinks)
(void) unlink(*i);
/* Note that we don't return NULL here, since s has not been freed. */
}
static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
@ -1609,10 +1611,10 @@ static int socket_address_listen_in_cgroup(
return fd;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Socket *, socket_close_fds);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(Socket *, socket_close_fds, NULL);
static int socket_open_fds(Socket *_s) {
_cleanup_(socket_close_fdsp) Socket *s = _s;
static int socket_open_fds(Socket *orig_s) {
_cleanup_(socket_close_fdsp) Socket *s = orig_s;
_cleanup_(mac_selinux_freep) char *label = NULL;
bool know_label = false;
SocketPort *p;

View File

@ -82,7 +82,7 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency);
Unit *unit_new(Manager *m, size_t size) {
Unit* unit_new(Manager *m, size_t size) {
Unit *u;
assert(m);
@ -607,11 +607,11 @@ static void unit_done(Unit *u) {
cgroup_context_done(cc);
}
void unit_free(Unit *u) {
Unit* unit_free(Unit *u) {
char *t;
if (!u)
return;
return NULL;
u->transient_file = safe_fclose(u->transient_file);
@ -741,7 +741,7 @@ void unit_free(Unit *u) {
set_free_free(u->aliases);
free(u->id);
free(u);
return mfree(u);
}
FreezerState unit_freezer_state(Unit *u) {

View File

@ -674,8 +674,8 @@ static inline Unit* UNIT_TRIGGER(Unit *u) {
return hashmap_first_key(u->dependencies[UNIT_TRIGGERS]);
}
Unit *unit_new(Manager *m, size_t size);
void unit_free(Unit *u);
Unit* unit_new(Manager *m, size_t size);
Unit* unit_free(Unit *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free);
int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret);

View File

@ -22,24 +22,23 @@
#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */
#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */
struct vacuum_candidate {
typedef struct VacuumCandidate {
unsigned n_files;
char *oldest_file;
usec_t oldest_mtime;
};
} VacuumCandidate;
static void vacuum_candidate_free(struct vacuum_candidate *c) {
static VacuumCandidate* vacuum_candidate_free(VacuumCandidate *c) {
if (!c)
return;
return NULL;
free(c->oldest_file);
free(c);
return mfree(c);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(VacuumCandidate*, vacuum_candidate_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free);
static void vacuum_candidate_hashmap_free(Hashmap *h) {
hashmap_free_with_destructor(h, vacuum_candidate_free);
static Hashmap* vacuum_candidate_hashmap_free(Hashmap *h) {
return hashmap_free_with_destructor(h, vacuum_candidate_free);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free);
@ -142,14 +141,14 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
for (;;) {
_cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL;
struct vacuum_candidate *worst = NULL;
VacuumCandidate *worst = NULL;
struct dirent *de;
uint64_t sum = 0;
rewinddir(d);
FOREACH_DIRENT(de, d, goto fail) {
struct vacuum_candidate *c;
VacuumCandidate *c;
struct stat st;
uid_t uid;
usec_t t;
@ -196,9 +195,9 @@ int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) {
}
} else {
_cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL;
_cleanup_(vacuum_candidate_freep) VacuumCandidate *n = NULL;
n = new0(struct vacuum_candidate, 1);
n = new0(VacuumCandidate, 1);
if (!n)
return log_oom();

View File

@ -2512,7 +2512,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_SETENV: {
_cleanup_free_ char **l = NULL, **k = NULL;
_cleanup_free_ char **l = NULL;
_cleanup_(json_variant_unrefp) JsonVariant *ne = NULL;
JsonVariant *e;
@ -2525,7 +2525,8 @@ static int parse_argv(int argc, char *argv[]) {
}
if (!env_assignment_is_valid(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Environment assignment '%s' not valid.", optarg);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Environment assignment '%s' not valid.", optarg);
e = json_variant_by_key(arg_identity_extra, "environment");
if (e) {
@ -2534,13 +2535,13 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(r, "Failed to parse JSON environment field: %m");
}
k = strv_env_set(l, optarg);
if (!k)
return log_oom();
r = strv_env_replace_strdup(&l, optarg);
if (r < 0)
return log_error_errno(r, "Failed to replace JSON environment field: %m");
strv_sort(k);
strv_sort(l);
r = json_variant_new_array_strv(&ne, k);
r = json_variant_new_array_strv(&ne, l);
if (r < 0)
return log_error_errno(r, "Failed to allocate environment list JSON: %m");

View File

@ -1343,7 +1343,7 @@ static int manager_load_key_pair(Manager *m) {
return 1;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY_CTX*, EVP_PKEY_CTX_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY_CTX*, EVP_PKEY_CTX_free, NULL);
static int manager_generate_key_pair(Manager *m) {
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *ctx = NULL;
@ -1454,7 +1454,7 @@ int manager_sign_user_record(Manager *m, UserRecord *u, UserRecord **ret, sd_bus
}
DEFINE_PRIVATE_HASH_OPS_FULL(public_key_hash_ops, char, string_hash_func, string_compare_func, free, EVP_PKEY, EVP_PKEY_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_PKEY*, EVP_PKEY_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_PKEY*, EVP_PKEY_free, NULL);
static int manager_load_public_key_one(Manager *m, const char *path) {
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;

View File

@ -1592,10 +1592,10 @@ static int luks_format(
return 0;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
static int make_partition_table(
int fd,

View File

@ -27,7 +27,7 @@ static int user_record_signable_json(UserRecord *ur, char **ret) {
return json_variant_format(j, 0, ret);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(EVP_MD_CTX*, EVP_MD_CTX_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
int user_record_sign(UserRecord *ur, EVP_PKEY *private_key, UserRecord **ret) {
_cleanup_(json_variant_unrefp) JsonVariant *encoded = NULL, *v = NULL;

View File

@ -423,25 +423,11 @@ static int context_write_data_machine_info(Context *c) {
return r;
for (int p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
_cleanup_free_ char *t = NULL;
char **u;
assert(name[p]);
if (isempty(c->data[p])) {
strv_env_unset(l, name[p]);
continue;
}
t = strjoin(name[p], "=", c->data[p]);
if (!t)
return -ENOMEM;
u = strv_env_set(l, t);
if (!u)
return -ENOMEM;
strv_free_and_replace(l, u);
r = strv_env_assign(&l, name[p], empty_to_null(c->data[p]));
if (r < 0)
return r;
}
if (strv_isempty(l)) {

View File

@ -34,6 +34,6 @@ struct curl_slist *curl_slist_new(const char *first, ...) _sentinel_;
int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value);
int curl_parse_http_time(const char *t, usec_t *ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup);
DEFINE_TRIVIAL_CLEANUP_FUNC(CURLM*, curl_multi_cleanup);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURL*, curl_easy_cleanup, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(CURLM*, curl_multi_cleanup, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct curl_slist*, curl_slist_free_all, NULL);

View File

@ -210,8 +210,9 @@ static int fifo_process(Fifo *f) {
return 0;
}
static void fifo_free(Fifo *f) {
assert(f);
static Fifo* fifo_free(Fifo *f) {
if (!f)
return NULL;
if (f->server) {
assert(f->server->n_fifos > 0);
@ -226,7 +227,7 @@ static void fifo_free(Fifo *f) {
safe_close(f->fd);
}
free(f);
return mfree(f);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);

View File

@ -80,5 +80,5 @@ int check_permissions(struct MHD_Connection *connection, int *code, char **hostn
*/
int setup_gnutls_logger(char **categories);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Response*, MHD_destroy_response);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Daemon*, MHD_stop_daemon, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct MHD_Response*, MHD_destroy_response, NULL);

View File

@ -166,8 +166,8 @@ typedef struct BootId {
} BootId;
#if HAVE_PCRE2
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, sym_pcre2_match_data_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, sym_pcre2_code_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_match_data*, sym_pcre2_match_data_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(pcre2_code*, sym_pcre2_code_free, NULL);
static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) {
int errorcode, r;

View File

@ -98,9 +98,9 @@ struct StdoutStream {
char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
};
void stdout_stream_free(StdoutStream *s) {
StdoutStream* stdout_stream_free(StdoutStream *s) {
if (!s)
return;
return NULL;
if (s->server) {
@ -129,7 +129,7 @@ void stdout_stream_free(StdoutStream *s) {
free(s->state_file);
free(s->buffer);
free(s);
return mfree(s);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);

View File

@ -9,7 +9,7 @@ typedef struct StdoutStream StdoutStream;
int server_open_stdout_socket(Server *s, const char *stdout_socket);
int server_restore_streams(Server *s, FDSet *fds);
void stdout_stream_free(StdoutStream *s);
StdoutStream* stdout_stream_free(StdoutStream *s);
int stdout_stream_install(Server *s, int fd, StdoutStream **ret);
void stdout_stream_destroy(StdoutStream *s);
void stdout_stream_send_notify(StdoutStream *s);

View File

@ -649,12 +649,12 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
return 0;
}
static void dhcp_request_free(DHCPRequest *req) {
static DHCPRequest* dhcp_request_free(DHCPRequest *req) {
if (!req)
return;
return NULL;
free(req->client_id.data);
free(req);
return mfree(req);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);

View File

@ -939,7 +939,7 @@ static void source_disconnect(sd_event_source *s) {
sd_event_unref(event);
}
static void source_free(sd_event_source *s) {
static sd_event_source* source_free(sd_event_source *s) {
assert(s);
source_disconnect(s);
@ -989,7 +989,7 @@ static void source_free(sd_event_source *s) {
s->destroy_callback(s->userdata);
free(s->description);
free(s);
return mfree(s);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free);

View File

@ -115,13 +115,13 @@ static void trie_node_cleanup(struct trie_node *node) {
free(node);
}
static void trie_free(struct trie *trie) {
static struct trie* trie_free(struct trie *trie) {
if (!trie)
return;
return NULL;
trie_node_cleanup(trie->root);
strbuf_cleanup(trie->strings);
free(trie);
strbuf_free(trie->strings);
return mfree(trie);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free);

View File

@ -444,7 +444,7 @@ error:
int catalog_update(const char* database, const char* root, const char* const* dirs) {
_cleanup_strv_free_ char **files = NULL;
char **f;
_cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL;
_cleanup_(strbuf_freep) struct strbuf *sb = NULL;
_cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL;
_cleanup_free_ CatalogItem *items = NULL;
ssize_t offset;

View File

@ -34,13 +34,13 @@
#include "util.h"
#if HAVE_LZ4
DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext);
DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_compressionContext_t, LZ4F_freeCompressionContext, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext, NULL);
#endif
#if HAVE_ZSTD
DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_CCtx *, ZSTD_freeCCtx);
DEFINE_TRIVIAL_CLEANUP_FUNC(ZSTD_DCtx *, ZSTD_freeDCtx);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_CCtx*, ZSTD_freeCCtx, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(ZSTD_DCtx*, ZSTD_freeDCtx, NULL);
static int zstd_ret_to_errno(size_t ret) {
switch (ZSTD_getErrorCode(ret)) {

View File

@ -208,6 +208,7 @@ static bool journal_file_set_offline_try_restart(JournalFile *f) {
* context without involving another thread.
*/
int journal_file_set_offline(JournalFile *f, bool wait) {
int target_state;
bool restarted;
int r;
@ -219,9 +220,13 @@ int journal_file_set_offline(JournalFile *f, bool wait) {
if (f->fd < 0 || !f->header)
return -EINVAL;
target_state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE;
/* An offlining journal is implicitly online and may modify f->header->state,
* we must also join any potentially lingering offline thread when not online. */
if (!journal_file_is_offlining(f) && f->header->state != STATE_ONLINE)
* we must also join any potentially lingering offline thread when already in
* the desired offline state.
*/
if (!journal_file_is_offlining(f) && f->header->state == target_state)
return journal_file_set_offline_thread_join(f);
/* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */

View File

@ -663,13 +663,17 @@ int sd_netlink_message_cancel_array(sd_netlink_message *m) {
return 0;
}
static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) {
static int netlink_message_read_internal(
sd_netlink_message *m,
unsigned short type,
void **ret_data,
bool *ret_net_byteorder) {
struct netlink_attribute *attribute;
struct rtattr *rta;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(data, -EINVAL);
assert(m->n_containers < RTNL_CONTAINER_DEPTH);
@ -686,10 +690,11 @@ static int netlink_message_read_internal(sd_netlink_message *m, unsigned short t
rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
*data = RTA_DATA(rta);
if (ret_data)
*ret_data = RTA_DATA(rta);
if (net_byteorder)
*net_byteorder = attribute->net_byteorder;
if (ret_net_byteorder)
*ret_net_byteorder = attribute->net_byteorder;
return RTA_PAYLOAD(rta);
}
@ -974,6 +979,27 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
return r;
}
int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type) {
void *attr_data;
int r;
assert_return(m, -EINVAL);
/* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_FLAG);
if (r < 0)
return r;
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r == -ENODATA)
return 0;
if (r < 0)
return r;
return 1;
}
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
_cleanup_strv_free_ char **s = NULL;
const NLTypeSystem *type_system;

View File

@ -733,14 +733,15 @@ static const NLType rtnl_route_types[] = {
[RTA_VIA] = { /* See struct rtvia */ },
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
[RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
[RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
[RTA_UID] = { .type = NETLINK_TYPE_U32 },
[RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 },
[RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
[RTA_SPORT] = { .type = NETLINK_TYPE_U16 },
[RTA_DPORT] = { .type = NETLINK_TYPE_U16 },
[RTA_NH_ID] = { .type = NETLINK_TYPE_U32 },
};
static const NLTypeSystem rtnl_route_type_system = {
@ -804,8 +805,16 @@ static const NLTypeSystem rtnl_routing_policy_rule_type_system = {
static const NLType rtnl_nexthop_types[] = {
[NHA_ID] = { .type = NETLINK_TYPE_U32 },
[NHA_GROUP] = { /* array of struct nexthop_grp */ },
[NHA_GROUP_TYPE] = { .type = NETLINK_TYPE_U16 },
[NHA_BLACKHOLE] = { .type = NETLINK_TYPE_FLAG },
[NHA_OIF] = { .type = NETLINK_TYPE_U32 },
[NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
[NHA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
[NHA_ENCAP] = { .type = NETLINK_TYPE_NESTED },
[NHA_GROUPS] = { .type = NETLINK_TYPE_FLAG },
[NHA_MASTER] = { .type = NETLINK_TYPE_U32 },
[NHA_FDB] = { .type = NETLINK_TYPE_FLAG },
};
static const NLTypeSystem rtnl_nexthop_type_system = {

View File

@ -125,20 +125,6 @@ int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family) {
return 0;
}
int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
rtm = NLMSG_DATA(m->hdr);
rtm->rtm_family = family;
return 0;
}
int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) {
struct rtmsg *rtm;
@ -294,8 +280,19 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
int r;
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
assert_return((nhmsg_type == RTM_GETNEXTHOP && nh_family == AF_UNSPEC) ||
IN_SET(nh_family, AF_INET, AF_INET6), -EINVAL);
switch(nhmsg_type) {
case RTM_DELNEXTHOP:
assert_return(nh_family == AF_UNSPEC, -EINVAL);
_fallthrough_;
case RTM_GETNEXTHOP:
assert_return(nh_protocol == RTPROT_UNSPEC, -EINVAL);
break;
case RTM_NEWNEXTHOP:
assert_return(IN_SET(nh_family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL);
break;
default:
assert_not_reached("Invalid message type.");
}
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nhmsg_type);
@ -319,7 +316,7 @@ int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL);
assert_return(m->hdr->nlmsg_type == RTM_NEWNEXTHOP, -EINVAL);
nhm = NLMSG_DATA(m->hdr);
nhm->nh_flags |= flags;
@ -327,18 +324,6 @@ int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
return 0;
}
int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family) {
struct nhmsg *nhm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
nhm = NLMSG_DATA(m->hdr);
nhm->nh_family = family;
return 0;
}
int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) {
struct nhmsg *nhm;
@ -346,7 +331,7 @@ int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *fam
assert_return(m->hdr, -EINVAL);
nhm = NLMSG_DATA(m->hdr);
*family = nhm->nh_family ;
*family = nhm->nh_family;
return 0;
}

View File

@ -66,9 +66,7 @@ static void context_free_vconsole(Context *c) {
}
static void context_free_locale(Context *c) {
int p;
for (p = 0; p < _VARIABLE_LC_MAX; p++)
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
c->locale[p] = mfree(c->locale[p]);
}
@ -85,9 +83,7 @@ void context_clear(Context *c) {
};
void locale_simplify(char *locale[_VARIABLE_LC_MAX]) {
int p;
for (p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
for (LocaleVariable p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++)
if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p]))
locale[p] = mfree(locale[p]);
}
@ -138,13 +134,11 @@ int locale_read_data(Context *c, sd_bus_message *m) {
if (r < 0)
return r;
} else {
int p;
c->locale_mtime = USEC_INFINITY;
context_free_locale(c);
/* Fill in what we got passed from systemd. */
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
const char *name;
name = locale_variable_to_string(p);
@ -294,30 +288,16 @@ int x11_read_data(Context *c, sd_bus_message *m) {
int locale_write_data(Context *c, char ***settings) {
_cleanup_strv_free_ char **l = NULL;
struct stat st;
int r, p;
int r;
/* Set values will be returned as strv in *settings on success. */
for (p = 0; p < _VARIABLE_LC_MAX; p++) {
_cleanup_free_ char *t = NULL;
char **u;
const char *name;
name = locale_variable_to_string(p);
assert(name);
if (isempty(c->locale[p]))
continue;
if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
return -ENOMEM;
u = strv_env_set(l, t);
if (!u)
return -ENOMEM;
strv_free_and_replace(l, u);
}
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++)
if (!isempty(c->locale[p])) {
r = strv_env_assign(&l, locale_variable_to_string(p), c->locale[p]);
if (r < 0)
return r;
}
if (strv_isempty(l)) {
if (unlink("/etc/locale.conf") < 0)
@ -348,39 +328,13 @@ int vconsole_write_data(Context *c) {
if (r < 0 && r != -ENOENT)
return r;
if (isempty(c->vc_keymap))
l = strv_env_unset(l, "KEYMAP");
else {
_cleanup_free_ char *s = NULL;
char **u;
r = strv_env_assign(&l, "KEYMAP", empty_to_null(c->vc_keymap));
if (r < 0)
return r;
s = strjoin("KEYMAP=", c->vc_keymap);
if (!s)
return -ENOMEM;
u = strv_env_set(l, s);
if (!u)
return -ENOMEM;
strv_free_and_replace(l, u);
}
if (isempty(c->vc_keymap_toggle))
l = strv_env_unset(l, "KEYMAP_TOGGLE");
else {
_cleanup_free_ char *s = NULL;
char **u;
s = strjoin("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
if (!s)
return -ENOMEM;
u = strv_env_set(l, s);
if (!u)
return -ENOMEM;
strv_free_and_replace(l, u);
}
r = strv_env_assign(&l, "KEYMAP_TOGGLE", empty_to_null(c->vc_keymap_toggle));
if (r < 0)
return r;
if (strv_isempty(l)) {
if (unlink("/etc/vconsole.conf") < 0)

View File

@ -55,7 +55,6 @@ static void status_info_clear(StatusInfo *info) {
static void print_overridden_variables(void) {
_cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
bool print_warning = true;
LocaleVariable j;
int r;
if (arg_transport != BUS_TRANSPORT_LOCAL)
@ -82,7 +81,7 @@ static void print_overridden_variables(void) {
return;
}
for (j = 0; j < _VARIABLE_LC_MAX; j++)
for (LocaleVariable j = 0; j < _VARIABLE_LC_MAX; j++)
if (variables[j]) {
if (print_warning) {
log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n"

View File

@ -37,8 +37,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) {
_cleanup_strv_free_ char **l_set = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
size_t c_set, c_unset;
LocaleVariable p;
size_t c_set = 0, c_unset = 0;
int r;
assert(bus);
@ -51,7 +50,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) {
if (!l_set)
return log_oom();
for (p = 0, c_set = 0, c_unset = 0; p < _VARIABLE_LC_MAX; p++) {
for (LocaleVariable p = 0; p < _VARIABLE_LC_MAX; p++) {
const char *name;
name = locale_variable_to_string(p);
@ -178,7 +177,7 @@ static int property_get_locale(
Context *c = userdata;
_cleanup_strv_free_ char **l = NULL;
int p, q, r;
int r;
r = locale_read_data(c, reply);
if (r < 0)
@ -188,7 +187,7 @@ static int property_get_locale(
if (!l)
return -ENOMEM;
for (p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
for (LocaleVariable p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) {
char *t;
const char *name;

View File

@ -44,9 +44,9 @@ typedef struct BrightnessWriter {
sd_event_source* child_event_source;
} BrightnessWriter;
static void brightness_writer_free(BrightnessWriter *w) {
static BrightnessWriter* brightness_writer_free(BrightnessWriter *w) {
if (!w)
return;
return NULL;
if (w->manager && w->path)
(void) hashmap_remove_value(w->manager->brightness_writers, w->path, w);
@ -59,7 +59,7 @@ static void brightness_writer_free(BrightnessWriter *w) {
w->child_event_source = sd_event_source_unref(w->child_event_source);
free(w);
return mfree(w);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free);

View File

@ -30,6 +30,7 @@
#include "format-util.h"
#include "fs-util.h"
#include "logind-dbus.h"
#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-user-dbus.h"
@ -1047,15 +1048,7 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
"Session %s not on seat %s", session_name, seat_name);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&m->polkit_registry,
error);
r = check_polkit_chvt(message, m, error);
if (r < 0)
return r;
if (r == 0)

24
src/login/logind-polkit.c Normal file
View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "bus-polkit.h"
#include "logind-polkit.h"
#include "missing_capability.h"
#include "user-util.h"
int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error) {
#if ENABLE_POLKIT
return bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&manager->polkit_registry,
error);
#else
/* Allow chvt when polkit is not present. This allows a service to start a graphical session as a
* non-root user when polkit is not compiled in, more closely matching the default polkit policy */
return 1;
#endif
}

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "bus-object.h"
#include "logind.h"
int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error);

View File

@ -9,6 +9,7 @@
#include "bus-polkit.h"
#include "bus-util.h"
#include "logind-dbus.h"
#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-seat.h"
#include "logind-session-dbus.h"
@ -179,15 +180,7 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b
if (session->seat != s)
return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
@ -215,15 +208,7 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro
if (to <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal");
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
@ -243,15 +228,7 @@ static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus
assert(message);
assert(s);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)
@ -271,15 +248,7 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd
assert(message);
assert(s);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)

View File

@ -11,6 +11,7 @@
#include "fd-util.h"
#include "logind-brightness.h"
#include "logind-dbus.h"
#include "logind-polkit.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-session-device.h"
@ -192,15 +193,7 @@ int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_
assert(message);
assert(s);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.chvt",
NULL,
false,
UID_INVALID,
&s->manager->polkit_registry,
error);
r = check_polkit_chvt(message, s->manager, error);
if (r < 0)
return r;
if (r == 0)

View File

@ -25,6 +25,8 @@ liblogind_core_sources = files('''
logind-device.h
logind-inhibit.c
logind-inhibit.h
logind-polkit.c
logind-polkit.h
logind-seat-dbus.c
logind-seat-dbus.h
logind-seat.c

View File

@ -39,18 +39,16 @@ static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRES
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType);
static void l2tp_session_free(L2tpSession *s) {
static L2tpSession* l2tp_session_free(L2tpSession *s) {
if (!s)
return;
return NULL;
if (s->tunnel && s->section)
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
network_config_section_free(s->section);
free(s->name);
free(s);
return mfree(s);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free);

View File

@ -35,9 +35,9 @@ static void security_association_init(SecurityAssociation *sa) {
sa->use_for_encoding = -1;
}
static void macsec_receive_association_free(ReceiveAssociation *c) {
static ReceiveAssociation* macsec_receive_association_free(ReceiveAssociation *c) {
if (!c)
return;
return NULL;
if (c->macsec && c->section)
ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section);
@ -45,7 +45,7 @@ static void macsec_receive_association_free(ReceiveAssociation *c) {
network_config_section_free(c->section);
security_association_clear(&c->sa);
free(c);
return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free);
@ -90,9 +90,9 @@ static int macsec_receive_association_new_static(MACsec *s, const char *filename
return 0;
}
static void macsec_receive_channel_free(ReceiveChannel *c) {
static ReceiveChannel* macsec_receive_channel_free(ReceiveChannel *c) {
if (!c)
return;
return NULL;
if (c->macsec) {
if (c->sci.as_uint64 > 0)
@ -104,7 +104,7 @@ static void macsec_receive_channel_free(ReceiveChannel *c) {
network_config_section_free(c->section);
free(c);
return mfree(c);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free);
@ -162,9 +162,9 @@ static int macsec_receive_channel_new_static(MACsec *s, const char *filename, un
return 0;
}
static void macsec_transmit_association_free(TransmitAssociation *a) {
static TransmitAssociation* macsec_transmit_association_free(TransmitAssociation *a) {
if (!a)
return;
return NULL;
if (a->macsec && a->section)
ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section);
@ -172,7 +172,7 @@ static void macsec_transmit_association_free(TransmitAssociation *a) {
network_config_section_free(a->section);
security_association_clear(&a->sa);
free(a);
return mfree(a);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free);

View File

@ -26,11 +26,11 @@
static void resolve_endpoints(NetDev *netdev);
static void wireguard_peer_free(WireguardPeer *peer) {
static WireguardPeer* wireguard_peer_free(WireguardPeer *peer) {
WireguardIPmask *mask;
if (!peer)
return;
return NULL;
if (peer->wireguard) {
LIST_REMOVE(peers, peer->wireguard->peers, peer);
@ -54,7 +54,7 @@ static void wireguard_peer_free(WireguardPeer *peer) {
free(peer->preshared_key_file);
explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN);
free(peer);
return mfree(peer);
}
DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free);

View File

@ -230,7 +230,7 @@ static int link_info_compare(const LinkInfo *a, const LinkInfo *b) {
return CMP(a->ifindex, b->ifindex);
}
static const LinkInfo* link_info_array_free(LinkInfo *array) {
static LinkInfo* link_info_array_free(LinkInfo *array) {
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
sd_device_unref(array[i].sd_device);
free(array[i].ssid);

View File

@ -262,16 +262,23 @@ static int address_set_masquerade(Address *address, bool add) {
if (!address->link->network)
return 0;
if (!address->link->network->ip_masquerade)
if (address->family == AF_INET &&
!FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV4))
return 0;
if (address->family != AF_INET)
if (address->family == AF_INET6 &&
!FLAGS_SET(address->link->network->ip_masquerade, ADDRESS_FAMILY_IPV6))
return 0;
if (address->scope >= RT_SCOPE_LINK)
return 0;
if (address->ip_masquerade_done == add)
if (address->family == AF_INET &&
address->ip_masquerade_done == add)
return 0;
if (address->family == AF_INET6 &&
address->ipv6_masquerade_done == add)
return 0;
masked = address->in_addr;
@ -279,11 +286,14 @@ static int address_set_masquerade(Address *address, bool add) {
if (r < 0)
return r;
r = fw_add_masquerade(&address->link->manager->fw_ctx, add, AF_INET, &masked, address->prefixlen);
r = fw_add_masquerade(&address->link->manager->fw_ctx, add, address->family, &masked, address->prefixlen);
if (r < 0)
return r;
address->ip_masquerade_done = add;
if (address->family == AF_INET)
address->ip_masquerade_done = add;
else if (address->family == AF_INET6)
address->ipv6_masquerade_done = add;
return 0;
}

View File

@ -38,6 +38,7 @@ typedef struct Address {
bool scope_set:1;
bool ip_masquerade_done:1;
bool ipv6_masquerade_done:1;
AddressFamily duplicate_address_detection;
/* Called when address become ready */

View File

@ -850,11 +850,11 @@ int manager_new(Manager **ret) {
return 0;
}
void manager_free(Manager *m) {
Manager* manager_free(Manager *m) {
Link *link;
if (!m)
return;
return NULL;
free(m->state_file);
@ -909,7 +909,7 @@ void manager_free(Manager *m) {
m->fw_ctx = fw_ctx_free(m->fw_ctx);
free(m);
return mfree(m);
}
int manager_start(Manager *m) {

View File

@ -83,7 +83,7 @@ struct Manager {
};
int manager_new(Manager **ret);
void manager_free(Manager *m);
Manager* manager_free(Manager *m);
int manager_connect_bus(Manager *m);
int manager_start(Manager *m);

View File

@ -63,7 +63,6 @@ struct IPv6Token {
};
int ipv6token_new(IPv6Token **ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6Token *, freep);
static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));

View File

@ -111,7 +111,7 @@ Network.DNSSEC, config_parse_dnssec_mode,
Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_with_kernel, 0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Network.IPMasquerade, config_parse_address_family_compat, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)

View File

@ -208,9 +208,8 @@ int network_verify(Network *network) {
if (network->link_local < 0)
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
/* IPMasquerade=yes implies IPForward=yes */
if (network->ip_masquerade)
network->ip_forward |= ADDRESS_FAMILY_IPV4;
/* IPMasquerade implies IPForward */
network->ip_forward |= network->ip_masquerade;
network_adjust_ipv6_accept_ra(network);
network_adjust_dhcp(network);

View File

@ -110,7 +110,7 @@ struct Network {
KeepConfiguration keep_configuration;
char **bind_carrier;
bool default_route_on_device;
bool ip_masquerade;
AddressFamily ip_masquerade;
/* DHCP Client Support */
AddressFamily dhcp;

View File

@ -281,10 +281,6 @@ static int nexthop_configure(NextHop *nexthop, Link *link) {
r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw);
if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m");
r = sd_rtnl_message_nexthop_set_family(req, nexthop->family);
if (r < 0)
return log_link_error_errno(link, r, "Could not set nexthop family: %m");
}
r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,

View File

@ -61,6 +61,16 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_addr
DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_deprecated_address_family, AddressFamily);
DEFINE_STRING_TABLE_LOOKUP(dhcp_lease_server_type, sd_dhcp_lease_server_type);
static AddressFamily address_family_compat_from_string(const char *s) {
if (streq_ptr(s, "yes")) /* compat name */
return ADDRESS_FAMILY_IPV4;
if (streq_ptr(s, "both"))
return ADDRESS_FAMILY_YES;
return address_family_from_string(s);
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_compat, address_family_compat,
AddressFamily, "Failed to parse option");
int config_parse_address_family_with_kernel(
const char* unit,
const char *filename,
@ -155,10 +165,6 @@ int network_config_section_new(const char *filename, unsigned line, NetworkConfi
return 0;
}
void network_config_section_free(NetworkConfigSection *cs) {
free(cs);
}
unsigned hashmap_find_free_section_line(Hashmap *hashmap) {
NetworkConfigSection *cs;
unsigned n = 0;

View File

@ -28,6 +28,7 @@ typedef struct NetworkConfigSection {
CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
CONFIG_PARSER_PROTOTYPE(config_parse_address_family_compat);
const char *address_family_to_string(AddressFamily b) _const_;
AddressFamily address_family_from_string(const char *s) _pure_;
@ -47,9 +48,12 @@ sd_dhcp_lease_server_type dhcp_lease_server_type_from_string(const char *s) _pur
int kernel_route_expiration_supported(void);
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
void network_config_section_free(NetworkConfigSection *network);
static inline NetworkConfigSection* network_config_section_free(NetworkConfigSection *cs) {
return mfree(cs);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free);
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s);
extern const struct hash_ops network_config_hash_ops;
unsigned hashmap_find_free_section_line(Hashmap *hashmap);
@ -63,13 +67,14 @@ static inline bool section_is_invalid(NetworkConfigSection *section) {
}
#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \
static inline void free_func##_or_set_invalid(type *p) { \
static inline type* free_func##_or_set_invalid(type *p) { \
assert(p); \
\
if (p->section) \
p->section->invalid = true; \
else \
free_func(p); \
return NULL; \
} \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \
DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid);

View File

@ -134,9 +134,9 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
return 0;
}
void qdisc_free(QDisc *qdisc) {
QDisc* qdisc_free(QDisc *qdisc) {
if (!qdisc)
return;
return NULL;
if (qdisc->network && qdisc->section)
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
@ -144,7 +144,7 @@ void qdisc_free(QDisc *qdisc) {
network_config_section_free(qdisc->section);
free(qdisc->tca_kind);
free(qdisc);
return mfree(qdisc);
}
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {

View File

@ -74,7 +74,7 @@ extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
/* For casting the various qdisc kinds into a qdisc */
#define QDISC(q) (&(q)->meta)
void qdisc_free(QDisc *qdisc);
QDisc* qdisc_free(QDisc *qdisc);
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
int qdisc_configure(Link *link, QDisc *qdisc);

View File

@ -90,16 +90,16 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
return 0;
}
void tclass_free(TClass *tclass) {
TClass* tclass_free(TClass *tclass) {
if (!tclass)
return;
return NULL;
if (tclass->network && tclass->section)
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
network_config_section_free(tclass->section);
free(tclass);
return mfree(tclass);
}
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {

View File

@ -53,7 +53,7 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX];
/* For casting the various tclass kinds into a tclass */
#define TCLASS(t) (&(t)->meta)
void tclass_free(TClass *tclass);
TClass* tclass_free(TClass *tclass);
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
int tclass_configure(Link *link, TClass *tclass);

View File

@ -347,21 +347,18 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
return 0;
}
void manager_free(Manager *m) {
Manager* manager_free(Manager *m) {
if (!m)
return;
return NULL;
hashmap_free_with_destructor(m->links, link_free);
hashmap_free(m->links_by_name);
sd_event_source_unref(m->network_monitor_event_source);
sd_network_monitor_unref(m->network_monitor);
sd_event_source_unref(m->rtnl_event_source);
sd_netlink_unref(m->rtnl);
sd_event_unref(m->event);
free(m);
return;
return mfree(m);
}

View File

@ -32,7 +32,7 @@ struct Manager {
sd_event *event;
};
void manager_free(Manager *m);
Manager* manager_free(Manager *m);
int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
LinkOperationalStateRange required_operstate,
bool any, usec_t timeout);

View File

@ -2,6 +2,7 @@
#include "sd-netlink.h"
#include "af-list.h"
#include "alloc-util.h"
#include "fd-util.h"
#include "firewall-util.h"
@ -82,9 +83,9 @@ void expose_port_free_all(ExposePort *p) {
}
}
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed) {
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, int af, union in_addr_union *exposed) {
ExposePort *p;
int r, af = AF_INET;
int r;
assert(exposed);
@ -106,19 +107,19 @@ int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_uni
p->container_port,
NULL);
if (r < 0)
log_warning_errno(r, "Failed to modify firewall: %m");
log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
}
*exposed = IN_ADDR_NULL;
return 0;
}
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed) {
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, int af, union in_addr_union *exposed) {
_cleanup_free_ struct local_address *addresses = NULL;
union in_addr_union new_exposed;
ExposePort *p;
bool add;
int af = AF_INET, r;
int r;
assert(exposed);
@ -137,7 +138,7 @@ int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *
addresses[0].scope < RT_SCOPE_LINK;
if (!add)
return expose_port_flush(fw_ctx, l, exposed);
return expose_port_flush(fw_ctx, l, af, exposed);
new_exposed = addresses[0].address;
if (in_addr_equal(af, exposed, &new_exposed))
@ -160,7 +161,7 @@ int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *
p->container_port,
in_addr_is_null(af, exposed) ? NULL : exposed);
if (r < 0)
log_warning_errno(r, "Failed to modify firewall: %m");
log_warning_errno(r, "Failed to modify %s firewall: %m", af_to_name(af));
}
*exposed = new_exposed;

View File

@ -23,5 +23,5 @@ int expose_port_parse(ExposePort **l, const char *s);
int expose_port_watch_rtnl(sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, void *userdata, sd_netlink **ret);
int expose_port_send_rtnl(int send_fd);
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, union in_addr_union *exposed);
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, union in_addr_union *exposed);
int expose_port_execute(sd_netlink *rtnl, FirewallContext **fw_ctx, ExposePort *l, int af, union in_addr_union *exposed);
int expose_port_flush(FirewallContext **fw_ctx, ExposePort* l, int af, union in_addr_union *exposed);

View File

@ -1110,17 +1110,13 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'E': {
char **n;
if (!env_assignment_is_valid(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Environment variable assignment '%s' is not valid.", optarg);
r = strv_env_replace_strdup(&arg_setenv, optarg);
if (r < 0)
return r;
n = strv_env_set(arg_setenv, optarg);
if (!n)
return log_oom();
strv_free_and_replace(arg_setenv, n);
arg_settings_mask |= SETTING_ENVIRONMENT;
break;
}
@ -2471,7 +2467,8 @@ static int setup_kmsg(int kmsg_socket) {
}
struct ExposeArgs {
union in_addr_union address;
union in_addr_union address4;
union in_addr_union address6;
struct FirewallContext *fw_ctx;
};
@ -2482,7 +2479,8 @@ static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *user
assert(m);
assert(args);
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, &args->address);
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, AF_INET, &args->address4);
expose_port_execute(rtnl, &args->fw_ctx, arg_expose_ports, AF_INET6, &args->address6);
return 0;
}
@ -4904,7 +4902,8 @@ static int run_container(
if (r < 0)
return r;
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, &expose_args->address);
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, AF_INET, &expose_args->address4);
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, AF_INET6, &expose_args->address6);
}
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
@ -5031,7 +5030,8 @@ static int run_container(
return 0; /* finito */
}
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, &expose_args->address);
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, AF_INET, &expose_args->address4);
expose_port_flush(&expose_args->fw_ctx, arg_expose_ports, AF_INET6, &expose_args->address6);
(void) remove_veth_links(veth_name, arg_network_veth_extra);
*veth_created = false;
@ -5586,7 +5586,8 @@ finish:
(void) rm_rf(p, REMOVE_ROOT);
}
expose_port_flush(&fw_ctx, arg_expose_ports, &expose_args.address);
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET, &expose_args.address4);
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET6, &expose_args.address6);
if (veth_created)
(void) remove_veth_links(veth_name, arg_network_veth_extra);

View File

@ -397,7 +397,7 @@ static int monitor_cgroup_contexts(Manager *m) {
return 0;
}
void manager_free(Manager *m) {
Manager* manager_free(Manager *m) {
assert(m);
varlink_close_unref(m->varlink);
@ -410,7 +410,7 @@ void manager_free(Manager *m) {
hashmap_free(m->monitored_swap_cgroup_contexts);
hashmap_free(m->monitored_mem_pressure_cgroup_contexts);
free(m);
return mfree(m);
}
int manager_new(Manager **ret) {

View File

@ -51,7 +51,7 @@ struct Manager {
Varlink *varlink;
};
void manager_free(Manager *m);
Manager* manager_free(Manager *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
int manager_new(Manager **ret);

View File

@ -1268,10 +1268,10 @@ static int context_read_definitions(
return 0;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_context*, fdisk_unref_context);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_partition*, fdisk_unref_partition);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_parttype*, fdisk_unref_parttype);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct fdisk_table*, fdisk_unref_table);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_context*, fdisk_unref_context, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
static int determine_current_padding(
struct fdisk_context *c,

View File

@ -82,17 +82,16 @@ static const char *dns_cache_item_type_to_string(DnsCacheItem *item) {
return NULL;
}
static void dns_cache_item_free(DnsCacheItem *i) {
static DnsCacheItem* dns_cache_item_free(DnsCacheItem *i) {
if (!i)
return;
return NULL;
dns_resource_record_unref(i->rr);
dns_resource_key_unref(i->key);
dns_answer_unref(i->answer);
dns_packet_unref(i->full_packet);
free(i);
return mfree(i);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) {

View File

@ -240,6 +240,7 @@ static void dns_server_reset_counters(DnsServer *s) {
s->n_failed_tcp = 0;
s->n_failed_tls = 0;
s->packet_truncated = false;
s->packet_invalid = false;
s->verified_usec = 0;
/* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
@ -366,6 +367,17 @@ void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level
log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
}
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
assert(s);
/* Invoked whenever we got a packet we couldn't parse at all */
if (s->possible_feature_level != level)
return;
s->packet_invalid = true;
}
static bool dns_server_grace_period_expired(DnsServer *s) {
usec_t ts;
@ -434,21 +446,46 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
* work. Upgrade back to UDP again. */
log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
} else if (s->n_failed_tls > 0 &&
DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) &&
dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
/* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
* if we don't require DNS-over-TLS */
log_debug("Server doesn't support DNS-over-TLS, downgrading protocol...");
s->possible_feature_level--;
} else if (s->packet_bad_opt &&
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
/* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below
* EDNS0 levels. After all, some records generate different responses with and without OPT RR
* in the request. Example:
* https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */
} else if (s->packet_invalid &&
s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN) {
/* Downgrade from DO to EDNS0 + from EDNS0 to UDP, from TLS+DO to plain TLS. Or in
* other words, if we receive a packet we cannot parse jump to the next lower feature
* level that actually has an influence on the packet layout (and not just the
* transport). */
log_debug("Got invalid packet from server, downgrading protocol...");
s->possible_feature_level =
s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TLS_DO ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_EDNS0 :
DNS_SERVER_FEATURE_LEVEL_UDP;
} else if (s->packet_bad_opt &&
DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(s->possible_feature_level) &&
dns_server_get_dnssec_mode(s) != DNSSEC_YES &&
dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
/* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to
* below EDNS0 levels. After all, some servers generate different responses with and
* without OPT RR in the request. Example:
*
* https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html
*
* If we are in strict DNSSEC or DoT mode, we don't do this kind of downgrade
* however, as both modes imply EDNS0 to work (DNSSEC strictly requires it, and DoT
* only in our implementation). */
log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
@ -458,42 +495,57 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
log_level = LOG_NOTICE;
} else if (s->packet_rrsig_missing &&
s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) {
DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
/* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't
* augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore,
* after all some servers generate different replies depending if an OPT RR is in the query or
* not. */
/* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server
* doesn't augment responses with DNSSEC RRs. If so, let's better not ask the server
* for it anymore, after all some servers generate different replies depending if an
* OPT RR is in the query or not. If we are in strict DNSSEC mode, don't allow such
* downgrades however, since a DNSSEC feature level is a requirement for strict
* DNSSEC mode. */
log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
DNS_SERVER_FEATURE_LEVEL_EDNS0;
} else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
((s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_DO) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
/* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the
* packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good
* idea. We might downgrade all the way down to TCP this way.
/* We lost too many UDP packets in a row, and are on an UDP feature level. If the
* packets are lost, maybe the server cannot parse them, hence downgrading sounds
* like a good idea. We might downgrade all the way down to TCP this way.
*
* If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss
* might have many reasons, a broken DNSSEC implementation being only one reason. And if the
* user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */
log_debug("Lost too many UDP packets, downgrading feature level...");
s->possible_feature_level--;
if (s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_DO) /* skip over TLS_PLAIN */
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
else
s->possible_feature_level--;
} else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
s->packet_truncated &&
s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) {
s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
(!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
/* We got too many TCP connection failures in a row, we had at least one truncated packet, and
* are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0
* data we hope to make the packet smaller, so that it still works via UDP given that TCP
* appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't
* go further down, since that's TCP, and TCP failed too often after all. */
/* We got too many TCP connection failures in a row, we had at least one truncated
* packet, and are on feature level above UDP. By downgrading things and getting rid
* of DNSSEC or EDNS0 data we hope to make the packet smaller, so that it still
* works via UDP given that TCP appears not to be a fallback. Note that if we are
* already at the lowest UDP level, we don't go further down, since that's TCP, and
* TCP failed too often after all. */
log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
s->possible_feature_level--;
if (DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level))
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; /* Go DNSSEC → EDNS0 */
else
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; /* Go EDNS0 → UDP */
}
if (p != s->possible_feature_level) {
@ -589,7 +641,10 @@ bool dns_server_dnssec_supported(DnsServer *server) {
/* Returns whether the server supports DNSSEC according to what we know about it */
if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO)
if (dns_server_get_dnssec_mode(server) == DNSSEC_YES) /* If strict DNSSEC mode is enabled, always assume DNSSEC mode is supported. */
return true;
if (!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(server->possible_feature_level))
return false;
if (server->packet_bad_opt)
@ -903,13 +958,15 @@ void dns_server_dump(DnsServer *s, FILE *f) {
"\tFailed TCP attempts: %u\n"
"\tSeen truncated packet: %s\n"
"\tSeen OPT RR getting lost: %s\n"
"\tSeen RRSIG RR missing: %s\n",
"\tSeen RRSIG RR missing: %s\n"
"\tSeen invalid packet: %s\n",
s->received_udp_packet_max,
s->n_failed_udp,
s->n_failed_tcp,
yes_no(s->packet_truncated),
yes_no(s->packet_bad_opt),
yes_no(s->packet_rrsig_missing));
yes_no(s->packet_rrsig_missing),
yes_no(s->packet_invalid));
}
void dns_server_unref_stream(DnsServer *s) {

View File

@ -40,7 +40,10 @@ typedef enum DnsServerFeatureLevel {
#define DNS_SERVER_FEATURE_LEVEL_WORST 0
#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1)
#define DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
#define DNS_SERVER_FEATURE_LEVEL_IS_TLS(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, DNS_SERVER_FEATURE_LEVEL_TLS_DO)
#define DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(x) ((x) >= DNS_SERVER_FEATURE_LEVEL_DO)
#define DNS_SERVER_FEATURE_LEVEL_IS_UDP(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_UDP, DNS_SERVER_FEATURE_LEVEL_EDNS0, DNS_SERVER_FEATURE_LEVEL_DO, DNS_SERVER_FEATURE_LEVEL_LARGE)
const char* dns_server_feature_level_to_string(int i) _const_;
int dns_server_feature_level_from_string(const char *s) _pure_;
@ -78,9 +81,10 @@ struct DnsServer {
unsigned n_failed_tcp;
unsigned n_failed_tls;
bool packet_truncated:1;
bool packet_bad_opt:1;
bool packet_rrsig_missing:1;
bool packet_truncated:1; /* Set when TC bit was set on reply */
bool packet_bad_opt:1; /* Set when OPT was missing or otherwise bad on reply */
bool packet_rrsig_missing:1; /* Set when RRSIG was missing */
bool packet_invalid:1; /* Set when we failed to parse a reply */
usec_t verified_usec;
usec_t features_grace_period_usec;
@ -119,6 +123,7 @@ void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level);
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level);
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);

View File

@ -162,23 +162,23 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
bool dns_transaction_gc(DnsTransaction *t) {
DnsTransaction* dns_transaction_gc(DnsTransaction *t) {
assert(t);
/* Returns !NULL if we can't gc yet. */
if (t->block_gc > 0)
return true;
return t;
if (set_isempty(t->notify_query_candidates) &&
set_isempty(t->notify_query_candidates_done) &&
set_isempty(t->notify_zone_items) &&
set_isempty(t->notify_zone_items_done) &&
set_isempty(t->notify_transactions) &&
set_isempty(t->notify_transactions_done)) {
dns_transaction_free(t);
return false;
}
set_isempty(t->notify_transactions_done))
return dns_transaction_free(t);
return true;
return t;
}
static uint16_t pick_new_id(Manager *m) {
@ -502,7 +502,12 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
assert(t);
log_debug("Retrying transaction %" PRIu16 ".", t->id);
/* Retries the transaction as it is, possibly on a different server */
if (next_server)
log_debug("Retrying transaction %" PRIu16 ", after switching servers.", t->id);
else
log_debug("Retrying transaction %" PRIu16 ".", t->id);
/* Before we try again, switch to a new server. */
if (next_server)
@ -513,12 +518,25 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
dns_transaction_complete_errno(t, r);
}
static bool dns_transaction_limited_retry(DnsTransaction *t) {
assert(t);
/* If we haven't tried all different servers yet, let's try again with a different server */
if (t->n_picked_servers >= dns_scope_get_n_dns_servers(t->scope))
return false;
dns_transaction_retry(t, /* next_server= */ true);
return true;
}
static int dns_transaction_maybe_restart(DnsTransaction *t) {
int r;
assert(t);
/* Returns > 0 if the transaction was restarted, 0 if not */
/* Restarts the transaction, under a new ID if the feature level of the server changed since we first
* tried, without changing DNS server. Returns > 0 if the transaction was restarted, 0 if not. */
if (!t->server)
return 0;
@ -911,11 +929,8 @@ static void dns_transaction_process_dnssec(DnsTransaction *t) {
/* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe
* that works. */
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
/* We tried fewer servers on this transaction than we know, let's try another one then */
dns_transaction_retry(t, true);
if (dns_transaction_limited_retry(t))
return;
}
/* OK, let's give up, apparently all servers we tried didn't work. */
dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED);
@ -1098,11 +1113,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
* packet loss, but is not going to give us better rcodes should we actually have
* managed to get them already at UDP level. */
if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) {
/* We tried fewer servers on this transaction than we know, let's try another one then */
dns_transaction_retry(t, true);
if (dns_transaction_limited_retry(t))
return;
}
/* Give up, accept the rcode */
log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p)));
@ -1133,8 +1145,11 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) {
/* This server refused our request? If so, try again, use a different server */
log_debug("Server returned REFUSED, switching servers, and retrying.");
dns_transaction_retry(t, true /* pick a new server */);
return;
if (dns_transaction_limited_retry(t))
return;
break;
}
if (DNS_PACKET_TC(p))
@ -1180,7 +1195,11 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
goto fail;
/* On DNS, couldn't send? Try immediately again, with a new server */
dns_transaction_retry(t, true);
if (dns_transaction_limited_retry(t))
return;
/* No new server to try, give up */
dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
}
return;
@ -1189,6 +1208,16 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
/* After the superficial checks, actually parse the message. */
r = dns_packet_extract(p);
if (r < 0) {
if (t->server) {
dns_server_packet_invalid(t->server, t->current_feature_level);
r = dns_transaction_maybe_restart(t);
if (r < 0)
goto fail;
if (r > 0) /* Transaction got restarted... */
return;
}
dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
return;
}
@ -1296,7 +1325,10 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
dns_transaction_close_connection(t, /* use_graveyard = */ false);
dns_transaction_retry(t, true);
if (dns_transaction_limited_retry(t)) /* Try a different server */
return 0;
dns_transaction_complete_errno(t, r);
return 0;
}
if (r < 0) {
@ -1415,7 +1447,8 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat
log_debug("Timeout reached on transaction %" PRIu16 ".", t->id);
dns_transaction_retry(t, true);
dns_transaction_retry(t, true); /* try a different server, but given this means packet loss, let's do
* so even if we already tried a bunch */
return 0;
}

View File

@ -140,7 +140,7 @@ struct DnsTransaction {
int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key, DnsPacket *bypass, uint64_t flags);
DnsTransaction* dns_transaction_free(DnsTransaction *t);
bool dns_transaction_gc(DnsTransaction *t);
DnsTransaction* dns_transaction_gc(DnsTransaction *t);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
int dns_transaction_go(DnsTransaction *t);

View File

@ -26,16 +26,15 @@ void dns_zone_item_probe_stop(DnsZoneItem *i) {
dns_transaction_gc(t);
}
static void dns_zone_item_free(DnsZoneItem *i) {
static DnsZoneItem* dns_zone_item_free(DnsZoneItem *i) {
if (!i)
return;
return NULL;
dns_zone_item_probe_stop(i);
dns_resource_record_unref(i->rr);
free(i);
return mfree(i);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free);
static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {

View File

@ -11,7 +11,7 @@
#include "resolved-manager.h"
#define TLS_PROTOCOL_PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gnutls_session_t, gnutls_deinit, NULL);
static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) {
int r;

View File

@ -21,13 +21,13 @@ int fd_add_uid_acl_permission(int fd, uid_t uid, unsigned mask);
/* acl_free takes multiple argument types.
* Multiple cleanup functions are necessary. */
DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(acl_t, acl_free, NULL);
#define acl_free_charp acl_free
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, acl_free_charp, NULL);
#define acl_free_uid_tp acl_free
DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(uid_t*, acl_free_uid_tp, NULL);
#define acl_free_gid_tp acl_free
DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(gid_t*, acl_free_gid_tp, NULL);
#else
#define ACL_READ 0x04

View File

@ -123,14 +123,15 @@ int barrier_create(Barrier *b) {
*
* If @b is NULL, this is a no-op.
*/
void barrier_destroy(Barrier *b) {
Barrier* barrier_destroy(Barrier *b) {
if (!b)
return;
return NULL;
b->me = safe_close(b->me);
b->them = safe_close(b->them);
safe_close_pair(b->pipe);
b->barriers = 0;
return NULL;
}
/**

View File

@ -37,7 +37,7 @@ struct Barrier {
#define BARRIER_NULL {-1, -1, {-1, -1}, 0}
int barrier_create(Barrier *obj);
void barrier_destroy(Barrier *b);
Barrier* barrier_destroy(Barrier *b);
DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy);

View File

@ -24,11 +24,11 @@
#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8))
#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem))
Bitmap *bitmap_new(void) {
Bitmap* bitmap_new(void) {
return new0(Bitmap, 1);
}
Bitmap *bitmap_copy(Bitmap *b) {
Bitmap* bitmap_copy(Bitmap *b) {
Bitmap *ret;
ret = bitmap_new();
@ -43,12 +43,12 @@ Bitmap *bitmap_copy(Bitmap *b) {
return ret;
}
void bitmap_free(Bitmap *b) {
Bitmap* bitmap_free(Bitmap *b) {
if (!b)
return;
return NULL;
free(b->bitmaps);
free(b);
return mfree(b);
}
int bitmap_ensure_allocated(Bitmap **b) {

View File

@ -12,10 +12,10 @@ typedef struct Bitmap {
size_t bitmaps_allocated;
} Bitmap;
Bitmap *bitmap_new(void);
Bitmap *bitmap_copy(Bitmap *b);
Bitmap* bitmap_new(void);
Bitmap* bitmap_copy(Bitmap *b);
int bitmap_ensure_allocated(Bitmap **b);
void bitmap_free(Bitmap *b);
Bitmap* bitmap_free(Bitmap *b);
int bitmap_set(Bitmap *b, unsigned n);
void bitmap_unset(Bitmap *b, unsigned n);

View File

@ -6,5 +6,5 @@
# include "macro.h"
DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(blkid_probe, blkid_free_probe, NULL);
#endif

Some files were not shown because too many files have changed in this diff Show More