xref: /freebsd/contrib/libfido2/fuzz/preload-fuzz.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
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