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