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 #define UDEV_MAGIC 0x584492cc 38 #define UDEV_DEVICE_MAGIC 0x569180dd 39 #define UDEV_LIST_ENTRY_MAGIC 0x497422ee 40 #define UDEV_ENUM_MAGIC 0x583570ff 41 42 #define ASSERT_TYPE(x, m) assert((x) != NULL && (x)->magic == (m)) 43 #define ASSERT_UDEV(x) ASSERT_TYPE((x), UDEV_MAGIC) 44 #define ASSERT_UDEV_ENUM(x) ASSERT_TYPE((x), UDEV_ENUM_MAGIC) 45 #define ASSERT_UDEV_LIST_ENTRY(x) ASSERT_TYPE((x), UDEV_LIST_ENTRY_MAGIC) 46 #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 { 79 ASSERT_UDEV_DEVICE(child); 80 fido_log_debug("%s", subsystem); /* XXX consume */ 81 fido_log_debug("%s", devtype); /* XXX consume */ 82 if (child->parent != NULL) 83 return child->parent; 84 if ((child->parent = calloc(1, sizeof(*child->parent))) == NULL) 85 return NULL; 86 child->parent->magic = UDEV_DEVICE_MAGIC; 87 88 return child->parent; 89 } 90 91 const char * 92 __wrap_udev_device_get_sysattr_value(struct udev_device *udev_device, 93 const char *sysattr) 94 { 95 ASSERT_UDEV_DEVICE(udev_device); 96 if (uniform_random(400) < 1) 97 return NULL; 98 if (!strcmp(sysattr, "manufacturer") || !strcmp(sysattr, "product")) 99 return "product info"; /* XXX randomise? */ 100 else if (!strcmp(sysattr, "uevent")) 101 return uevent; 102 103 return NULL; 104 } 105 106 const char * 107 __wrap_udev_list_entry_get_name(struct udev_list_entry *entry) 108 { 109 ASSERT_UDEV_LIST_ENTRY(entry); 110 return uniform_random(400) < 1 ? NULL : "name"; /* XXX randomise? */ 111 } 112 113 struct udev_device * 114 __wrap_udev_device_new_from_syspath(struct udev *udev, const char *syspath) 115 { 116 struct udev_device *udev_device; 117 118 ASSERT_UDEV(udev); 119 fido_log_debug("%s", syspath); 120 if ((udev_device = calloc(1, sizeof(*udev_device))) == NULL) 121 return NULL; 122 udev_device->magic = UDEV_DEVICE_MAGIC; 123 124 return udev_device; 125 } 126 127 const char * 128 __wrap_udev_device_get_devnode(struct udev_device *udev_device) 129 { 130 ASSERT_UDEV_DEVICE(udev_device); 131 return uniform_random(400) < 1 ? NULL : "/dev/zero"; 132 } 133 134 const char * 135 __wrap_udev_device_get_sysnum(struct udev_device *udev_device) 136 { 137 ASSERT_UDEV_DEVICE(udev_device); 138 return uniform_random(400) < 1 ? NULL : "101010"; /* XXX randomise? */ 139 } 140 141 void 142 __wrap_udev_device_unref(struct udev_device *udev_device) 143 { 144 ASSERT_UDEV_DEVICE(udev_device); 145 if (udev_device->parent) { 146 ASSERT_UDEV_DEVICE(udev_device->parent); 147 free(udev_device->parent); 148 } 149 free(udev_device); 150 } 151 152 struct udev * 153 __wrap_udev_new(void) 154 { 155 struct udev *udev; 156 157 if ((udev = calloc(1, sizeof(*udev))) == NULL) 158 return NULL; 159 udev->magic = UDEV_MAGIC; 160 161 return udev; 162 } 163 164 struct udev_enumerate * 165 __wrap_udev_enumerate_new(struct udev *udev) 166 { 167 struct udev_enumerate *udev_enum; 168 169 ASSERT_UDEV(udev); 170 if ((udev_enum = calloc(1, sizeof(*udev_enum))) == NULL) 171 return NULL; 172 udev_enum->magic = UDEV_ENUM_MAGIC; 173 174 return udev_enum; 175 } 176 177 int 178 __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum, 179 const char *subsystem) 180 { 181 ASSERT_UDEV_ENUM(udev_enum); 182 fido_log_debug("%s:", subsystem); 183 return uniform_random(400) < 1 ? -EINVAL : 0; 184 } 185 186 int 187 __wrap_udev_enumerate_scan_devices(struct udev_enumerate *udev_enum) 188 { 189 ASSERT_UDEV_ENUM(udev_enum); 190 return uniform_random(400) < 1 ? -EINVAL : 0; 191 } 192 193 struct udev_list_entry * 194 __wrap_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enum) 195 { 196 ASSERT_UDEV_ENUM(udev_enum); 197 if ((udev_enum->list_entry = calloc(1, 198 sizeof(*udev_enum->list_entry))) == NULL) 199 return NULL; 200 udev_enum->list_entry->magic = UDEV_LIST_ENTRY_MAGIC; 201 202 return udev_enum->list_entry; 203 } 204 205 struct udev_list_entry * 206 __wrap_udev_list_entry_get_next(struct udev_list_entry *udev_list_entry) 207 { 208 ASSERT_UDEV_LIST_ENTRY(udev_list_entry); 209 return uniform_random(400) < 1 ? NULL : udev_list_entry; 210 } 211 212 void 213 __wrap_udev_enumerate_unref(struct udev_enumerate *udev_enum) 214 { 215 ASSERT_UDEV_ENUM(udev_enum); 216 if (udev_enum->list_entry) 217 ASSERT_UDEV_LIST_ENTRY(udev_enum->list_entry); 218 free(udev_enum->list_entry); 219 free(udev_enum); 220 } 221 222 void 223 __wrap_udev_unref(struct udev *udev) 224 { 225 ASSERT_UDEV(udev); 226 free(udev); 227 } 228 229 int 230 __wrap_ioctl(int fd, unsigned long request, ...) 231 { 232 va_list ap; 233 struct hidraw_report_descriptor *hrd; 234 235 (void)fd; 236 237 if (uniform_random(400) < 1) { 238 errno = EINVAL; 239 return -1; 240 } 241 242 va_start(ap, request); 243 244 switch (request) { 245 case IOCTL_REQ(HIDIOCGRDESCSIZE): 246 *va_arg(ap, int *) = (int)report_descriptor->len; 247 break; 248 case IOCTL_REQ(HIDIOCGRDESC): 249 hrd = va_arg(ap, struct hidraw_report_descriptor *); 250 assert(hrd->size == report_descriptor->len); 251 memcpy(hrd->value, report_descriptor->body, hrd->size); 252 break; 253 default: 254 warnx("%s: unknown request 0x%lx", __func__, request); 255 abort(); 256 } 257 258 va_end(ap); 259 260 return 0; 261 } 262 263 void 264 set_udev_parameters(const char *uevent_ptr, 265 const struct blob *report_descriptor_ptr) 266 { 267 uevent = uevent_ptr; 268 report_descriptor = report_descriptor_ptr; 269 } 270