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_radius6.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/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
#include <cstdlib>
31
32
#include "helper_func.h"
33
34
using namespace isc::dhcp;
35
using namespace isc::hooks;
36
using namespace isc::util;
37
38
extern "C" int subnet6_select(CalloutHandle& handle);
39
extern "C" int lease6_release(CalloutHandle& handle);
40
extern "C" int lease6_decline(CalloutHandle& handle);
41
42
namespace isc {
43
    namespace dhcp {
44
        class MyDhcpv6Srv : public ControlledDhcpv6Srv {
45
            public:
46
5.71k
                void fuzz_classifyPacket(const Pkt6Ptr& pkt) {
47
5.71k
                    classifyPacket(pkt);
48
5.71k
                }
49
        };
50
    }
51
}
52
53
1.77k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
54
1.77k
    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.75k
    isc::util::file::PathChecker::enableEnforcement(false);
61
62
    // Force DUID file to /tmp
63
1.75k
    setenv("KEA_DHCP_DATA_DIR", "/tmp", 1);
64
65
    // Initialise logging
66
1.75k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
67
1.75k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
68
1.75k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
69
1.75k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
70
1.75k
    try {
71
1.75k
        isc::log::initLogger("fuzzer");
72
1.75k
        isc::process::Daemon::loggerInit("fuzzer", false);
73
1.75k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
74
1.75k
    } catch (...) {
75
        // Early exit if logging initialisation failed
76
0
        return 0;
77
0
    }
78
79
    // Creating temp config file
80
1.75k
    std::string path = fuzz::writeTempConfig(false);
81
1.75k
    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.75k
    std::string lease_path = fuzz::writeTempLease(false);
89
90
1.75k
    Pkt6Ptr pkt;
91
1.75k
    std::unique_ptr<MyDhcpv6Srv> srv;
92
93
    // Package parsing
94
1.75k
    try {
95
1.75k
        pkt = Pkt6Ptr(new Pkt6(data, size));
96
1.75k
        pkt->unpack();
97
1.75k
    } catch (...) {
98
        // Early exit if package parsing failed.
99
686
        return 0;
100
686
    }
101
102
    // Configure random value in packet
103
1.07k
    FuzzedDataProvider fdp(data, size);
104
1.07k
    uint8_t typeChoice = fdp.ConsumeIntegralInRange<uint8_t>(0, 37);
105
1.07k
    pkt->setType(static_cast<DHCPv6MessageType>(typeChoice));
106
107
    // Server initialisation
108
1.07k
    try {
109
1.07k
        srv.reset(new MyDhcpv6Srv());
110
1.07k
        srv->init(path);
111
1.07k
    } catch (...) {
112
        // Early exit if server initialisation failed.
113
10
        return 0;
114
10
    }
115
116
1.06k
    if (!srv) {
117
        // Early exit if server initialisation failed.
118
0
        return 0;
119
0
    }
120
121
    // Call classifyPacket for packet checking
122
1.06k
    try {
123
1.06k
        srv->fuzz_classifyPacket(pkt);
124
1.06k
    } 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.06k
    CalloutHandlePtr handle = nullptr;
132
1.06k
    AllocEngine::ClientContext6 ctx;
133
134
    // Call earlyGHRLookup
135
1.06k
    try {
136
1.06k
        srv->earlyGHRLookup(pkt, ctx);
137
1.06k
    } catch (const isc::Exception& e) {
138
        // Slient exceptions
139
10
    } catch (const boost::exception& e) {
140
        // Slient exceptions
141
0
    }
142
143
    // Fuzz subnet6_select
144
1.06k
    try {
145
1.06k
        Pkt6Ptr rsp;
146
1.06k
        CfgMgr& cfgmgr = CfgMgr::instance();
147
1.06k
        handle = getCalloutHandle(pkt);
148
1.06k
        handle->setArgument("query6", pkt);
149
1.06k
        handle->setArgument("subnet6", ctx.subnet_);
150
1.06k
        handle->setArgument("subnet6collection",
151
1.06k
                            cfgmgr.getCurrentCfg()->getCfgSubnets6()->getAll());
152
1.06k
        subnet6_select(*handle);
153
1.06k
    } catch (const isc::Exception& e) {
154
        // Slient exceptions
155
0
    } catch (const boost::exception& e) {
156
        // Slient exceptions
157
0
    }
158
159
    // Clean handle to avoid mem leak
160
1.06k
    if (handle) {
161
1.06k
        handle->deleteAllArguments();
162
1.06k
    }
163
164
    // Call lease6_decline
165
1.06k
    try {
166
1.06k
        uint8_t mac_addr[6];
167
7.43k
        for (size_t i = 0; i < 6; ++i) {
168
6.37k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
169
6.37k
        }
170
1.06k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
171
1.06k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
172
1.06k
        handle->setArgument("leases6", leases);
173
1.06k
        handle->setArgument("query6", pkt);
174
175
1.06k
        lease6_decline(*handle);
176
1.06k
    } catch (const isc::Exception& e) {
177
        // Slient exceptions
178
1.06k
    } catch (const boost::exception& e) {
179
        // Slient exceptions
180
0
    }
181
182
    // Clean up to avoid mem leak
183
1.06k
    if (handle) {
184
1.06k
        handle->deleteAllArguments();
185
1.06k
    }
186
187
    // Call lease6_release
188
1.06k
    try {
189
1.06k
        uint8_t mac_addr[6];
190
7.43k
        for (size_t i = 0; i < 6; ++i) {
191
6.37k
            mac_addr[i] = fdp.ConsumeIntegral<uint8_t>();
192
6.37k
        }
193
1.06k
        HWAddr hw(mac_addr, sizeof(mac_addr), HTYPE_ETHER);
194
1.06k
        Lease6Collection leases = LeaseMgrFactory::instance().getLease6(hw);
195
1.06k
        handle->setArgument("leases6", leases);
196
1.06k
        handle->setArgument("query6", pkt);
197
198
1.06k
        lease6_release(*handle);
199
1.06k
    } catch (const isc::Exception& e) {
200
        // Slient exceptions
201
1.06k
    } catch (const boost::exception& e) {
202
        // Slient exceptions
203
0
    }
204
205
    // Clean up to avoid mem leak
206
1.06k
    if (handle) {
207
1.06k
        handle->deleteAllArguments();
208
1.06k
    }
209
210
1.06k
    srv.reset();
211
212
    // Remove temp files
213
1.06k
    fuzz::deleteTempFile(path);
214
1.06k
    fuzz::deleteTempFile(lease_path);
215
216
1.06k
    return 0;
217
1.06k
}