xref: /netbsd-src/external/bsd/libfido2/dist/fuzz/preload-fuzz.c (revision 2d40c4512a84c0d064ec30a492c5e2a14d230bc3)
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