The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
fuzzer_value.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: f7bbd4a236b42ed88c750bcf1c2b12085dfd9850 $
19 *
20 * @file src/bin/fuzzer_value.c
21 * @brief Functions to fuzz fr_value_box_from_str()
22 *
23 * fr_value_box_from_str() is the universal text -> typed-value parser in
24 * FreeRADIUS. Every string-form value (config files, dictionaries, CLI
25 * input, radclient, JSON) flows through it. It dispatches to per-type
26 * sub-parsers for IP addresses, IPv6 prefixes, MAC addresses, integers,
27 * dates, hex octets, floats, ifid, etc. Each is a potential bug surface,
28 * so a single harness covers a wide attack surface.
29 *
30 * Input layout:
31 * byte[0] - type selector (mod number of leaf types)
32 * byte[1+] - string to parse for that type
33 */
34RCSID("$Id: f7bbd4a236b42ed88c750bcf1c2b12085dfd9850 $")
35
36#include <freeradius-devel/build.h>
37#include <freeradius-devel/util/talloc.h>
38#include <freeradius-devel/util/types.h>
39#include <freeradius-devel/util/value.h>
40#include <freeradius-devel/util/lsan.h>
41
42#include <stdint.h>
43#include <stddef.h>
44#include <stdlib.h>
45#include <string.h>
46
47/*
48 * Poison gutters either side of the input string and the value
49 * box. __asan_poison_memory_region() rounds to 8-byte granules,
50 * so reads more than ~7 bytes past either end of the live region
51 * will be reported by ASan. 64 bytes per side is plenty without
52 * bloating each iteration noticeably.
53 */
54#define POISON_START 64
55#define POISON_END 64
56
57int LLVMFuzzerInitialize(int *argc, char ***argv);
58int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
59
60/*
61 * Leaf data types that fr_value_box_from_str() actually parses.
62 * Excludes structural (TLV, STRUCT, GROUP, UNION, VSA, VENDOR, ATTR)
63 * and pseudo (NULL, MAX, VOID, *_CURSOR) types.
64 */
91
92int LLVMFuzzerInitialize(UNUSED int *argc, UNUSED char ***argv)
93{
94 return 0;
95}
96
97int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
98{
99 TALLOC_CTX *ctx;
100 fr_value_box_t *dst;
102 uint8_t *raw_str = NULL, *raw_box = NULL;
103 char *str;
104 size_t inlen;
105
106 if (size < 1) return 0;
107 if (size > 8192) return 0; /* keep iterations fast */
108
109 inlen = size - 1;
110 type = fuzz_types[data[0] % (sizeof(fuzz_types) / sizeof(fuzz_types[0]))];
111
112 ctx = talloc_init_const("fuzzer_value");
113 if (!ctx) return 0;
114
115 /*
116 * Input string with poison gutters either side. We deliberately
117 * do NOT NUL-terminate: if fr_value_box_from_str() reads past
118 * the declared inlen, the poison (or talloc redzone) should
119 * flag it under ASan rather than the read landing on a
120 * convenient stop byte.
121 */
122 raw_str = talloc_array(ctx, uint8_t, POISON_START + inlen + POISON_END);
123 if (!raw_str) goto out;
124 str = (char *)(raw_str + POISON_START);
125 if (inlen) memcpy(str, data + 1, inlen);
128
129 /*
130 * Value box with poison gutters around the struct. Catches
131 * per-type sub-parsers that write past the end (or before
132 * the start) of the destination box.
133 */
134 raw_box = talloc_zero_array(ctx, uint8_t,
136 if (!raw_box) goto out;
137 dst = (fr_value_box_t *)(raw_box + POISON_START);
140
141 (void) fr_value_box_from_str(ctx, dst, type, NULL, str, inlen, NULL);
142
143 /*
144 * Unpoison before talloc_free walks the chunks.
145 */
148
149out:
150 talloc_free(ctx);
151 return 0;
152}
#define RCSID(id)
Definition build.h:512
#define UNUSED
Definition build.h:336
#define POISON_START
#define POISON_END
static fr_type_t const fuzz_types[]
int LLVMFuzzerInitialize(int *argc, char ***argv)
Definition fuzzer.c:94
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
talloc_free(hp)
#define ASAN_POISON_MEMORY_REGION(_start, _size)
Definition lsan.h:62
#define ASAN_UNPOISON_MEMORY_REGION(_start, _size)
Definition lsan.h:63
fr_type_t
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_FLOAT32
Single precision floating point.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_INT8
8 Bit signed integer.
@ FR_TYPE_ETHERNET
48 Bit Mac-Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_INT64
64 Bit signed integer.
@ FR_TYPE_INT16
16 Bit signed integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_FLOAT64
Double precision floating point.
unsigned char uint8_t
fr_aka_sim_id_type_t type
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:127
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules)
Definition value.c:6068
static fr_slen_t data
Definition value.h:1340
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1030
static size_t char ** out
Definition value.h:1030