Coverage Report

Created: 2026-02-14 07:22

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.29k
                void fuzz_classifyPacket(const Pkt6Ptr& pkt) {
48
5.29k
                    classifyPacket(pkt);
49
5.29k
                }
50
        };
51
    }
52
}
53
54
1.73k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
55
1.73k
    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.72k
    isc::util::file::PathChecker::enableEnforcement(false);
62
63
    // Force DUID file to /tmp
64
1.72k
    setenv("KEA_DHCP_DATA_DIR", "/tmp", 1);
65
66
    // Initialise logging
67
1.72k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
68
1.72k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
69
1.72k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
70
1.72k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
71
1.72k
    try {
72
1.72k
        isc::log::initLogger("fuzzer");
73
1.72k
        isc::process::Daemon::loggerInit("fuzzer", false);
74
1.72k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
75
1.72k
    } catch (...) {
76
        // Early exit if logging initialisation failed
77
0
        return 0;
78
0
    }
79
80
    // Creating temp config file
81
1.72k
    std::string path = fuzz::writeTempConfig(false);
82
1.72k
    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.72k
    std::string lease_path = fuzz::writeTempLease(false);
90
91
1.72k
    Pkt6Ptr pkt;
92
1.72k
    std::unique_ptr<MyDhcpv6Srv> srv;
93
94
    // Package parsing
95
1.72k
    try {
96
1.72k
        pkt = Pkt6Ptr(new Pkt6(data, size));
97
1.72k
        pkt->unpack();
98
1.72k
    } catch (...) {
99
        // Early exit if package parsing failed.
100
723
        return 0;
101
723
    }
102
103
    // Configure random value in packet
104
999
    FuzzedDataProvider fdp(data, size);
105
999
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 37);
106
999
    pkt->setType(static_cast<DHCPv6MessageType>(typeChoice));
107
108
    // Server initialisation
109
999
    try {
110
999
        srv.reset(new MyDhcpv6Srv());
111
999
        srv->init(path);
112
999
    } catch (...) {
113
        // Early exit if server initialisation failed.
114
3
        return 0;
115
3
    }
116
117
996
    if (!srv) {
118
        // Early exit if server initialisation failed.
119
0
        return 0;
120
0
    }
121
122
    // Call classifyPacket for packet checking
123
996
    try {
124
996
        srv->fuzz_classifyPacket(pkt);
125
996
    } 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
996
    CalloutHandlePtr handle = nullptr;
133
996
    AllocEngine::ClientContext6 ctx;
134
135
    // Call earlyGHRLookup
136
996
    try {
137
996
        srv->earlyGHRLookup(pkt, ctx);
138
996
    } catch (const isc::Exception& e) {
139
        // Slient exceptions
140
4
    } catch (const boost::exception& e) {
141
        // Slient exceptions
142
0
    }
143
144
    // Call lease6_decline
145
996
    try {
146
996
        handle = getCalloutHandle(pkt);
147
996
        uint8_t mac_addr[6];
148
6.97k
        for (size_t i = 0; i < 6; ++i) {
149
5.97k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
150
5.97k
        }
151
996
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
152
996
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
153
996
        handle->setArgument("leases6", leases);
154
996
        handle->setArgument("query6", pkt);
155
156
996
        lease6_decline(*handle);
157
996
    } catch (const isc::Exception& e) {
158
        // Slient exceptions
159
996
    } catch (const boost::exception& e) {
160
        // Slient exceptions
161
0
    }
162
163
    // Clean up to avoid mem leak
164
996
    if (handle) {
165
996
        handle->deleteAllArguments();
166
996
    }
167
168
    // Call lease6_release
169
996
    try {
170
996
        handle = getCalloutHandle(pkt);
171
996
        uint8_t mac_addr[6];
172
6.97k
        for (size_t i = 0; i < 6; ++i) {
173
5.97k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
174
5.97k
        }
175
996
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
176
996
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
177
996
        handle->setArgument("leases6", leases);
178
996
        handle->setArgument("query6", pkt);
179
180
996
        lease6_release(*handle);
181
996
    } catch (const isc::Exception& e) {
182
        // Slient exceptions
183
996
    } catch (const boost::exception& e) {
184
        // Slient exceptions
185
0
    }
186
187
    // Clean up to avoid mem leak
188
996
    if (handle) {
189
996
        handle->deleteAllArguments();
190
996
    }
191
192
    // Call leases6_committed
193
996
    try {
194
996
        handle = getCalloutHandle(pkt);
195
996
        uint8_t mac_addr[6];
196
6.97k
        for (size_t i = 0; i < 6; ++i) {
197
5.97k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
198
5.97k
        }
199
996
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
200
996
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
201
996
        handle->setArgument("leases6", leases);
202
996
        handle->setArgument("deleted_leases6", leases);
203
996
        handle->setArgument("query6", pkt);
204
205
996
        leases6_committed(*handle);
206
996
    } catch (const isc::Exception& e) {
207
        // Slient exceptions
208
996
    } catch (const boost::exception& e) {
209
        // Slient exceptions
210
996
    }
211
212
    // Clean up to avoid mem leak
213
996
    if (handle) {
214
996
        handle->deleteAllArguments();
215
996
    }
216
217
    // Call addr6_register
218
996
    try {
219
996
        handle = getCalloutHandle(pkt);
220
996
        Pkt6Ptr rsp;
221
996
        uint8_t mac_addr[6];
222
6.97k
        for (size_t i = 0; i < 6; ++i) {
223
5.97k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
224
5.97k
        }
225
996
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
226
996
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
227
996
        handle->setArgument("new_leases6", leases);
228
996
        handle->setArgument("response6", rsp);
229
996
        handle->setArgument("query6", pkt);
230
231
996
        IOAddress addr = ctx.query_->getRemoteAddr();
232
996
        handle->setArgument("address6", addr);
233
996
        handle->setArgument("old_leases6",
234
996
                            LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, addr));
235
236
996
        addr6_register(*handle);
237
996
    } catch (const isc::Exception& e) {
238
        // Slient exceptions
239
996
    } catch (const boost::exception& e) {
240
        // Slient exceptions
241
0
    }
242
243
    // Clean up to avoid mem leak
244
996
    if (handle) {
245
996
        handle->deleteAllArguments();
246
996
    }
247
248
996
    srv.reset();
249
250
    // Remove temp files
251
996
    fuzz::deleteTempFile(path);
252
996
    fuzz::deleteTempFile(lease_path);
253
254
996
    return 0;
255
996
}