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
10 #include <linux/hidraw.h>
11 #include <linux/input.h>
18 #include "mutator_aux.h"
24 struct udev_enumerate {
26 struct udev_list_entry *list_entry;
29 struct udev_list_entry {
35 struct udev_device *parent;
38 #define UDEV_MAGIC 0x584492cc
39 #define UDEV_DEVICE_MAGIC 0x569180dd
40 #define UDEV_LIST_ENTRY_MAGIC 0x497422ee
41 #define UDEV_ENUM_MAGIC 0x583570ff
43 #define ASSERT_TYPE(x, m) assert((x) != NULL && (x)->magic == (m))
44 #define ASSERT_UDEV(x) ASSERT_TYPE((x), UDEV_MAGIC)
45 #define ASSERT_UDEV_ENUM(x) ASSERT_TYPE((x), UDEV_ENUM_MAGIC)
46 #define ASSERT_UDEV_LIST_ENTRY(x) ASSERT_TYPE((x), UDEV_LIST_ENTRY_MAGIC)
47 #define ASSERT_UDEV_DEVICE(x) ASSERT_TYPE((x), UDEV_DEVICE_MAGIC)
49 static const char *uevent;
50 static const struct blob *report_descriptor;
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 *,
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 *,
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 *,
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 *);
77 __wrap_udev_device_get_parent_with_subsystem_devtype(struct udev_device *child,
78 const char *subsystem, const char *devtype)
80 ASSERT_UDEV_DEVICE(child);
81 fido_log_debug("%s", subsystem); /* XXX consume */
82 fido_log_debug("%s", devtype); /* XXX consume */
83 if (child->parent != NULL)
85 if ((child->parent = calloc(1, sizeof(*child->parent))) == NULL)
87 child->parent->magic = UDEV_DEVICE_MAGIC;
93 __wrap_udev_device_get_sysattr_value(struct udev_device *udev_device,
96 ASSERT_UDEV_DEVICE(udev_device);
97 if (uniform_random(400) < 1)
99 if (!strcmp(sysattr, "manufacturer") || !strcmp(sysattr, "product"))
100 return "product info"; /* XXX randomise? */
101 else if (!strcmp(sysattr, "uevent"))
108 __wrap_udev_list_entry_get_name(struct udev_list_entry *entry)
110 ASSERT_UDEV_LIST_ENTRY(entry);
111 return uniform_random(400) < 1 ? NULL : "name"; /* XXX randomise? */
115 __wrap_udev_device_new_from_syspath(struct udev *udev, const char *syspath)
117 struct udev_device *udev_device;
120 fido_log_debug("%s", syspath);
121 if ((udev_device = calloc(1, sizeof(*udev_device))) == NULL)
123 udev_device->magic = UDEV_DEVICE_MAGIC;
129 __wrap_udev_device_get_devnode(struct udev_device *udev_device)
131 ASSERT_UDEV_DEVICE(udev_device);
132 return uniform_random(400) < 1 ? NULL : "/dev/zero";
136 __wrap_udev_device_get_sysnum(struct udev_device *udev_device)
138 ASSERT_UDEV_DEVICE(udev_device);
139 return uniform_random(400) < 1 ? NULL : "101010"; /* XXX randomise? */
143 __wrap_udev_device_unref(struct udev_device *udev_device)
145 ASSERT_UDEV_DEVICE(udev_device);
146 if (udev_device->parent) {
147 ASSERT_UDEV_DEVICE(udev_device->parent);
148 free(udev_device->parent);
154 __wrap_udev_new(void)
158 if ((udev = calloc(1, sizeof(*udev))) == NULL)
160 udev->magic = UDEV_MAGIC;
165 struct udev_enumerate *
166 __wrap_udev_enumerate_new(struct udev *udev)
168 struct udev_enumerate *udev_enum;
171 if ((udev_enum = calloc(1, sizeof(*udev_enum))) == NULL)
173 udev_enum->magic = UDEV_ENUM_MAGIC;
179 __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum,
180 const char *subsystem)
182 ASSERT_UDEV_ENUM(udev_enum);
183 fido_log_debug("%s:", subsystem);
184 return uniform_random(400) < 1 ? -EINVAL : 0;
188 __wrap_udev_enumerate_scan_devices(struct udev_enumerate *udev_enum)
190 ASSERT_UDEV_ENUM(udev_enum);
191 return uniform_random(400) < 1 ? -EINVAL : 0;
194 struct udev_list_entry *
195 __wrap_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enum)
197 ASSERT_UDEV_ENUM(udev_enum);
198 if ((udev_enum->list_entry = calloc(1,
199 sizeof(*udev_enum->list_entry))) == NULL)
201 udev_enum->list_entry->magic = UDEV_LIST_ENTRY_MAGIC;
203 return udev_enum->list_entry;
206 struct udev_list_entry *
207 __wrap_udev_list_entry_get_next(struct udev_list_entry *udev_list_entry)
209 ASSERT_UDEV_LIST_ENTRY(udev_list_entry);
210 return uniform_random(400) < 1 ? NULL : udev_list_entry;
214 __wrap_udev_enumerate_unref(struct udev_enumerate *udev_enum)
216 ASSERT_UDEV_ENUM(udev_enum);
217 if (udev_enum->list_entry)
218 ASSERT_UDEV_LIST_ENTRY(udev_enum->list_entry);
219 free(udev_enum->list_entry);
224 __wrap_udev_unref(struct udev *udev)
231 __wrap_ioctl(int fd, unsigned long request, ...)
234 struct hidraw_report_descriptor *hrd;
238 if (uniform_random(400) < 1) {
243 va_start(ap, request);
245 switch (IOCTL_REQ(request)) {
246 case IOCTL_REQ(HIDIOCGRDESCSIZE):
247 *va_arg(ap, int *) = (int)report_descriptor->len;
249 case IOCTL_REQ(HIDIOCGRDESC):
250 hrd = va_arg(ap, struct hidraw_report_descriptor *);
251 assert(hrd->size == report_descriptor->len);
252 memcpy(hrd->value, report_descriptor->body, hrd->size);
255 warnx("%s: unknown request 0x%lx", __func__, request);
265 set_udev_parameters(const char *uevent_ptr,
266 const struct blob *report_descriptor_ptr)
269 report_descriptor = report_descriptor_ptr;