Path: blob/main/contrib/libfido2/fuzz/preload-snoop.c
39586 views
/*1* Copyright (c) 2019 Yubico AB. All rights reserved.2* Use of this source code is governed by a BSD-style3* license that can be found in the LICENSE file.4* SPDX-License-Identifier: BSD-2-Clause5*/67/*8* cc -fPIC -D_GNU_SOURCE -shared -o preload-snoop.so preload-snoop.c9* LD_PRELOAD=$(realpath preload-snoop.so)10*/1112#include <sys/types.h>13#include <sys/stat.h>1415#include <dlfcn.h>16#include <err.h>17#include <errno.h>18#include <fcntl.h>19#include <limits.h>20#include <stdarg.h>21#include <stdio.h>22#include <stdlib.h>23#include <string.h>24#include <unistd.h>2526#define SNOOP_DEV_PREFIX "/dev/hidraw"2728struct fd_tuple {29int snoop_in;30int snoop_out;31int real_dev;32};3334static struct fd_tuple *fd_tuple;35static int (*open_f)(const char *, int, mode_t);36static int (*close_f)(int);37static ssize_t (*read_f)(int, void *, size_t);38static ssize_t (*write_f)(int, const void *, size_t);3940static int41get_fd(const char *hid_path, const char *suffix)42{43char *s = NULL;44char path[PATH_MAX];45int fd;46int r;4748if ((s = strdup(hid_path)) == NULL) {49warnx("%s: strdup", __func__);50return (-1);51}5253for (size_t i = 0; i < strlen(s); i++)54if (s[i] == '/')55s[i] = '_';5657if ((r = snprintf(path, sizeof(path), "%s-%s", s, suffix)) < 0 ||58(size_t)r >= sizeof(path)) {59warnx("%s: snprintf", __func__);60free(s);61return (-1);62}6364free(s);65s = NULL;6667if ((fd = open_f(path, O_CREAT | O_WRONLY, 0644)) < 0) {68warn("%s: open", __func__);69return (-1);70}7172return (fd);73}7475int76open(const char *path, int flags, ...)77{78va_list ap;79mode_t mode;8081va_start(ap, flags);82mode = va_arg(ap, mode_t);83va_end(ap);8485if (open_f == NULL) {86open_f = dlsym(RTLD_NEXT, "open");87if (open_f == NULL) {88warnx("%s: dlsym", __func__);89errno = EACCES;90return (-1);91}92}9394if (strncmp(path, SNOOP_DEV_PREFIX, strlen(SNOOP_DEV_PREFIX)) != 0)95return (open_f(path, flags, mode));9697if (fd_tuple != NULL) {98warnx("%s: fd_tuple != NULL", __func__);99errno = EACCES;100return (-1);101}102103if ((fd_tuple = calloc(1, sizeof(*fd_tuple))) == NULL) {104warn("%s: calloc", __func__);105errno = ENOMEM;106return (-1);107}108109fd_tuple->snoop_in = -1;110fd_tuple->snoop_out = -1;111fd_tuple->real_dev = -1;112113if ((fd_tuple->snoop_in = get_fd(path, "in")) < 0 ||114(fd_tuple->snoop_out = get_fd(path, "out")) < 0 ||115(fd_tuple->real_dev = open_f(path, flags, mode)) < 0) {116warn("%s: get_fd/open", __func__);117goto fail;118}119120return (fd_tuple->real_dev);121fail:122if (fd_tuple->snoop_in != -1)123close(fd_tuple->snoop_in);124if (fd_tuple->snoop_out != -1)125close(fd_tuple->snoop_out);126if (fd_tuple->real_dev != -1)127close(fd_tuple->real_dev);128129free(fd_tuple);130fd_tuple = NULL;131132errno = EACCES;133134return (-1);135}136137int138close(int fd)139{140if (close_f == NULL) {141close_f = dlsym(RTLD_NEXT, "close");142if (close_f == NULL) {143warnx("%s: dlsym", __func__);144errno = EBADF;145return (-1);146}147}148149if (fd_tuple == NULL || fd_tuple->real_dev != fd)150return (close_f(fd));151152close_f(fd_tuple->snoop_in);153close_f(fd_tuple->snoop_out);154close_f(fd_tuple->real_dev);155156free(fd_tuple);157fd_tuple = NULL;158159return (0);160}161162ssize_t163read(int fd, void *buf, size_t nbytes)164{165ssize_t n;166167if (read_f == NULL) {168read_f = dlsym(RTLD_NEXT, "read");169if (read_f == NULL) {170warnx("%s: dlsym", __func__);171errno = EBADF;172return (-1);173}174}175176if (write_f == NULL) {177write_f = dlsym(RTLD_NEXT, "write");178if (write_f == NULL) {179warnx("%s: dlsym", __func__);180errno = EBADF;181return (-1);182}183}184185if (fd_tuple == NULL || fd_tuple->real_dev != fd)186return (read_f(fd, buf, nbytes));187188if ((n = read_f(fd, buf, nbytes)) < 0 ||189write_f(fd_tuple->snoop_in, buf, n) != n)190return (-1);191192return (n);193}194195ssize_t196write(int fd, const void *buf, size_t nbytes)197{198ssize_t n;199200if (write_f == NULL) {201write_f = dlsym(RTLD_NEXT, "write");202if (write_f == NULL) {203warnx("%s: dlsym", __func__);204errno = EBADF;205return (-1);206}207}208209if (fd_tuple == NULL || fd_tuple->real_dev != fd)210return (write_f(fd, buf, nbytes));211212if ((n = write_f(fd, buf, nbytes)) < 0 ||213write_f(fd_tuple->snoop_out, buf, n) != n)214return (-1);215216return (n);217}218219220