Commit Graph
2157 Commits
Author SHA1 Message Date
Siteshwar Vashisht 00ca860b2c ndisc: fix an out of memory condition
... and skip the loop when building NDisc option fails.
2026-09-03 05:53:35 +09:00
Yu WatanabeandSiteshwar Vashisht 9064524e44 ndisc: fix a memory leak in ndisc_option_parse_encrypted_dns()
Newly allocated new_res variable was left unreferenced if memory
allocation failed in ndisc_option_add_encrypted_dns_internal().

Co-authored-by: Siteshwar Vashisht <svashisht@redhat.com>
2026-09-01 01:00:15 +09:00
Yu Watanabe 90481c0b1b tree-wide: add missing assertions
Found by coccinelle.
2026-08-18 06:30:10 +09:00
Yu Watanabe 05f790da8f dhcp: drop unnecessary !!
Found by coccinelle.
2026-08-18 03:33:37 +09:00
Anton Tiurin 7bd9f0f805 dhcp-server: reject pool offsets beyond the subnet (#43389)
`sd_dhcp_server_configure_pool()` calculated the maximum pool size
before checking whether `PoolOffset=` was inside the subnet.

Because the calculation used unsigned arithmetic, an offset beyond the
broadcast address could wrap around to a large value and pass validation.
For example, `PoolOffset=256` with a `/24` and `PoolSize=1` was accepted,
allowing the DHCP server to offer an address outside its configured subnet.

Reject offsets at or beyond the broadcast address before performing the
subtraction, and calculate the remaining pool size directly as
`broadcast_off - offset`.
2026-08-16 03:35:45 +09:00
Ronan Pigott c6c6a3f3fd test-ndisc-send: correct add_link_layer_address argument order
Found by inspection while working on networkd.
2026-07-24 13:44:32 +09:00
hanjinpeng 90739ac251 sd-dhcp-relay: fix off-by-one when discarding BOOTREQUEST messages by hops count
According to RFC specifications
```
RFC 1542 section 4.1.1 states:
The relay agent MUST silently discard BOOTREQUEST messages whose 'hops'
   field exceeds the value 16."
```

"Exceeds the value 16" means hops > 16, i.e. a message that arrives with
hops == 16 is still valid and must be relayed (after which its hops field
becomes 17). The code used ">= 16", which silently dropped a valid message
that had legitimately traversed exactly 16 relay agents, one hop too early.

This matches the wording of the adjacent comment, which already says
"exceeds the value 16".
2026-07-15 08:44:31 +09:00
Yu Watanabe 01e1303f9c Rename basic-forward.h, sd-forward.h, and shared-forward.h to forward.h
Follow-up for 74d392ed1b.
2026-07-15 02:18:05 +09:00
Luca Boccassi 8baed40298 ndisc: reject non-zero ICMPv6 codes in parsers
NDisc packets received through the socket path are filtered before
parser dispatch, but parser entry points should still reject malformed
packet bytes instead of asserting on them. Return EBADMSG for non-zero
ICMPv6 code values in RA, NA, and Redirect messages.

Follow-up for c34cb1d645
Follow-up for 696eb2b8de
Follow-up for 44e8cf303b
2026-07-11 17:07:53 +01:00
Zbigniew Jędrzejewski-Szmek f00ccf93b7 meson: rename extract+objects to export+import
We have two concepts: a list of files that should be extracted from an
intermediate build artifact to be used in a later build artifact, and for a
given artifact, a list "donors". The first list was called "extract", because
it is passed to the .extract_objects() meson function, and the second was
called "objects", because that is the meson parameter to specify pre-built
objects files (6350d2dbd9). But this naming is
confusing: we don't care about the 'extract' step, this is something internal
to the build machinery. And 'objects' is a very generic term.

Let's use 'export' for the stuff that is "exported" for other binaries to use,
and 'import' to say where to import from. Those terms are symmetrical and the
association between them should be intuitive. (If you think the terms are
actually assymetrical, there are precedents for confusing the import with the
import sources. E.g. in modern English, turkeys are called so because they were
imported from the Americas and guineafowls were imported from Africa via
Türkiye and all that foreign stuff is alike.)
2026-07-07 13:40:13 +02:00
Lennart Poettering b2fcb12af9 networkd/resolved hardening fixes flagged by kres (#42736) 2026-06-25 17:13:58 +02:00
Luca Boccassi f98629421b dhcp6: reject IA_PD_PREFIX with invalid prefix length
dhcp6_option_parse_ia_pdprefix() validates the lifetimes but never the
prefixlen byte, so a delegated prefix with prefixlen == 0 or > 128 is
stored in the lease and handed over.

RFC 8415 defines the prefix length as 1 to 128, and the send-side
option_append_pd_prefix() already rejects 0, so reject the out-of-range
values on the receive path too.

Follow-up for f8ad4dd45d
2026-06-25 10:16:26 +01:00
Luca Boccassi a762c92a7c sd-lldp-rx: keep object ref around event callbacks
If the user callback set via sd_lldp_rx_set_callback() drops the last
reference to the sd_lldp_rx object, trying to use it later does not go
well. Take a ref to keep the objects alive as long as they are needed.
2026-06-25 10:16:26 +01:00
Luca Boccassi 2e79d397a4 dhcp-message-dump: guard against negative option type before indexing
dhcp_option_type_from_code() returns _DHCP_OPTION_TYPE_INVALID (-EINVAL)
for the PAD and END option codes, and dump_dhcp_option_one() uses the
returned value directly as an index into the functions[] table. Those
codes are excluded by an assert() at the top of the function, but
assert() compiles down to __builtin_unreachable() under NDEBUG, so a
negative array index read is reachable there (and trips static
analyzers). Bail out explicitly on the error return.

CID#1660105

Follow-up for 149adb2fdc
2026-06-24 19:06:21 +01:00
Yu Watanabe 33faf6e070 fuzz-dhcp-client: do not trigger assertion on building payload
Fixes oss-fuzz#521277316 (https://issues.oss-fuzz.com/issues/521277316).
Fixes #42516.
2026-06-08 20:29:59 +01:00
Zbigniew Jędrzejewski-Szmek cd79e5620b dhcp: update test and header cleanup (#42256) 2026-05-27 14:23:34 +02:00
Chris Mason 3f0aa5852e libsystemd-network: propagate sd_event_default() failure
Four *_attach_event helpers swallow sd_event_default() failures and
return success while leaving obj->event NULL:

    sd_dhcp_client_attach_event   (sd-dhcp-client.c)
    sd_dhcp6_client_attach_event  (sd-dhcp6-client.c)
    sd_ndisc_attach_event         (sd-ndisc.c)
    sd_radv_attach_event          (sd-radv.c)

Each contains the same copy-pasted typo in the NULL-event branch:

    r = sd_event_default(&obj->event);
    if (r < 0)
            return 0;          /* swallows -ENOMEM / -ECHILD */

The caller is told the attach succeeded, but obj->event is still
NULL. A subsequent *_start() then trips assert_return(obj->event,
-EINVAL) and returns a spurious -EINVAL (or aborts on assert-abort
builds), and any consumer of *_get_event() dereferences NULL.

The sibling helper sd_dhcp_server_attach_event already uses the
correct pattern:

    r = sd_event_default(&server->event);
    if (r < 0)
            return r;

Fix by returning r instead of 0 at each of the four sites so the
sd_event_default() errno is propagated to the caller and ownership
stays with the caller.

Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:20:03 +02:00
Chris Mason 700d8e73d4 sd-dhcp6-client: fix ref leak on duplicate option add
sd_dhcp6_client_add_option() and sd_dhcp6_client_add_vendor_option()
store the caller's sd_dhcp6_option in an ordered container whose value
destructor is sd_dhcp6_option_unref, registered via
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR in dhcp6_option_hash_ops. The
container therefore owns exactly one ref per stored slot.

Both helpers guarded the ref bump only on r < 0:

    r = ordered_{hashmap,set}_ensure_put(..., v);
    if (r < 0)
            return r;
    sd_dhcp6_option_ref(v);

ordered_hashmap_ensure_put() (and the ordered_set wrapper) forward the
underlying hashmap_put_boldly tri-state verbatim: 1 on fresh insert, 0
when the identical key+value pair is already stored (no new slot
allocated), <0 on error. The r == 0 path fell through and bumped the
refcount without a corresponding slot.

The extra ref is permanently stranded once the container's destructor
runs. In a long-running networkd that reapplies .network files on
reload this leaks one sd_dhcp6_option allocation per duplicate-add.

Fix by tightening the guard to r <= 0 in both helpers, so
sd_dhcp6_option_ref(v) is reached only on a genuine new slot (r == 1).
Propagate the tri-valued result by returning r from both helpers
instead of a hard-coded constant.

sd_dhcp6_client_add_vendor_option() is a public libsystemd sd_ API;
its success return changes from a constant 1 to {0, 1}.
sd_dhcp6_client_add_option() now also propagates the tri-valued
result (previously a hard-coded 0 on success), giving the two parallel
helpers identical return contracts.

The sole non-fuzz in-tree callers are both in dhcp6_configure()
(src/network/networkd-dhcp6.c), which treat any r >= 0 as success and
do not distinguish 0 from 1, so the contract widening is caller-safe.

Fixes: e7d5fe17db ("DHCP client: make SendOption work for DHCPv6 too.")
Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
2026-05-22 22:17:28 +02:00
Yu Watanabe 76ae87e222 dhcp: introduce dhcp-forward.h
Then, rework header inclusions for DHCP related files.
2026-05-22 23:06:54 +09:00
Yu Watanabe db8f504afb dhcp: drop unused functions and macros
This removes the legacy functions for manipulating DHCP message.

This also moves the definition of struct sd_dhcp_message into
dhcp-message.h.
2026-05-22 23:06:53 +09:00
Yu Watanabe f1c47ab00b test-dhcp-server: use sd_dhcp_message object to build test message 2026-05-22 23:06:53 +09:00
Yu Watanabe e75c406448 sd-dhcp-server-lease: always update all information in bound lease
We manage bound leases by their client ID. Hence, potentially, other
fields may be changed. Let's always update all information.
2026-05-22 22:11:45 +09:00
Yu Watanabe c130068ebd sd-dhcp-server: update conditions when we should send DHCPNAK (#42252) 2026-05-22 20:02:17 +09:00
Yu Watanabe d69d919379 dhcp-server-request: drop unused value in DHCPRequest 2026-05-22 19:47:48 +09:00
Yu Watanabe b4f7e30d0b dhcp-server-request: rename dhcp_server_handle_message() -> dhcp_server_process_message()
Then, make it take struct iovec.
No functional change, just refactoring.
2026-05-22 15:57:06 +09:00
Yu Watanabe e294a8eada dhcp-server-request: rework when we should reply DHCPNAK
Previously, DHCPNAK was sent only when the client is in INIT-REBOOT
state. But, on selecting or renewing, the request is directed to a
specific server, so we can safely reply with DHCPNAK.

Also, verify existing bound lease even when there is no static lease for
the client.
2026-05-22 15:57:06 +09:00
Yu Watanabe 94b39d22dd dhcp-server-request: logs more when received invalid messages 2026-05-22 15:57:06 +09:00
Yu Watanabe c73478d49f dhcp-server-request: also save IP_PKTINFO of received message
It will be used later.

This also drops redundant ifindex check, as the socket is already
initialized with socket_bind_to_ifindex().
2026-05-22 15:57:06 +09:00
Yu Watanabe dced69aba5 sd-dhcp-server: use sd_dhcp_message to parse/build DHCP messages (#42240) 2026-05-22 15:28:52 +09:00
Yu Watanabe 30200eee52 sd-dhcp-server: drop unused enum
Follow-up for 2e5580a8c1.
2026-05-22 06:58:45 +02:00
Yu Watanabe 15103b697d sd-dhcp-server: use sd_dhcp_message object on sending reply
This also makes the conditions in dhcp_server_send_message() uses
the message that will be sent, rather than we received.

This does not change basic functionality, but changes/fixes several
minor behaviors, e.g.
- fix when the broadcast flag assignment,
- set server identifier in DHCPFORCERENEW.
2026-05-22 09:38:29 +09:00
Yu Watanabe 5e08ff899e sd-dhcp-server: use sd_dhcp_message to parse received messages
This is mostly refactoring. This does not change basic behavior, but
changes/fixes some minor/corner cases, e.g.

- extend the minimum default lease time from 1 second to 30 seconds, as
  1 second is too short and causes the network unstable (though 30
  seconds is stll too short, but hopefully that does not make the
  network unstable).
- error code on broken/malicious message received may be changed.
2026-05-22 09:33:15 +09:00
Yu Watanabe 8c09b8f128 dhcp-server-request: drop invalid short-cut logic
Even if no pool is allocated, the server may have a static lease
matching with the DHCPDISCOVER message.
2026-05-22 08:34:42 +09:00
Yu Watanabe 05c295d269 dhcp: move definition of enum DHCPState to dhcp-protocol.[ch]
It will be also used in DHCP server, later.
2026-05-22 08:34:22 +09:00
Yu Watanabe d40d021ca5 dhcp-server-request: check server address in DHCPDECLINE and DHCPRELEASE
Otherwise, we may do something wrong by messages for another DHCP server.
Let's silently ignore messages with unmatching server identifier.

Also, logs something when we receive DHCPRELEASE but found lease does
not match the reported address.
2026-05-22 04:30:34 +09:00
Yu Watanabe e359c6df65 sd-dhcp-server: store more information in DHCPRequest
This makes DHCPRequest stores
- the message type of the received message,
- acquired address,
- found static DHCP lease,

This also moves call of dhcp_request_get_lifetime_timestamp() from
dhcp_server_ack() to dhcp_server_set_lease(), and rename
DHCPRequest.server_id -> .server_address.

No functional change, just refactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 252f3855fe sd-dhcp-server: use struct hw_addr_data to manage client hardware address parsed from DHCP message
Then, this drops garbage in DHCP server lease in DBus and Varlink message.

This also drops fallback to use client ID as hardware address when chaddr
field is not set. In that case, we should broadcast reply.
2026-05-22 04:30:34 +09:00
Yu Watanabe dae51cc08e dhcp-server-send: rework sending DHCP reply message
This should mostly not change anything, except for some corner cases.
Just refactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 29b662184b sd-dhcp-server: make IP service type (TOS) configurable 2026-05-22 04:30:34 +09:00
Yu Watanabe 0bb26684d0 sd-dhcp-server: refactoring for socket fd handling
This makes
- UDP socket fd is owned by IO event source,
- open RAW socket fd just before sending first packet,
- set TOS and socket priority,
- use AF_UNIX soxket pair in the unit test and fuzzer, so the unit test
  can now run by unprivileged user.
2026-05-22 04:30:34 +09:00
Yu Watanabe 27d99475b6 dhcp-serve-request: move message size check to dhcp_server_handle_message() 2026-05-22 04:30:34 +09:00
Yu Watanabe 45a3a3b92c dhcp-server-request: modernize server_receive_message() 2026-05-22 04:30:34 +09:00
Yu Watanabe 3f8d0004e9 sd-dhcp-server: split into small pieaces
No functional change, just several functions are moved/split/renamed.
2026-05-22 04:30:34 +09:00
Yu Watanabe 0e07870f59 test-dhcp-server: several cleanups
No effective change, just rafactoring.
2026-05-22 04:30:34 +09:00
Yu Watanabe 54c97ce6a4 sd-dhcp-server: drop legacy DHCP relay mode 2026-05-21 16:55:59 +09:00
Yu Watanabe 0ff6bace59 fuzz: introduce fuzzer for DHCP relay agent 2026-05-21 16:55:59 +09:00
Yu Watanabe 0325022c15 test: add unit test for DHCP relay agent 2026-05-21 16:55:59 +09:00
Yu Watanabe 06ce0f90a5 sd-dhcp-relay: introduce new DHCP relay agent
Previously, sd-dhcp-server can be run as a DHCP relay agent.
But, DHCP server and DHCP relay agent behave completely differently,
hence there is almost no code that can be shared between the two modes.
Let's split out the DHCP relay agent feature from sd-dhcp-server.

The new DHCP relay agent supports:
- multiple upstream and downstream interfaces,
- gateway address (giaddr field in DHCP message header) is configurable,
- supports more DHCP relay agent information sub-options,
- each interface has their own socket fd, and each socket is bound to
  the interface, so that we can enable/disable each interface
  safely without affecting other interfaces, and we can filter out any
  unexpected packets from unmanaged interfaces,

networkd integration and test cases will be added later.
2026-05-21 16:55:58 +09:00
Daan De Meyer 74d392ed1b tree-wide: standardize header names across src/fundamental, src/basic and src/shared
Drop the -fundamental suffix from src/fundamental/ headers in favor of names
that match their src/basic/ or src/shared/ counterparts (e.g.
macro-fundamental.h -> macro.h, assert-fundamental.h -> assert-util.h,
cleanup-fundamental.h -> cleanup-util.h). Rename src/basic/{btrfs,label}.{c,h}
to use the -util suffix to match the existing shared/btrfs-util and
shared/label-util siblings. Rename src/shared/mkdir-label.{c,h} to mkdir.{c,h}
and src/shared/tmpfile-util-label.{c,h} to tmpfile-util.{c,h} to match the
corresponding src/basic names.

This saves us from having to come up with separate names for files that do
the same thing across tiers, and it makes it easier to move stuff between
src/fundamental, src/basic and src/shared: consumers just #include "foo.h"
and pick up whichever tier their -I path resolves to first, so call sites
don't need to be updated when an API moves between layers.

Where a higher-tier wrapper exists (e.g. src/basic/macro.h wrapping
src/fundamental/macro.h), the wrapper uses an explicit "../fundamental/foo.h"
or "../basic/foo.h" relative include for the lower-tier header. We can't use
GCC's #include_next directive for this — when the wrapper is reachable both
via same-dir-as-source lookup and via -I (e.g. -Isrc/shared) for the
directory it lives in, #include_next advances by exactly one slot in libcpp's
internal directory chain and lands on the same physical directory it was
already in, never reaching the lower-tier sibling (see make_cpp_dir() in
gcc/libcpp/files.cc:1986).

To make sure the right headers are always picked up, the include directories
are reordered so that e.g. src/shared always takes priority over src/basic and
similar for the other directories.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 10:33:03 +09:00
Patrick Rohr b131473ce5 networkd: fix race condition in per-interface ICMPv6 processing
There exists a small window of time in icmp6_bind() between creating the
ICMPv6 socket and binding it to an ifindex, where the link-scoped socket
can process an ICMPv6 packet received on any interface. The applies to
both sd-radv and sd-ndisc codepaths.

This change adds an explicit check for ifindex on the receive path and
ignores packets received on other interfaces.

Co-developed-by: OpenAI Codex <noreply@openai.com>
2026-05-20 10:26:39 +09:00