]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fuzz-dhcp-client: fuzz dhcp_client_parse_message()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 1 Apr 2026 13:52:12 +0000 (22:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 16 May 2026 13:34:25 +0000 (22:34 +0900)
Also, if the fuzzing engine provides a valid message, then try to build
json variant and UDP payload from the parsed message. We will drop
dhcp_lease_save() and dhcp_lease_load(), hence the tests for them are
dropped.

src/libsystemd-network/fuzz-dhcp-client.c

index d6a2577194d51afd176746c8ac48a4fe0c1d0140..bc6be37be80d66a1f6462b59e329e66de39bd52a 100644 (file)
@@ -1,14 +1,19 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <net/if_arp.h>
 #include <sys/socket.h>
 
+#include "sd-event.h"
+#include "sd-json.h"
+
+#include "dhcp-client-internal.h"
+#include "dhcp-lease-internal.h"
+#include "dhcp-message.h"
 #include "dhcp-network.h"
-#include "fd-util.h"
 #include "fuzz.h"
-#include "network-internal.h"
-#include "sd-dhcp-client.c"
+#include "iovec-util.h"
+#include "iovec-wrapper.h"
 #include "tests.h"
-#include "tmpfile-util.h"
 
 int dhcp_network_bind_raw_socket(
                 int ifindex,
@@ -61,14 +66,30 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
         client->xid = 2;
         client->state = DHCP_STATE_SELECTING;
 
-        if (client_handle_offer_or_rapid_ack(client, (DHCPMessage*) data, size, NULL) >= 0) {
-                _cleanup_(unlink_tempfilep) char lease_file[] = "/tmp/fuzz-dhcp-client.XXXXXX";
-                _unused_ _cleanup_close_ int fd = ASSERT_OK(mkostemp_safe(lease_file));
+        _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
+        if (dhcp_client_parse_message(client, &IOVEC_MAKE(data, size), &lease) >= 0) {
+                /* Build json variant and parse it. */
+                _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+                ASSERT_OK(dhcp_message_build_json(lease->message, &v));
+
+                _cleanup_(sd_dhcp_message_unrefp) sd_dhcp_message *m = NULL;
+                ASSERT_OK(dhcp_message_parse_json(v, &m));
+
+                /* Build UDP payload and parse it. */
+                _cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
+                ASSERT_OK(dhcp_message_build(lease->message, &iovw));
+
+                _cleanup_(iovec_done) struct iovec iov = {};
+                ASSERT_OK(iovw_concat(&iovw, &iov));
+
+                _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease2 = NULL;
+                ASSERT_OK(dhcp_client_parse_message(client, &iov, &lease2));
 
-                ASSERT_OK(dhcp_lease_save(client->lease, lease_file));
+                /* Build UDP payload again, and compare with the previous one. */
+                _cleanup_(iovw_done_free) struct iovec_wrapper iovw2 = {};
+                ASSERT_OK(dhcp_message_build(lease2->message, &iovw2));
 
-                _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
-                ASSERT_OK(dhcp_lease_load(&lease, lease_file));
+                ASSERT_TRUE(iovw_equal(&iovw, &iovw2));
         }
 
         ASSERT_OK(sd_dhcp_client_stop(client));