Coverage Report

Created: 2025-11-16 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea-fuzzer/fuzz_hook_ddns_tuning6.cc
Line
Count
Source
1
// Copyright (C) 2025 Ada Logcis Ltd.
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
////////////////////////////////////////////////////////////////////////////////
7
#include <config.h>
8
#include <fuzzer/FuzzedDataProvider.h>
9
10
#include <dhcp/dhcp6.h>
11
#include <dhcp/pkt6.h>
12
#include <dhcp/libdhcp++.h>
13
#include <dhcp6/ctrl_dhcp6_srv.h>
14
#include <dhcpsrv/callout_handle_store.h>
15
#include <log/logger_support.h>
16
#include <util/filesystem.h>
17
18
#include <cstddef>
19
#include <cstdint>
20
#include <vector>
21
#include <list>
22
#include <memory>
23
#include <iostream>
24
#include <filesystem>
25
#include <fstream>
26
#include <string>
27
#include <cstdio>
28
#include <cstdlib>
29
30
#include "helper_func.h"
31
32
using namespace isc::dhcp;
33
using namespace isc::hooks;
34
using namespace isc::util;
35
36
extern "C" int ddns6_update(CalloutHandle& handle);
37
38
namespace isc {
39
    namespace dhcp {
40
        class MyDhcpv6Srv : public ControlledDhcpv6Srv {
41
            public:
42
5.71k
                void fuzz_classifyPacket(const Pkt6Ptr& pkt) {
43
5.71k
                    classifyPacket(pkt);
44
5.71k
                }
45
46
2.10k
                ConstSubnet6Ptr fuzz_selectSubnet(const Pkt6Ptr& question, bool& drop) {
47
2.10k
                    return selectSubnet(question, drop);
48
2.10k
                }
49
        };
50
    }
51
}
52
53
1.87k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
54
1.87k
    if (size < 236) {
55
        // package size requires at least 236 bytes
56
15
        return 0;
57
15
    }
58
59
    // Disable validatePath checking to allow writing configuration file to /tmp
60
1.86k
    isc::util::file::PathChecker::enableEnforcement(false);
61
62
    // Force DUID file to /tmp
63
1.86k
    setenv("KEA_DHCP_DATA_DIR", "/tmp", 1);
64
65
    // Initialise logging
66
1.86k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
67
1.86k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
68
1.86k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
69
1.86k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
70
1.86k
    try {
71
1.86k
        isc::log::initLogger("fuzzer");
72
1.86k
        isc::process::Daemon::loggerInit("fuzzer", false);
73
1.86k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
74
1.86k
    } catch (...) {
75
        // Early exit if logging initialisation failed
76
0
        return 0;
77
0
    }
78
79
    // Creating temp config file
80
1.86k
    std::string path = fuzz::writeTempConfig(false);
81
1.86k
    if (path.empty()) {
82
        // Early exit if configuration file creation failed
83
0
        fuzz::deleteTempFile(path);
84
0
        return 0;
85
0
    }
86
87
    // Creating temp lease file
88
1.86k
    std::string lease_path = fuzz::writeTempLease(false);
89
90
1.86k
    Pkt6Ptr pkt;
91
1.86k
    std::unique_ptr<MyDhcpv6Srv> srv;
92
93
    // Package parsing
94
1.86k
    try {
95
1.86k
        pkt = Pkt6Ptr(new Pkt6(data, size));
96
1.86k
        pkt->unpack();
97
1.86k
    } catch (...) {
98
        // Early exit if package parsing failed.
99
742
        return 0;
100
742
    }
101
102
    // Configure random value in packet
103
1.11k
    FuzzedDataProvider fdp(data, size);
104
1.11k
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 37);
105
1.11k
    pkt->setType(static_cast<DHCPv6MessageType>(typeChoice));
106
107
    // Server initialisation
108
1.11k
    try {
109
1.11k
        srv.reset(new MyDhcpv6Srv());
110
1.11k
        srv->init(path);
111
1.11k
    } catch (...) {
112
        // Early exit if server initialisation failed.
113
13
        return 0;
114
13
    }
115
116
1.10k
    if (!srv) {
117
        // Early exit if server initialisation failed.
118
0
        return 0;
119
0
    }
120
121
    // Call classifyPacket for packet checking
122
1.10k
    try {
123
1.10k
        srv->fuzz_classifyPacket(pkt);
124
1.10k
    } catch (const isc::Exception& e) {
125
        // Slient exceptions
126
0
    } catch (const boost::exception& e) {
127
        // Slient exceptions
128
0
    }
129
130
    // Prepare client context
131
1.10k
    CalloutHandlePtr handle = getCalloutHandle(pkt);
132
1.10k
    AllocEngine::ClientContext6 ctx;
133
134
    // Call earlyGHRLookup
135
1.10k
    try {
136
1.10k
        srv->earlyGHRLookup(pkt, ctx);
137
1.10k
    } catch (const isc::Exception& e) {
138
        // Slient exceptions
139
3
    } catch (const boost::exception& e) {
140
        // Slient exceptions
141
0
    }
142
143
    // Call select subnet
144
1.10k
    try {
145
1.10k
        bool drop = false;
146
1.10k
        ctx.subnet_ = srv->fuzz_selectSubnet(pkt, drop);
147
1.10k
    } catch (const isc::Exception& e) {
148
       // Slient exceptions
149
0
    } catch (const boost::exception& e) {
150
        // Slient exceptions
151
0
    }
152
153
    // Fuzz ddns6_update
154
1.10k
    try {
155
1.10k
        Pkt6Ptr rsp;
156
1.10k
        handle = getCalloutHandle(pkt);
157
1.10k
        handle->setArgument("query6", pkt);
158
1.10k
        handle->setArgument("response6", rsp);
159
1.10k
        handle->setArgument("hostname", fdp.ConsumeRandomLengthString(32));
160
1.10k
        handle->setArgument("fwd-update", fdp.ConsumeBool());
161
1.10k
        handle->setArgument("rev-update", fdp.ConsumeBool());
162
1.10k
        handle->setArgument("ddns-params", ctx.getDdnsParams());
163
1.10k
        handle->setArgument("subnet6", ctx.subnet_);
164
1.10k
        ddns6_update(*handle);
165
1.10k
    } catch (const isc::Exception& e) {
166
        // Slient exceptions
167
1.10k
    } catch (const boost::exception& e) {
168
        // Slient exceptions
169
0
    }
170
171
    // Clean up to avoid mem leak
172
1.10k
    if (handle) {
173
1.10k
        handle->deleteAllArguments();
174
1.10k
    }
175
176
1.10k
    srv.reset();
177
178
    // Remove temp files
179
1.10k
    fuzz::deleteTempFile(path);
180
1.10k
    fuzz::deleteTempFile(lease_path);
181
182
1.10k
    return 0;
183
1.10k
}