1ba9bdd8bSchristos /*
2ba9bdd8bSchristos * Copyright (c) 2019 Yubico AB. All rights reserved.
3ba9bdd8bSchristos * Use of this source code is governed by a BSD-style
4ba9bdd8bSchristos * license that can be found in the LICENSE file.
5*2d40c451Schristos * SPDX-License-Identifier: BSD-2-Clause
6ba9bdd8bSchristos */
7ba9bdd8bSchristos
8ba9bdd8bSchristos /*
9ba9bdd8bSchristos * cc -fPIC -D_GNU_SOURCE -shared -o preload-fuzz.so preload-fuzz.c
10ba9bdd8bSchristos * LD_PRELOAD=$(realpath preload-fuzz.so)
11ba9bdd8bSchristos */
12ba9bdd8bSchristos
13ba9bdd8bSchristos #include <sys/types.h>
14ba9bdd8bSchristos #include <sys/stat.h>
15ba9bdd8bSchristos
16ba9bdd8bSchristos #include <dlfcn.h>
17ba9bdd8bSchristos #include <err.h>
18ba9bdd8bSchristos #include <errno.h>
19ba9bdd8bSchristos #include <fcntl.h>
20ba9bdd8bSchristos #include <limits.h>
21ba9bdd8bSchristos #include <stdarg.h>
22ba9bdd8bSchristos #include <stdio.h>
23ba9bdd8bSchristos #include <stdlib.h>
24ba9bdd8bSchristos #include <string.h>
25ba9bdd8bSchristos #include <unistd.h>
26ba9bdd8bSchristos
27ba9bdd8bSchristos #define FUZZ_DEV_PREFIX "nodev"
28ba9bdd8bSchristos
29ba9bdd8bSchristos static int fd_fuzz = -1;
30ba9bdd8bSchristos static int (*open_f)(const char *, int, mode_t);
31ba9bdd8bSchristos static int (*close_f)(int);
32ba9bdd8bSchristos static ssize_t (*write_f)(int, const void *, size_t);
33ba9bdd8bSchristos
34ba9bdd8bSchristos int
open(const char * path,int flags,...)35ba9bdd8bSchristos open(const char *path, int flags, ...)
36ba9bdd8bSchristos {
37ba9bdd8bSchristos va_list ap;
38ba9bdd8bSchristos mode_t mode;
39ba9bdd8bSchristos
40ba9bdd8bSchristos va_start(ap, flags);
41ba9bdd8bSchristos mode = va_arg(ap, mode_t);
42ba9bdd8bSchristos va_end(ap);
43ba9bdd8bSchristos
44ba9bdd8bSchristos if (open_f == NULL) {
45ba9bdd8bSchristos open_f = dlsym(RTLD_NEXT, "open");
46ba9bdd8bSchristos if (open_f == NULL) {
47ba9bdd8bSchristos warnx("%s: dlsym", __func__);
48ba9bdd8bSchristos errno = EACCES;
49ba9bdd8bSchristos return (-1);
50ba9bdd8bSchristos }
51ba9bdd8bSchristos }
52ba9bdd8bSchristos
53ba9bdd8bSchristos if (strncmp(path, FUZZ_DEV_PREFIX, strlen(FUZZ_DEV_PREFIX)) != 0)
54ba9bdd8bSchristos return (open_f(path, flags, mode));
55ba9bdd8bSchristos
56ba9bdd8bSchristos if (fd_fuzz != -1) {
57ba9bdd8bSchristos warnx("%s: fd_fuzz != -1", __func__);
58ba9bdd8bSchristos errno = EACCES;
59ba9bdd8bSchristos return (-1);
60ba9bdd8bSchristos }
61ba9bdd8bSchristos
62ba9bdd8bSchristos if ((fd_fuzz = dup(STDIN_FILENO)) < 0) {
63ba9bdd8bSchristos warn("%s: dup", __func__);
64ba9bdd8bSchristos errno = EACCES;
65ba9bdd8bSchristos return (-1);
66ba9bdd8bSchristos }
67ba9bdd8bSchristos
68ba9bdd8bSchristos return (fd_fuzz);
69ba9bdd8bSchristos }
70ba9bdd8bSchristos
71ba9bdd8bSchristos int
close(int fd)72ba9bdd8bSchristos close(int fd)
73ba9bdd8bSchristos {
74ba9bdd8bSchristos if (close_f == NULL) {
75ba9bdd8bSchristos close_f = dlsym(RTLD_NEXT, "close");
76ba9bdd8bSchristos if (close_f == NULL) {
77ba9bdd8bSchristos warnx("%s: dlsym", __func__);
78ba9bdd8bSchristos errno = EACCES;
79ba9bdd8bSchristos return (-1);
80ba9bdd8bSchristos }
81ba9bdd8bSchristos }
82ba9bdd8bSchristos
83ba9bdd8bSchristos if (fd == fd_fuzz)
84ba9bdd8bSchristos fd_fuzz = -1;
85ba9bdd8bSchristos
86ba9bdd8bSchristos return (close_f(fd));
87ba9bdd8bSchristos }
88ba9bdd8bSchristos
89ba9bdd8bSchristos ssize_t
write(int fd,const void * buf,size_t nbytes)90ba9bdd8bSchristos write(int fd, const void *buf, size_t nbytes)
91ba9bdd8bSchristos {
92ba9bdd8bSchristos if (write_f == NULL) {
93ba9bdd8bSchristos write_f = dlsym(RTLD_NEXT, "write");
94ba9bdd8bSchristos if (write_f == NULL) {
95ba9bdd8bSchristos warnx("%s: dlsym", __func__);
96ba9bdd8bSchristos errno = EBADF;
97ba9bdd8bSchristos return (-1);
98ba9bdd8bSchristos }
99ba9bdd8bSchristos }
100ba9bdd8bSchristos
101ba9bdd8bSchristos if (fd != fd_fuzz)
102ba9bdd8bSchristos return (write_f(fd, buf, nbytes));
103ba9bdd8bSchristos
104ba9bdd8bSchristos return (nbytes);
105ba9bdd8bSchristos }
106