## 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
    }