10afa8e06SEd Maste /*
20afa8e06SEd Maste * Copyright (c) 2019 Yubico AB. All rights reserved.
30afa8e06SEd Maste * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste */
70afa8e06SEd Maste
80afa8e06SEd Maste /*
90afa8e06SEd Maste * cc -fPIC -D_GNU_SOURCE -shared -o preload-fuzz.so preload-fuzz.c
100afa8e06SEd Maste * LD_PRELOAD=$(realpath preload-fuzz.so)
110afa8e06SEd Maste */
120afa8e06SEd Maste
130afa8e06SEd Maste #include <sys/types.h>
140afa8e06SEd Maste #include <sys/stat.h>
150afa8e06SEd Maste
160afa8e06SEd Maste #include <dlfcn.h>
170afa8e06SEd Maste #include <err.h>
180afa8e06SEd Maste #include <errno.h>
190afa8e06SEd Maste #include <fcntl.h>
200afa8e06SEd Maste #include <limits.h>
210afa8e06SEd Maste #include <stdarg.h>
220afa8e06SEd Maste #include <stdio.h>
230afa8e06SEd Maste #include <stdlib.h>
240afa8e06SEd Maste #include <string.h>
250afa8e06SEd Maste #include <unistd.h>
260afa8e06SEd Maste
270afa8e06SEd Maste #define FUZZ_DEV_PREFIX "nodev"
280afa8e06SEd Maste
290afa8e06SEd Maste static int fd_fuzz = -1;
300afa8e06SEd Maste static int (*open_f)(const char *, int, mode_t);
310afa8e06SEd Maste static int (*close_f)(int);
320afa8e06SEd Maste static ssize_t (*write_f)(int, const void *, size_t);
330afa8e06SEd Maste
340afa8e06SEd Maste int
open(const char * path,int flags,...)350afa8e06SEd Maste open(const char *path, int flags, ...)
360afa8e06SEd Maste {
370afa8e06SEd Maste va_list ap;
380afa8e06SEd Maste mode_t mode;
390afa8e06SEd Maste
400afa8e06SEd Maste va_start(ap, flags);
410afa8e06SEd Maste mode = va_arg(ap, mode_t);
420afa8e06SEd Maste va_end(ap);
430afa8e06SEd Maste
440afa8e06SEd Maste if (open_f == NULL) {
450afa8e06SEd Maste open_f = dlsym(RTLD_NEXT, "open");
460afa8e06SEd Maste if (open_f == NULL) {
470afa8e06SEd Maste warnx("%s: dlsym", __func__);
480afa8e06SEd Maste errno = EACCES;
490afa8e06SEd Maste return (-1);
500afa8e06SEd Maste }
510afa8e06SEd Maste }
520afa8e06SEd Maste
530afa8e06SEd Maste if (strncmp(path, FUZZ_DEV_PREFIX, strlen(FUZZ_DEV_PREFIX)) != 0)
540afa8e06SEd Maste return (open_f(path, flags, mode));
550afa8e06SEd Maste
560afa8e06SEd Maste if (fd_fuzz != -1) {
570afa8e06SEd Maste warnx("%s: fd_fuzz != -1", __func__);
580afa8e06SEd Maste errno = EACCES;
590afa8e06SEd Maste return (-1);
600afa8e06SEd Maste }
610afa8e06SEd Maste
620afa8e06SEd Maste if ((fd_fuzz = dup(STDIN_FILENO)) < 0) {
630afa8e06SEd Maste warn("%s: dup", __func__);
640afa8e06SEd Maste errno = EACCES;
650afa8e06SEd Maste return (-1);
660afa8e06SEd Maste }
670afa8e06SEd Maste
680afa8e06SEd Maste return (fd_fuzz);
690afa8e06SEd Maste }
700afa8e06SEd Maste
710afa8e06SEd Maste int
close(int fd)720afa8e06SEd Maste close(int fd)
730afa8e06SEd Maste {
740afa8e06SEd Maste if (close_f == NULL) {
750afa8e06SEd Maste close_f = dlsym(RTLD_NEXT, "close");
760afa8e06SEd Maste if (close_f == NULL) {
770afa8e06SEd Maste warnx("%s: dlsym", __func__);
780afa8e06SEd Maste errno = EACCES;
790afa8e06SEd Maste return (-1);
800afa8e06SEd Maste }
810afa8e06SEd Maste }
820afa8e06SEd Maste
830afa8e06SEd Maste if (fd == fd_fuzz)
840afa8e06SEd Maste fd_fuzz = -1;
850afa8e06SEd Maste
860afa8e06SEd Maste return (close_f(fd));
870afa8e06SEd Maste }
880afa8e06SEd Maste
890afa8e06SEd Maste ssize_t
write(int fd,const void * buf,size_t nbytes)900afa8e06SEd Maste write(int fd, const void *buf, size_t nbytes)
910afa8e06SEd Maste {
920afa8e06SEd Maste if (write_f == NULL) {
930afa8e06SEd Maste write_f = dlsym(RTLD_NEXT, "write");
940afa8e06SEd Maste if (write_f == NULL) {
950afa8e06SEd Maste warnx("%s: dlsym", __func__);
960afa8e06SEd Maste errno = EBADF;
970afa8e06SEd Maste return (-1);
980afa8e06SEd Maste }
990afa8e06SEd Maste }
1000afa8e06SEd Maste
1010afa8e06SEd Maste if (fd != fd_fuzz)
1020afa8e06SEd Maste return (write_f(fd, buf, nbytes));
1030afa8e06SEd Maste
1040afa8e06SEd Maste return (nbytes);
1050afa8e06SEd Maste }
106