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_script4.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/dhcp4.h>
11
#include <dhcp/pkt4.h>
12
#include <dhcp/libdhcp++.h>
13
#include <dhcp4/ctrl_dhcp4_srv.h>
14
#include <dhcpsrv/callout_handle_store.h>
15
#include <dhcpsrv/cfgmgr.h>
16
#include <dhcpsrv/lease_mgr_factory.h>
17
#include <log/logger_support.h>
18
#include <util/filesystem.h>
19
20
#include <cstddef>
21
#include <cstdint>
22
#include <vector>
23
#include <list>
24
#include <memory>
25
#include <iostream>
26
#include <filesystem>
27
#include <fstream>
28
#include <string>
29
#include <cstdio>
30
31
#include "helper_func.h"
32
33
using namespace isc::dhcp;
34
using namespace isc::hooks;
35
using namespace isc::util;
36
37
extern "C" int lease4_release(CalloutHandle& handle);
38
extern "C" int lease4_decline(CalloutHandle& handle);
39
extern "C" int leases4_committed(CalloutHandle& handle);
40
41
namespace isc {
42
    namespace dhcp {
43
        class MyDhcpv4Srv : public ControlledDhcpv4Srv {
44
            public:
45
6.36k
                void fuzz_classifyPacket(const Pkt4Ptr& pkt) {
46
6.36k
                    classifyPacket(pkt);
47
6.36k
                }
48
        };
49
    }
50
}
51
52
2.80k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
53
2.80k
    if (size < 236) {
54
        // package size requires at least 236 bytes
55
15
        return 0;
56
15
    }
57
58
    // Disable validatePath checking to allow writing configuration file to /tmp
59
2.78k
    isc::util::file::PathChecker::enableEnforcement(false);
60
61
    // Initialise logging
62
2.78k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
63
2.78k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
64
2.78k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
65
2.78k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
66
2.78k
    try {
67
2.78k
        isc::log::initLogger("fuzzer");
68
2.78k
        isc::process::Daemon::loggerInit("fuzzer", false);
69
2.78k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
70
2.78k
    } catch (...) {
71
        // Early exit if logging initialisation failed
72
0
        return 0;
73
0
    }
74
75
    // Creating temp config file
76
2.78k
    std::string path = fuzz::writeTempConfig(true);
77
2.78k
    if (path.empty()) {
78
        // Early exit if configuration file creation failed
79
0
        fuzz::deleteTempFile(path);
80
0
        return 0;
81
0
    }
82
83
    // Creating temp lease file
84
2.78k
    std::string lease_path = fuzz::writeTempLease(true);
85
86
2.78k
    Pkt4Ptr pkt;
87
2.78k
    std::unique_ptr<MyDhcpv4Srv> srv;
88
89
    // Package parsing
90
2.78k
    try {
91
        // Add fixed magic cookie and correct hardware address
92
2.78k
        std::vector<uint8_t> buf(data, data + size);
93
2.78k
        if (size >= 240) {
94
            // Max hardware address length is 20
95
2.76k
            buf[2] = 20;
96
97
            // Magic cookie fixed value 0x63825363
98
2.76k
            buf[236] = 0x63;
99
2.76k
            buf[237] = 0x82;
100
2.76k
            buf[238] = 0x53;
101
2.76k
            buf[239] = 0x63;
102
2.76k
        }
103
104
2.78k
        pkt = Pkt4Ptr(new Pkt4(buf.data(), buf.size()));
105
2.78k
        pkt->unpack();
106
2.78k
    } catch (...) {
107
        // Early exit if package parsing failed.
108
1.38k
        return 0;
109
1.38k
    }
110
111
    // Configure random value in packet
112
1.39k
    FuzzedDataProvider fdp(data, size);
113
1.39k
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 8);
114
1.39k
    pkt->setType(static_cast<DHCPMessageType>(typeChoice));
115
116
    // Server initialisation
117
1.39k
    try {
118
1.39k
        srv.reset(new MyDhcpv4Srv());
119
1.39k
        srv->init(path);
120
1.39k
    } catch (...) {
121
        // Early exit if server initialisation failed.
122
24
        return 0;
123
24
    }
124
125
1.37k
    if (!srv) {
126
        // Early exit if server initialisation failed.
127
0
        return 0;
128
0
    }
129
130
    // Call classifyPacket for packet checking
131
1.37k
    try {
132
1.37k
        srv->fuzz_classifyPacket(pkt);
133
1.37k
    } catch (const isc::Exception& e) {
134
        // Slient exceptions
135
0
    } catch (const boost::exception& e) {
136
        // Slient exceptions
137
0
    }
138
139
    // Prepare client context
140
1.37k
    CalloutHandlePtr handle = nullptr;
141
1.37k
    AllocEngine::ClientContext4Ptr ctx(new AllocEngine::ClientContext4());
142
143
    // Call earlyGHRLookup
144
1.37k
    try {
145
1.37k
        srv->earlyGHRLookup(pkt, ctx);
146
1.37k
    } catch (const isc::Exception& e) {
147
        // Slient exceptions
148
0
    } catch (const boost::exception& e) {
149
        // Slient exceptions
150
0
    }
151
152
    // Call lease4_release
153
1.37k
    try {
154
1.37k
        handle = getCalloutHandle(pkt);
155
1.37k
        uint8_t mac_addr[6];
156
9.61k
        for (size_t i = 0; i < 6; ++i) {
157
8.23k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
158
8.23k
        }
159
1.37k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
160
1.37k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
161
1.37k
        handle->setArgument("leases4", leases);
162
1.37k
        handle->setArgument("query4", pkt);
163
164
1.37k
        lease4_release(*handle);
165
1.37k
    } catch (const isc::Exception& e) {
166
        // Slient exceptions
167
1.37k
    } catch (const boost::exception& e) {
168
        // Slient exceptions
169
0
    }
170
171
    // Clean up to avoid mem leak
172
1.37k
    if (handle) {
173
1.37k
        handle->deleteAllArguments();
174
1.37k
    }
175
176
    // Call lease4_decline
177
1.37k
    try {
178
1.37k
        handle = getCalloutHandle(pkt);
179
1.37k
        uint8_t mac_addr[6];
180
9.61k
        for (size_t i = 0; i < 6; ++i) {
181
8.23k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
182
8.23k
        }
183
1.37k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
184
1.37k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
185
1.37k
        handle->setArgument("leases4", leases);
186
1.37k
        handle->setArgument("query4", pkt);
187
188
1.37k
        lease4_decline(*handle);
189
1.37k
    } catch (const isc::Exception& e) {
190
        // Slient exceptions
191
1.37k
    } catch (const boost::exception& e) {
192
        // Slient exceptions
193
0
    }
194
195
    // Clean up to avoid mem leak
196
1.37k
    if (handle) {
197
1.37k
        handle->deleteAllArguments();
198
1.37k
    }
199
200
    // Call lease4_committed
201
1.37k
    try {
202
1.37k
        handle = getCalloutHandle(pkt);
203
1.37k
        Pkt4Ptr rsp;
204
1.37k
        uint8_t mac_addr[6];
205
9.61k
        for (size_t i = 0; i < 6; ++i) {
206
8.23k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
207
8.23k
        }
208
1.37k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
209
1.37k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
210
1.37k
        handle->setArgument("leases4", leases);
211
1.37k
        handle->setArgument("query4", pkt);
212
1.37k
        handle->setArgument("response4", rsp);
213
214
1.37k
        leases4_committed(*handle);
215
1.37k
    } catch (const isc::Exception& e) {
216
        // Slient exceptions
217
1.37k
    } catch (const boost::exception& e) {
218
        // Slient exceptions
219
1.37k
    }
220
221
    // Clean up to avoid mem leak
222
1.37k
    if (handle) {
223
1.37k
        handle->deleteAllArguments();
224
1.37k
    }
225
226
1.37k
    srv.reset();
227
228
    // Remove temp files
229
1.37k
    fuzz::deleteTempFile(path);
230
1.37k
    fuzz::deleteTempFile(lease_path);
231
1.37k
    return 0;
232
1.37k
}