10afa8e06SEd Maste /*
20afa8e06SEd Maste * Copyright (c) 2021 Yubico AB. All rights reserved.
30afa8e06SEd Maste * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste */
70afa8e06SEd Maste
80afa8e06SEd Maste #include <sys/types.h>
90afa8e06SEd Maste
100afa8e06SEd Maste #include <linux/hidraw.h>
110afa8e06SEd Maste #include <linux/input.h>
120afa8e06SEd Maste
130afa8e06SEd Maste #include <assert.h>
140afa8e06SEd Maste #include <errno.h>
150afa8e06SEd Maste #include <libudev.h>
160afa8e06SEd Maste #include <stdlib.h>
170afa8e06SEd Maste
180afa8e06SEd Maste #include "mutator_aux.h"
190afa8e06SEd Maste
200afa8e06SEd Maste struct udev {
210afa8e06SEd Maste int magic;
220afa8e06SEd Maste };
230afa8e06SEd Maste
240afa8e06SEd Maste struct udev_enumerate {
250afa8e06SEd Maste int magic;
260afa8e06SEd Maste struct udev_list_entry *list_entry;
270afa8e06SEd Maste };
280afa8e06SEd Maste
290afa8e06SEd Maste struct udev_list_entry {
300afa8e06SEd Maste int magic;
310afa8e06SEd Maste };
320afa8e06SEd Maste
330afa8e06SEd Maste struct udev_device {
340afa8e06SEd Maste int magic;
350afa8e06SEd Maste struct udev_device *parent;
360afa8e06SEd Maste };
370afa8e06SEd Maste
380afa8e06SEd Maste #define UDEV_MAGIC 0x584492cc
390afa8e06SEd Maste #define UDEV_DEVICE_MAGIC 0x569180dd
400afa8e06SEd Maste #define UDEV_LIST_ENTRY_MAGIC 0x497422ee
410afa8e06SEd Maste #define UDEV_ENUM_MAGIC 0x583570ff
420afa8e06SEd Maste
430afa8e06SEd Maste #define ASSERT_TYPE(x, m) assert((x) != NULL && (x)->magic == (m))
440afa8e06SEd Maste #define ASSERT_UDEV(x) ASSERT_TYPE((x), UDEV_MAGIC)
450afa8e06SEd Maste #define ASSERT_UDEV_ENUM(x) ASSERT_TYPE((x), UDEV_ENUM_MAGIC)
460afa8e06SEd Maste #define ASSERT_UDEV_LIST_ENTRY(x) ASSERT_TYPE((x), UDEV_LIST_ENTRY_MAGIC)
470afa8e06SEd Maste #define ASSERT_UDEV_DEVICE(x) ASSERT_TYPE((x), UDEV_DEVICE_MAGIC)
480afa8e06SEd Maste
490afa8e06SEd Maste static const char *uevent;
500afa8e06SEd Maste static const struct blob *report_descriptor;
510afa8e06SEd Maste
520afa8e06SEd Maste struct udev *__wrap_udev_new(void);
530afa8e06SEd Maste struct udev_device *__wrap_udev_device_get_parent_with_subsystem_devtype(
540afa8e06SEd Maste struct udev_device *, const char *, const char *);
550afa8e06SEd Maste struct udev_device *__wrap_udev_device_new_from_syspath(struct udev *,
560afa8e06SEd Maste const char *);
570afa8e06SEd Maste struct udev_enumerate *__wrap_udev_enumerate_new(struct udev *);
580afa8e06SEd Maste struct udev_list_entry *__wrap_udev_enumerate_get_list_entry(
590afa8e06SEd Maste struct udev_enumerate *);
600afa8e06SEd Maste struct udev_list_entry *__wrap_udev_list_entry_get_next(
610afa8e06SEd Maste struct udev_list_entry *);
620afa8e06SEd Maste const char *__wrap_udev_device_get_sysattr_value(struct udev_device *,
630afa8e06SEd Maste const char *);
640afa8e06SEd Maste const char *__wrap_udev_list_entry_get_name(struct udev_list_entry *);
650afa8e06SEd Maste const char *__wrap_udev_device_get_devnode(struct udev_device *);
660afa8e06SEd Maste const char *__wrap_udev_device_get_sysnum(struct udev_device *);
670afa8e06SEd Maste int __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *,
680afa8e06SEd Maste const char *);
690afa8e06SEd Maste int __wrap_udev_enumerate_scan_devices(struct udev_enumerate *);
700afa8e06SEd Maste int __wrap_ioctl(int, unsigned long , ...);
710afa8e06SEd Maste void __wrap_udev_device_unref(struct udev_device *);
720afa8e06SEd Maste void __wrap_udev_enumerate_unref(struct udev_enumerate *);
730afa8e06SEd Maste void __wrap_udev_unref(struct udev *);
740afa8e06SEd Maste void set_udev_parameters(const char *, const struct blob *);
750afa8e06SEd Maste
760afa8e06SEd Maste struct udev_device *
__wrap_udev_device_get_parent_with_subsystem_devtype(struct udev_device * child,const char * subsystem,const char * devtype)770afa8e06SEd Maste __wrap_udev_device_get_parent_with_subsystem_devtype(struct udev_device *child,
780afa8e06SEd Maste const char *subsystem, const char *devtype)
790afa8e06SEd Maste {
800afa8e06SEd Maste ASSERT_UDEV_DEVICE(child);
810afa8e06SEd Maste fido_log_debug("%s", subsystem); /* XXX consume */
820afa8e06SEd Maste fido_log_debug("%s", devtype); /* XXX consume */
830afa8e06SEd Maste if (child->parent != NULL)
840afa8e06SEd Maste return child->parent;
850afa8e06SEd Maste if ((child->parent = calloc(1, sizeof(*child->parent))) == NULL)
860afa8e06SEd Maste return NULL;
870afa8e06SEd Maste child->parent->magic = UDEV_DEVICE_MAGIC;
880afa8e06SEd Maste
890afa8e06SEd Maste return child->parent;
900afa8e06SEd Maste }
910afa8e06SEd Maste
920afa8e06SEd Maste const char *
__wrap_udev_device_get_sysattr_value(struct udev_device * udev_device,const char * sysattr)930afa8e06SEd Maste __wrap_udev_device_get_sysattr_value(struct udev_device *udev_device,
940afa8e06SEd Maste const char *sysattr)
950afa8e06SEd Maste {
960afa8e06SEd Maste ASSERT_UDEV_DEVICE(udev_device);
970afa8e06SEd Maste if (uniform_random(400) < 1)
980afa8e06SEd Maste return NULL;
990afa8e06SEd Maste if (!strcmp(sysattr, "manufacturer") || !strcmp(sysattr, "product"))
1000afa8e06SEd Maste return "product info"; /* XXX randomise? */
1010afa8e06SEd Maste else if (!strcmp(sysattr, "uevent"))
1020afa8e06SEd Maste return uevent;
1030afa8e06SEd Maste
1040afa8e06SEd Maste return NULL;
1050afa8e06SEd Maste }
1060afa8e06SEd Maste
1070afa8e06SEd Maste const char *
__wrap_udev_list_entry_get_name(struct udev_list_entry * entry)1080afa8e06SEd Maste __wrap_udev_list_entry_get_name(struct udev_list_entry *entry)
1090afa8e06SEd Maste {
1100afa8e06SEd Maste ASSERT_UDEV_LIST_ENTRY(entry);
1110afa8e06SEd Maste return uniform_random(400) < 1 ? NULL : "name"; /* XXX randomise? */
1120afa8e06SEd Maste }
1130afa8e06SEd Maste
1140afa8e06SEd Maste struct udev_device *
__wrap_udev_device_new_from_syspath(struct udev * udev,const char * syspath)1150afa8e06SEd Maste __wrap_udev_device_new_from_syspath(struct udev *udev, const char *syspath)
1160afa8e06SEd Maste {
1170afa8e06SEd Maste struct udev_device *udev_device;
1180afa8e06SEd Maste
1190afa8e06SEd Maste ASSERT_UDEV(udev);
1200afa8e06SEd Maste fido_log_debug("%s", syspath);
1210afa8e06SEd Maste if ((udev_device = calloc(1, sizeof(*udev_device))) == NULL)
1220afa8e06SEd Maste return NULL;
1230afa8e06SEd Maste udev_device->magic = UDEV_DEVICE_MAGIC;
1240afa8e06SEd Maste
1250afa8e06SEd Maste return udev_device;
1260afa8e06SEd Maste }
1270afa8e06SEd Maste
1280afa8e06SEd Maste const char *
__wrap_udev_device_get_devnode(struct udev_device * udev_device)1290afa8e06SEd Maste __wrap_udev_device_get_devnode(struct udev_device *udev_device)
1300afa8e06SEd Maste {
1310afa8e06SEd Maste ASSERT_UDEV_DEVICE(udev_device);
1320afa8e06SEd Maste return uniform_random(400) < 1 ? NULL : "/dev/zero";
1330afa8e06SEd Maste }
1340afa8e06SEd Maste
1350afa8e06SEd Maste const char *
__wrap_udev_device_get_sysnum(struct udev_device * udev_device)1360afa8e06SEd Maste __wrap_udev_device_get_sysnum(struct udev_device *udev_device)
1370afa8e06SEd Maste {
1380afa8e06SEd Maste ASSERT_UDEV_DEVICE(udev_device);
1390afa8e06SEd Maste return uniform_random(400) < 1 ? NULL : "101010"; /* XXX randomise? */
1400afa8e06SEd Maste }
1410afa8e06SEd Maste
1420afa8e06SEd Maste void
__wrap_udev_device_unref(struct udev_device * udev_device)1430afa8e06SEd Maste __wrap_udev_device_unref(struct udev_device *udev_device)
1440afa8e06SEd Maste {
1450afa8e06SEd Maste ASSERT_UDEV_DEVICE(udev_device);
1460afa8e06SEd Maste if (udev_device->parent) {
1470afa8e06SEd Maste ASSERT_UDEV_DEVICE(udev_device->parent);
1480afa8e06SEd Maste free(udev_device->parent);
1490afa8e06SEd Maste }
1500afa8e06SEd Maste free(udev_device);
1510afa8e06SEd Maste }
1520afa8e06SEd Maste
1530afa8e06SEd Maste struct udev *
__wrap_udev_new(void)1540afa8e06SEd Maste __wrap_udev_new(void)
1550afa8e06SEd Maste {
1560afa8e06SEd Maste struct udev *udev;
1570afa8e06SEd Maste
1580afa8e06SEd Maste if ((udev = calloc(1, sizeof(*udev))) == NULL)
1590afa8e06SEd Maste return NULL;
1600afa8e06SEd Maste udev->magic = UDEV_MAGIC;
1610afa8e06SEd Maste
1620afa8e06SEd Maste return udev;
1630afa8e06SEd Maste }
1640afa8e06SEd Maste
1650afa8e06SEd Maste struct udev_enumerate *
__wrap_udev_enumerate_new(struct udev * udev)1660afa8e06SEd Maste __wrap_udev_enumerate_new(struct udev *udev)
1670afa8e06SEd Maste {
1680afa8e06SEd Maste struct udev_enumerate *udev_enum;
1690afa8e06SEd Maste
1700afa8e06SEd Maste ASSERT_UDEV(udev);
1710afa8e06SEd Maste if ((udev_enum = calloc(1, sizeof(*udev_enum))) == NULL)
1720afa8e06SEd Maste return NULL;
1730afa8e06SEd Maste udev_enum->magic = UDEV_ENUM_MAGIC;
1740afa8e06SEd Maste
1750afa8e06SEd Maste return udev_enum;
1760afa8e06SEd Maste }
1770afa8e06SEd Maste
1780afa8e06SEd Maste int
__wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate * udev_enum,const char * subsystem)1790afa8e06SEd Maste __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum,
1800afa8e06SEd Maste const char *subsystem)
1810afa8e06SEd Maste {
1820afa8e06SEd Maste ASSERT_UDEV_ENUM(udev_enum);
1830afa8e06SEd Maste fido_log_debug("%s:", subsystem);
1840afa8e06SEd Maste return uniform_random(400) < 1 ? -EINVAL : 0;
1850afa8e06SEd Maste }
1860afa8e06SEd Maste
1870afa8e06SEd Maste int
__wrap_udev_enumerate_scan_devices(struct udev_enumerate * udev_enum)1880afa8e06SEd Maste __wrap_udev_enumerate_scan_devices(struct udev_enumerate *udev_enum)
1890afa8e06SEd Maste {
1900afa8e06SEd Maste ASSERT_UDEV_ENUM(udev_enum);
1910afa8e06SEd Maste return uniform_random(400) < 1 ? -EINVAL : 0;
1920afa8e06SEd Maste }
1930afa8e06SEd Maste
1940afa8e06SEd Maste struct udev_list_entry *
__wrap_udev_enumerate_get_list_entry(struct udev_enumerate * udev_enum)1950afa8e06SEd Maste __wrap_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enum)
1960afa8e06SEd Maste {
1970afa8e06SEd Maste ASSERT_UDEV_ENUM(udev_enum);
1980afa8e06SEd Maste if ((udev_enum->list_entry = calloc(1,
1990afa8e06SEd Maste sizeof(*udev_enum->list_entry))) == NULL)
2000afa8e06SEd Maste return NULL;
2010afa8e06SEd Maste udev_enum->list_entry->magic = UDEV_LIST_ENTRY_MAGIC;
2020afa8e06SEd Maste
2030afa8e06SEd Maste return udev_enum->list_entry;
2040afa8e06SEd Maste }
2050afa8e06SEd Maste
2060afa8e06SEd Maste struct udev_list_entry *
__wrap_udev_list_entry_get_next(struct udev_list_entry * udev_list_entry)2070afa8e06SEd Maste __wrap_udev_list_entry_get_next(struct udev_list_entry *udev_list_entry)
2080afa8e06SEd Maste {
2090afa8e06SEd Maste ASSERT_UDEV_LIST_ENTRY(udev_list_entry);
2100afa8e06SEd Maste return uniform_random(400) < 1 ? NULL : udev_list_entry;
2110afa8e06SEd Maste }
2120afa8e06SEd Maste
2130afa8e06SEd Maste void
__wrap_udev_enumerate_unref(struct udev_enumerate * udev_enum)2140afa8e06SEd Maste __wrap_udev_enumerate_unref(struct udev_enumerate *udev_enum)
2150afa8e06SEd Maste {
2160afa8e06SEd Maste ASSERT_UDEV_ENUM(udev_enum);
2170afa8e06SEd Maste if (udev_enum->list_entry)
2180afa8e06SEd Maste ASSERT_UDEV_LIST_ENTRY(udev_enum->list_entry);
2190afa8e06SEd Maste free(udev_enum->list_entry);
2200afa8e06SEd Maste free(udev_enum);
2210afa8e06SEd Maste }
2220afa8e06SEd Maste
2230afa8e06SEd Maste void
__wrap_udev_unref(struct udev * udev)2240afa8e06SEd Maste __wrap_udev_unref(struct udev *udev)
2250afa8e06SEd Maste {
2260afa8e06SEd Maste ASSERT_UDEV(udev);
2270afa8e06SEd Maste free(udev);
2280afa8e06SEd Maste }
2290afa8e06SEd Maste
2300afa8e06SEd Maste int
__wrap_ioctl(int fd,unsigned long request,...)2310afa8e06SEd Maste __wrap_ioctl(int fd, unsigned long request, ...)
2320afa8e06SEd Maste {
2330afa8e06SEd Maste va_list ap;
2340afa8e06SEd Maste struct hidraw_report_descriptor *hrd;
2350afa8e06SEd Maste
2360afa8e06SEd Maste (void)fd;
2370afa8e06SEd Maste
2380afa8e06SEd Maste if (uniform_random(400) < 1) {
2390afa8e06SEd Maste errno = EINVAL;
2400afa8e06SEd Maste return -1;
2410afa8e06SEd Maste }
2420afa8e06SEd Maste
2430afa8e06SEd Maste va_start(ap, request);
2440afa8e06SEd Maste
245*2ccfa855SEd Maste switch (IOCTL_REQ(request)) {
2460afa8e06SEd Maste case IOCTL_REQ(HIDIOCGRDESCSIZE):
2470afa8e06SEd Maste *va_arg(ap, int *) = (int)report_descriptor->len;
2480afa8e06SEd Maste break;
2490afa8e06SEd Maste case IOCTL_REQ(HIDIOCGRDESC):
2500afa8e06SEd Maste hrd = va_arg(ap, struct hidraw_report_descriptor *);
2510afa8e06SEd Maste assert(hrd->size == report_descriptor->len);
2520afa8e06SEd Maste memcpy(hrd->value, report_descriptor->body, hrd->size);
2530afa8e06SEd Maste break;
2540afa8e06SEd Maste default:
2550afa8e06SEd Maste warnx("%s: unknown request 0x%lx", __func__, request);
2560afa8e06SEd Maste abort();
2570afa8e06SEd Maste }
2580afa8e06SEd Maste
2590afa8e06SEd Maste va_end(ap);
2600afa8e06SEd Maste
2610afa8e06SEd Maste return 0;
2620afa8e06SEd Maste }
2630afa8e06SEd Maste
2640afa8e06SEd Maste void
set_udev_parameters(const char * uevent_ptr,const struct blob * report_descriptor_ptr)2650afa8e06SEd Maste set_udev_parameters(const char *uevent_ptr,
2660afa8e06SEd Maste const struct blob *report_descriptor_ptr)
2670afa8e06SEd Maste {
2680afa8e06SEd Maste uevent = uevent_ptr;
2690afa8e06SEd Maste report_descriptor = report_descriptor_ptr;
2700afa8e06SEd Maste }
271