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_run_script6.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 <dhcpsrv/lease_mgr_factory.h>
16
#include <log/logger_support.h>
17
#include <util/filesystem.h>
18
19
#include <cstddef>
20
#include <cstdint>
21
#include <vector>
22
#include <list>
23
#include <memory>
24
#include <iostream>
25
#include <filesystem>
26
#include <fstream>
27
#include <string>
28
#include <cstdio>
29
#include <cstdlib>
30
31
#include "helper_func.h"
32
33
using namespace isc::asiolink;
34
using namespace isc::dhcp;
35
using namespace isc::hooks;
36
using namespace isc::util;
37
38
extern "C" int lease6_release(CalloutHandle& handle);
39
extern "C" int lease6_decline(CalloutHandle& handle);
40
extern "C" int leases6_committed(CalloutHandle& handle);
41
extern "C" int addr6_register(CalloutHandle& handle);
42
43
namespace isc {
44
    namespace dhcp {
45
        class MyDhcpv6Srv : public ControlledDhcpv6Srv {
46
            public:
47
5.71k
                void fuzz_classifyPacket(const Pkt6Ptr& pkt) {
48
5.71k
                    classifyPacket(pkt);
49
5.71k
                }
50
        };
51
    }
52
}
53
54
1.93k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
55
1.93k
    if (size < 236) {
56
        // package size requires at least 236 bytes
57
15
        return 0;
58
15
    }
59
60
    // Disable validatePath checking to allow writing configuration file to /tmp
61
1.91k
    isc::util::file::PathChecker::enableEnforcement(false);
62
63
    // Force DUID file to /tmp
64
1.91k
    setenv("KEA_DHCP_DATA_DIR", "/tmp", 1);
65
66
    // Initialise logging
67
1.91k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
68
1.91k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
69
1.91k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
70
1.91k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
71
1.91k
    try {
72
1.91k
        isc::log::initLogger("fuzzer");
73
1.91k
        isc::process::Daemon::loggerInit("fuzzer", false);
74
1.91k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
75
1.91k
    } catch (...) {
76
        // Early exit if logging initialisation failed
77
0
        return 0;
78
0
    }
79
80
    // Creating temp config file
81
1.91k
    std::string path = fuzz::writeTempConfig(false);
82
1.91k
    if (path.empty()) {
83
        // Early exit if configuration file creation failed
84
0
        fuzz::deleteTempFile(path);
85
0
        return 0;
86
0
    }
87
88
    // Creating temp lease file
89
1.91k
    std::string lease_path = fuzz::writeTempLease(false);
90
91
1.91k
    Pkt6Ptr pkt;
92
1.91k
    std::unique_ptr<MyDhcpv6Srv> srv;
93
94
    // Package parsing
95
1.91k
    try {
96
1.91k
        pkt = Pkt6Ptr(new Pkt6(data, size));
97
1.91k
        pkt->unpack();
98
1.91k
    } catch (...) {
99
        // Early exit if package parsing failed.
100
726
        return 0;
101
726
    }
102
103
    // Configure random value in packet
104
1.19k
    FuzzedDataProvider fdp(data, size);
105
1.19k
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 37);
106
1.19k
    pkt->setType(static_cast<DHCPv6MessageType>(typeChoice));
107
108
    // Server initialisation
109
1.19k
    try {
110
1.19k
        srv.reset(new MyDhcpv6Srv());
111
1.19k
        srv->init(path);
112
1.19k
    } catch (...) {
113
        // Early exit if server initialisation failed.
114
10
        return 0;
115
10
    }
116
117
1.18k
    if (!srv) {
118
        // Early exit if server initialisation failed.
119
0
        return 0;
120
0
    }
121
122
    // Call classifyPacket for packet checking
123
1.18k
    try {
124
1.18k
        srv->fuzz_classifyPacket(pkt);
125
1.18k
    } catch (const isc::Exception& e) {
126
        // Slient exceptions
127
0
    } catch (const boost::exception& e) {
128
        // Slient exceptions
129
0
    }
130
131
    // Prepare client context
132
1.18k
    CalloutHandlePtr handle = nullptr;
133
1.18k
    AllocEngine::ClientContext6 ctx;
134
135
    // Call earlyGHRLookup
136
1.18k
    try {
137
1.18k
        srv->earlyGHRLookup(pkt, ctx);
138
1.18k
    } catch (const isc::Exception& e) {
139
        // Slient exceptions
140
2
    } catch (const boost::exception& e) {
141
        // Slient exceptions
142
0
    }
143
144
    // Call lease6_decline
145
1.18k
    try {
146
1.18k
        handle = getCalloutHandle(pkt);
147
1.18k
        uint8_t mac_addr[6];
148
8.26k
        for (size_t i = 0; i < 6; ++i) {
149
7.08k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
150
7.08k
        }
151
1.18k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
152
1.18k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
153
1.18k
        handle->setArgument("leases6", leases);
154
1.18k
        handle->setArgument("query6", pkt);
155
156
1.18k
        lease6_decline(*handle);
157
1.18k
    } catch (const isc::Exception& e) {
158
        // Slient exceptions
159
1.18k
    } catch (const boost::exception& e) {
160
        // Slient exceptions
161
0
    }
162
163
    // Clean up to avoid mem leak
164
1.18k
    if (handle) {
165
1.18k
        handle->deleteAllArguments();
166
1.18k
    }
167
168
    // Call lease6_release
169
1.18k
    try {
170
1.18k
        handle = getCalloutHandle(pkt);
171
1.18k
        uint8_t mac_addr[6];
172
8.26k
        for (size_t i = 0; i < 6; ++i) {
173
7.08k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
174
7.08k
        }
175
1.18k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
176
1.18k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
177
1.18k
        handle->setArgument("leases6", leases);
178
1.18k
        handle->setArgument("query6", pkt);
179
180
1.18k
        lease6_release(*handle);
181
1.18k
    } catch (const isc::Exception& e) {
182
        // Slient exceptions
183
1.18k
    } catch (const boost::exception& e) {
184
        // Slient exceptions
185
0
    }
186
187
    // Clean up to avoid mem leak
188
1.18k
    if (handle) {
189
1.18k
        handle->deleteAllArguments();
190
1.18k
    }
191
192
    // Call leases6_committed
193
1.18k
    try {
194
1.18k
        handle = getCalloutHandle(pkt);
195
1.18k
        uint8_t mac_addr[6];
196
8.26k
        for (size_t i = 0; i < 6; ++i) {
197
7.08k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
198
7.08k
        }
199
1.18k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
200
1.18k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
201
1.18k
        handle->setArgument("leases6", leases);
202
1.18k
        handle->setArgument("deleted_leases6", leases);
203
1.18k
        handle->setArgument("query6", pkt);
204
205
1.18k
        leases6_committed(*handle);
206
1.18k
    } catch (const isc::Exception& e) {
207
        // Slient exceptions
208
1.18k
    } catch (const boost::exception& e) {
209
        // Slient exceptions
210
1.18k
    }
211
212
    // Clean up to avoid mem leak
213
1.18k
    if (handle) {
214
1.18k
        handle->deleteAllArguments();
215
1.18k
    }
216
217
    // Call addr6_register
218
1.18k
    try {
219
1.18k
        handle = getCalloutHandle(pkt);
220
1.18k
        Pkt6Ptr rsp;
221
1.18k
        uint8_t mac_addr[6];
222
8.26k
        for (size_t i = 0; i < 6; ++i) {
223
7.08k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
224
7.08k
        }
225
1.18k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
226
1.18k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
227
1.18k
        handle->setArgument("new_leases6", leases);
228
1.18k
        handle->setArgument("response6", rsp);
229
1.18k
        handle->setArgument("query6", pkt);
230
231
1.18k
        IOAddress addr = ctx.query_->getRemoteAddr();
232
1.18k
        handle->setArgument("address6", addr);
233
1.18k
        handle->setArgument("old_leases6",
234
1.18k
                            LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr));
235
236
1.18k
        addr6_register(*handle);
237
1.18k
    } catch (const isc::Exception& e) {
238
        // Slient exceptions
239
1.18k
    } catch (const boost::exception& e) {
240
        // Slient exceptions
241
0
    }
242
243
    // Clean up to avoid mem leak
244
1.18k
    if (handle) {
245
1.18k
        handle->deleteAllArguments();
246
1.18k
    }
247
248
1.18k
    srv.reset();
249
250
    // Remove temp files
251
1.18k
    fuzz::deleteTempFile(path);
252
1.18k
    fuzz::deleteTempFile(lease_path);
253
254
1.18k
    return 0;
255
1.18k
}