Coverage Report

Created: 2025-12-31 07:33

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
7.69k
                void fuzz_classifyPacket(const Pkt4Ptr& pkt) {
46
7.69k
                    classifyPacket(pkt);
47
7.69k
                }
48
        };
49
    }
50
}
51
52
3.16k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
53
3.16k
    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
3.15k
    isc::util::file::PathChecker::enableEnforcement(false);
60
61
    // Initialise logging
62
3.15k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
63
3.15k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
64
3.15k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
65
3.15k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
66
3.15k
    try {
67
3.15k
        isc::log::initLogger("fuzzer");
68
3.15k
        isc::process::Daemon::loggerInit("fuzzer", false);
69
3.15k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
70
3.15k
    } catch (...) {
71
        // Early exit if logging initialisation failed
72
0
        return 0;
73
0
    }
74
75
    // Creating temp config file
76
3.15k
    std::string path = fuzz::writeTempConfig(true);
77
3.15k
    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
3.15k
    std::string lease_path = fuzz::writeTempLease(true);
85
86
3.15k
    Pkt4Ptr pkt;
87
3.15k
    std::unique_ptr<MyDhcpv4Srv> srv;
88
89
    // Package parsing
90
3.15k
    try {
91
        // Add fixed magic cookie and correct hardware address
92
3.15k
        std::vector<uint8_t> buf(data, data + size);
93
3.15k
        if (size >= 240) {
94
            // Max hardware address length is 20
95
3.12k
            buf[2] = 20;
96
97
            // Magic cookie fixed value 0x63825363
98
3.12k
            buf[236] = 0x63;
99
3.12k
            buf[237] = 0x82;
100
3.12k
            buf[238] = 0x53;
101
3.12k
            buf[239] = 0x63;
102
3.12k
        }
103
104
3.15k
        pkt = Pkt4Ptr(new Pkt4(buf.data(), buf.size()));
105
3.15k
        pkt->unpack();
106
3.15k
    } catch (...) {
107
        // Early exit if package parsing failed.
108
1.55k
        return 0;
109
1.55k
    }
110
111
    // Configure random value in packet
112
1.59k
    FuzzedDataProvider fdp(data, size);
113
1.59k
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 8);
114
1.59k
    pkt->setType(static_cast<DHCPMessageType>(typeChoice));
115
116
    // Server initialisation
117
1.59k
    try {
118
1.59k
        srv.reset(new MyDhcpv4Srv());
119
1.59k
        srv->init(path);
120
1.59k
    } catch (...) {
121
        // Early exit if server initialisation failed.
122
4
        return 0;
123
4
    }
124
125
1.59k
    if (!srv) {
126
        // Early exit if server initialisation failed.
127
0
        return 0;
128
0
    }
129
130
    // Call classifyPacket for packet checking
131
1.59k
    try {
132
1.59k
        srv->fuzz_classifyPacket(pkt);
133
1.59k
    } 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.59k
    CalloutHandlePtr handle = nullptr;
141
1.59k
    AllocEngine::ClientContext4Ptr ctx(new AllocEngine::ClientContext4());
142
143
    // Call earlyGHRLookup
144
1.59k
    try {
145
1.59k
        srv->earlyGHRLookup(pkt, ctx);
146
1.59k
    } 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.59k
    try {
154
1.59k
        handle = getCalloutHandle(pkt);
155
1.59k
        uint8_t mac_addr[6];
156
11.1k
        for (size_t i = 0; i < 6; ++i) {
157
9.57k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
158
9.57k
        }
159
1.59k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
160
1.59k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
161
1.59k
        handle->setArgument("leases4", leases);
162
1.59k
        handle->setArgument("query4", pkt);
163
164
1.59k
        lease4_release(*handle);
165
1.59k
    } catch (const isc::Exception& e) {
166
        // Slient exceptions
167
1.59k
    } catch (const boost::exception& e) {
168
        // Slient exceptions
169
0
    }
170
171
    // Clean up to avoid mem leak
172
1.59k
    if (handle) {
173
1.59k
        handle->deleteAllArguments();
174
1.59k
    }
175
176
    // Call lease4_decline
177
1.59k
    try {
178
1.59k
        handle = getCalloutHandle(pkt);
179
1.59k
        uint8_t mac_addr[6];
180
11.1k
        for (size_t i = 0; i < 6; ++i) {
181
9.57k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
182
9.57k
        }
183
1.59k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
184
1.59k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
185
1.59k
        handle->setArgument("leases4", leases);
186
1.59k
        handle->setArgument("query4", pkt);
187
188
1.59k
        lease4_decline(*handle);
189
1.59k
    } catch (const isc::Exception& e) {
190
        // Slient exceptions
191
1.59k
    } catch (const boost::exception& e) {
192
        // Slient exceptions
193
0
    }
194
195
    // Clean up to avoid mem leak
196
1.59k
    if (handle) {
197
1.59k
        handle->deleteAllArguments();
198
1.59k
    }
199
200
    // Call lease4_committed
201
1.59k
    try {
202
1.59k
        handle = getCalloutHandle(pkt);
203
1.59k
        Pkt4Ptr rsp;
204
1.59k
        uint8_t mac_addr[6];
205
11.1k
        for (size_t i = 0; i < 6; ++i) {
206
9.57k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
207
9.57k
        }
208
1.59k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
209
1.59k
        Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw);
210
1.59k
        handle->setArgument("leases4", leases);
211
1.59k
        handle->setArgument("query4", pkt);
212
1.59k
        handle->setArgument("response4", rsp);
213
214
1.59k
        leases4_committed(*handle);
215
1.59k
    } catch (const isc::Exception& e) {
216
        // Slient exceptions
217
1.59k
    } catch (const boost::exception& e) {
218
        // Slient exceptions
219
1.59k
    }
220
221
    // Clean up to avoid mem leak
222
1.59k
    if (handle) {
223
1.59k
        handle->deleteAllArguments();
224
1.59k
    }
225
226
1.59k
    srv.reset();
227
228
    // Remove temp files
229
1.59k
    fuzz::deleteTempFile(path);
230
1.59k
    fuzz::deleteTempFile(lease_path);
231
1.59k
    return 0;
232
1.59k
}