Coverage Report

Created: 2022-01-17 10:46

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