Coverage Report

Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/libfido2/fuzz/udev.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2021 Yubico AB. All rights reserved.
3
 * Use of this source code is governed by a BSD-style
4
 * license that can be found in the LICENSE file.
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#include <sys/types.h>
9
10
#include <linux/hidraw.h>
11
#include <linux/input.h>
12
13
#include <assert.h>
14
#include <errno.h>
15
#include <libudev.h>
16
#include <stdlib.h>
17
18
#include "mutator_aux.h"
19
20
struct udev {
21
        int magic;
22
};
23
24
struct udev_enumerate {
25
        int magic;
26
        struct udev_list_entry *list_entry;
27
};
28
29
struct udev_list_entry {
30
        int magic;
31
};
32
33
struct udev_device {
34
        int magic;
35
        struct udev_device *parent;
36
};
37
38
2.49M
#define UDEV_MAGIC              0x584492cc
39
7.84M
#define UDEV_DEVICE_MAGIC       0x569180dd
40
11.6k
#define UDEV_LIST_ENTRY_MAGIC   0x497422ee
41
11.6k
#define UDEV_ENUM_MAGIC         0x583570ff
42
43
33.7M
#define ASSERT_TYPE(x, m)               assert((x) != NULL && (x)->magic == (m))
44
10.0M
#define ASSERT_UDEV(x)                  ASSERT_TYPE((x), UDEV_MAGIC)
45
46.6k
#define ASSERT_UDEV_ENUM(x)             ASSERT_TYPE((x), UDEV_ENUM_MAGIC)
46
10.0M
#define ASSERT_UDEV_LIST_ENTRY(x)       ASSERT_TYPE((x), UDEV_LIST_ENTRY_MAGIC)
47
13.5M
#define ASSERT_UDEV_DEVICE(x)           ASSERT_TYPE((x), UDEV_DEVICE_MAGIC)
48
49
static const char *uevent;
50
static const struct blob *report_descriptor;
51
52
struct udev *__wrap_udev_new(void);
53
struct udev_device *__wrap_udev_device_get_parent_with_subsystem_devtype(
54
    struct udev_device *, const char *, const char *);
55
struct udev_device *__wrap_udev_device_new_from_syspath(struct udev *,
56
    const char *);
57
struct udev_enumerate *__wrap_udev_enumerate_new(struct udev *);
58
struct udev_list_entry *__wrap_udev_enumerate_get_list_entry(
59
    struct udev_enumerate *);
60
struct udev_list_entry *__wrap_udev_list_entry_get_next(
61
    struct udev_list_entry *);
62
const char *__wrap_udev_device_get_sysattr_value(struct udev_device *,
63
    const char *);
64
const char *__wrap_udev_list_entry_get_name(struct udev_list_entry *);
65
const char *__wrap_udev_device_get_devnode(struct udev_device *);
66
const char *__wrap_udev_device_get_sysnum(struct udev_device *);
67
int __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *,
68
    const char *);
69
int __wrap_udev_enumerate_scan_devices(struct udev_enumerate *);
70
int __wrap_ioctl(int, unsigned long , ...);
71
void __wrap_udev_device_unref(struct udev_device *);
72
void __wrap_udev_enumerate_unref(struct udev_enumerate *);
73
void __wrap_udev_unref(struct udev *);
74
void set_udev_parameters(const char *, const struct blob *);
75
76
struct udev_device *
77
__wrap_udev_device_get_parent_with_subsystem_devtype(struct udev_device *child,
78
    const char *subsystem, const char *devtype)
79
377k
{
80
377k
        ASSERT_UDEV_DEVICE(child);
81
377k
        fido_log_debug("%s", subsystem); /* XXX consume */
82
377k
        fido_log_debug("%s", devtype); /* XXX consume */
83
377k
        if (child->parent != NULL)
84
17.6k
                return child->parent;
85
360k
        if ((child->parent = calloc(1, sizeof(*child->parent))) == NULL)
86
970
                return NULL;
87
359k
        child->parent->magic = UDEV_DEVICE_MAGIC;
88
89
359k
        return child->parent;
90
360k
}
91
92
const char *
93
__wrap_udev_device_get_sysattr_value(struct udev_device *udev_device,
94
    const char *sysattr)
95
376k
{
96
376k
        ASSERT_UDEV_DEVICE(udev_device);
97
376k
        if (uniform_random(400) < 1)
98
1.11k
                return NULL;
99
375k
        if (!strcmp(sysattr, "manufacturer") || !strcmp(sysattr, "product"))
100
17.4k
                return "product info"; /* XXX randomise? */
101
358k
        else if (!strcmp(sysattr, "uevent"))
102
358k
                return uevent;
103
104
0
        return NULL;
105
375k
}
106
107
const char *
108
__wrap_udev_list_entry_get_name(struct udev_list_entry *entry)
109
5.03M
{
110
5.03M
        ASSERT_UDEV_LIST_ENTRY(entry);
111
5.03M
        return uniform_random(400) < 1 ? NULL : "name"; /* XXX randomise? */
112
5.03M
}
113
114
struct udev_device *
115
__wrap_udev_device_new_from_syspath(struct udev *udev, const char *syspath)
116
7.50M
{
117
7.50M
        struct udev_device *udev_device;
118
119
7.50M
        ASSERT_UDEV(udev);
120
7.50M
        fido_log_debug("%s", syspath);
121
7.50M
        if ((udev_device = calloc(1, sizeof(*udev_device))) == NULL)
122
19.2k
                return NULL;
123
7.48M
        udev_device->magic = UDEV_DEVICE_MAGIC;
124
125
7.48M
        return udev_device;
126
7.50M
}
127
128
const char *
129
__wrap_udev_device_get_devnode(struct udev_device *udev_device)
130
2.49M
{
131
2.49M
        ASSERT_UDEV_DEVICE(udev_device);
132
2.49M
        return uniform_random(400) < 1 ? NULL : "/dev/zero";
133
2.49M
}
134
135
const char *
136
__wrap_udev_device_get_sysnum(struct udev_device *udev_device)
137
2.47M
{
138
2.47M
        ASSERT_UDEV_DEVICE(udev_device);
139
2.47M
        return uniform_random(400) < 1 ? NULL : "101010"; /* XXX randomise? */
140
2.47M
}
141
142
void
143
__wrap_udev_device_unref(struct udev_device *udev_device)
144
7.48M
{
145
7.48M
        ASSERT_UDEV_DEVICE(udev_device);
146
7.48M
        if (udev_device->parent) {
147
359k
                ASSERT_UDEV_DEVICE(udev_device->parent);
148
359k
                free(udev_device->parent);
149
359k
        }
150
7.48M
        free(udev_device);
151
7.48M
}
152
153
struct udev *
154
__wrap_udev_new(void)
155
2.50M
{
156
2.50M
        struct udev *udev;
157
158
2.50M
        if ((udev = calloc(1, sizeof(*udev))) == NULL)
159
6.52k
                return NULL;
160
2.49M
        udev->magic = UDEV_MAGIC;
161
162
2.49M
        return udev;
163
2.50M
}
164
165
struct udev_enumerate *
166
__wrap_udev_enumerate_new(struct udev *udev)
167
11.7k
{
168
11.7k
        struct udev_enumerate *udev_enum;
169
170
11.7k
        ASSERT_UDEV(udev);
171
11.7k
        if ((udev_enum = calloc(1, sizeof(*udev_enum))) == NULL)
172
53
                return NULL;
173
11.6k
        udev_enum->magic = UDEV_ENUM_MAGIC;
174
175
11.6k
        return udev_enum;
176
11.7k
}
177
178
int
179
__wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum,
180
    const char *subsystem)
181
11.6k
{
182
11.6k
        ASSERT_UDEV_ENUM(udev_enum);
183
11.6k
        fido_log_debug("%s:", subsystem);
184
11.6k
        return uniform_random(400) < 1 ? -EINVAL : 0;
185
11.6k
}
186
187
int
188
__wrap_udev_enumerate_scan_devices(struct udev_enumerate *udev_enum)
189
11.6k
{
190
11.6k
        ASSERT_UDEV_ENUM(udev_enum);
191
11.6k
        return uniform_random(400) < 1 ? -EINVAL : 0;
192
11.6k
}
193
194
struct udev_list_entry *
195
__wrap_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enum)
196
11.6k
{
197
11.6k
        ASSERT_UDEV_ENUM(udev_enum);
198
11.6k
        if ((udev_enum->list_entry = calloc(1,
199
11.6k
            sizeof(*udev_enum->list_entry))) == NULL)
200
19
                return NULL;
201
11.6k
        udev_enum->list_entry->magic = UDEV_LIST_ENTRY_MAGIC;
202
203
11.6k
        return udev_enum->list_entry;
204
11.6k
}
205
206
struct udev_list_entry *
207
__wrap_udev_list_entry_get_next(struct udev_list_entry *udev_list_entry)
208
5.03M
{
209
5.03M
        ASSERT_UDEV_LIST_ENTRY(udev_list_entry);
210
5.03M
        return uniform_random(400) < 1 ? NULL : udev_list_entry;
211
5.03M
}
212
213
void
214
__wrap_udev_enumerate_unref(struct udev_enumerate *udev_enum)
215
11.6k
{
216
11.6k
        ASSERT_UDEV_ENUM(udev_enum);
217
11.6k
        if (udev_enum->list_entry)
218
11.6k
                ASSERT_UDEV_LIST_ENTRY(udev_enum->list_entry);
219
11.6k
        free(udev_enum->list_entry);
220
11.6k
        free(udev_enum);
221
11.6k
}
222
223
void
224
__wrap_udev_unref(struct udev *udev)
225
2.49M
{
226
2.49M
        ASSERT_UDEV(udev);
227
2.49M
        free(udev);
228
2.49M
}
229
230
int
231
__wrap_ioctl(int fd, unsigned long request, ...)
232
4.96M
{
233
4.96M
        va_list ap;
234
4.96M
        struct hidraw_report_descriptor *hrd;
235
236
4.96M
        (void)fd;
237
238
4.96M
        if (uniform_random(400) < 1) {
239
12.0k
                errno = EINVAL;
240
12.0k
                return -1;
241
12.0k
        }
242
243
4.96M
        va_start(ap, request);
244
245
4.95M
        switch (IOCTL_REQ(request)) {
246
2.47M
        case IOCTL_REQ(HIDIOCGRDESCSIZE):
247
2.47M
                *va_arg(ap, int *) = (int)report_descriptor->len;
248
2.47M
                break;
249
2.47M
        case IOCTL_REQ(HIDIOCGRDESC):
250
2.47M
                hrd = va_arg(ap, struct hidraw_report_descriptor *);
251
2.47M
                assert(hrd->size == report_descriptor->len);
252
2.47M
                memcpy(hrd->value, report_descriptor->body, hrd->size);
253
2.47M
                break;
254
0
        default:
255
0
                warnx("%s: unknown request 0x%lx", __func__, request);
256
0
                abort();
257
4.95M
        }
258
259
4.95M
        va_end(ap);
260
261
4.95M
        return 0;
262
4.95M
}
263
264
void
265
set_udev_parameters(const char *uevent_ptr,
266
    const struct blob *report_descriptor_ptr)
267
6.02k
{
268
6.02k
        uevent = uevent_ptr;
269
6.02k
        report_descriptor = report_descriptor_ptr;
270
6.02k
}