xref: /freebsd/contrib/libfido2/fuzz/preload-snoop.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-snoop.so preload-snoop.c
100afa8e06SEd Maste  * LD_PRELOAD=$(realpath preload-snoop.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 SNOOP_DEV_PREFIX	"/dev/hidraw"
280afa8e06SEd Maste 
290afa8e06SEd Maste struct fd_tuple {
300afa8e06SEd Maste 	int snoop_in;
310afa8e06SEd Maste 	int snoop_out;
320afa8e06SEd Maste 	int real_dev;
330afa8e06SEd Maste };
340afa8e06SEd Maste 
350afa8e06SEd Maste static struct fd_tuple  *fd_tuple;
360afa8e06SEd Maste static int              (*open_f)(const char *, int, mode_t);
370afa8e06SEd Maste static int              (*close_f)(int);
380afa8e06SEd Maste static ssize_t          (*read_f)(int, void *, size_t);
390afa8e06SEd Maste static ssize_t          (*write_f)(int, const void *, size_t);
400afa8e06SEd Maste 
410afa8e06SEd Maste static int
get_fd(const char * hid_path,const char * suffix)420afa8e06SEd Maste get_fd(const char *hid_path, const char *suffix)
430afa8e06SEd Maste {
440afa8e06SEd Maste 	char	*s = NULL;
450afa8e06SEd Maste 	char	 path[PATH_MAX];
460afa8e06SEd Maste 	int	 fd;
470afa8e06SEd Maste 	int	 r;
480afa8e06SEd Maste 
490afa8e06SEd Maste 	if ((s = strdup(hid_path)) == NULL) {
500afa8e06SEd Maste 		warnx("%s: strdup", __func__);
510afa8e06SEd Maste 		return (-1);
520afa8e06SEd Maste 	}
530afa8e06SEd Maste 
540afa8e06SEd Maste 	for (size_t i = 0; i < strlen(s); i++)
550afa8e06SEd Maste 		if (s[i] == '/')
560afa8e06SEd Maste 			s[i] = '_';
570afa8e06SEd Maste 
580afa8e06SEd Maste 	if ((r = snprintf(path, sizeof(path), "%s-%s", s, suffix)) < 0 ||
590afa8e06SEd Maste 	    (size_t)r >= sizeof(path)) {
600afa8e06SEd Maste 		warnx("%s: snprintf", __func__);
610afa8e06SEd Maste 		free(s);
620afa8e06SEd Maste 		return (-1);
630afa8e06SEd Maste 	}
640afa8e06SEd Maste 
650afa8e06SEd Maste 	free(s);
660afa8e06SEd Maste 	s = NULL;
670afa8e06SEd Maste 
680afa8e06SEd Maste 	if ((fd = open_f(path, O_CREAT | O_WRONLY, 0644)) < 0) {
690afa8e06SEd Maste 		warn("%s: open", __func__);
700afa8e06SEd Maste 		return (-1);
710afa8e06SEd Maste 	}
720afa8e06SEd Maste 
730afa8e06SEd Maste 	return (fd);
740afa8e06SEd Maste }
750afa8e06SEd Maste 
760afa8e06SEd Maste int
open(const char * path,int flags,...)770afa8e06SEd Maste open(const char *path, int flags, ...)
780afa8e06SEd Maste {
790afa8e06SEd Maste 	va_list	ap;
800afa8e06SEd Maste 	mode_t	mode;
810afa8e06SEd Maste 
820afa8e06SEd Maste 	va_start(ap, flags);
830afa8e06SEd Maste 	mode = va_arg(ap, mode_t);
840afa8e06SEd Maste 	va_end(ap);
850afa8e06SEd Maste 
860afa8e06SEd Maste 	if (open_f == NULL) {
870afa8e06SEd Maste 		open_f = dlsym(RTLD_NEXT, "open");
880afa8e06SEd Maste 		if (open_f == NULL) {
890afa8e06SEd Maste 			warnx("%s: dlsym", __func__);
900afa8e06SEd Maste 			errno = EACCES;
910afa8e06SEd Maste 			return (-1);
920afa8e06SEd Maste 		}
930afa8e06SEd Maste 	}
940afa8e06SEd Maste 
950afa8e06SEd Maste 	if (strncmp(path, SNOOP_DEV_PREFIX, strlen(SNOOP_DEV_PREFIX)) != 0)
960afa8e06SEd Maste 		return (open_f(path, flags, mode));
970afa8e06SEd Maste 
980afa8e06SEd Maste 	if (fd_tuple != NULL) {
990afa8e06SEd Maste 		warnx("%s: fd_tuple != NULL", __func__);
1000afa8e06SEd Maste 		errno = EACCES;
1010afa8e06SEd Maste 		return (-1);
1020afa8e06SEd Maste 	}
1030afa8e06SEd Maste 
1040afa8e06SEd Maste 	if ((fd_tuple = calloc(1, sizeof(*fd_tuple))) == NULL) {
1050afa8e06SEd Maste 		warn("%s: calloc", __func__);
1060afa8e06SEd Maste 		errno = ENOMEM;
1070afa8e06SEd Maste 		return (-1);
1080afa8e06SEd Maste 	}
1090afa8e06SEd Maste 
1100afa8e06SEd Maste 	fd_tuple->snoop_in = -1;
1110afa8e06SEd Maste 	fd_tuple->snoop_out = -1;
1120afa8e06SEd Maste 	fd_tuple->real_dev = -1;
1130afa8e06SEd Maste 
1140afa8e06SEd Maste 	if ((fd_tuple->snoop_in = get_fd(path, "in")) < 0 ||
1150afa8e06SEd Maste 	    (fd_tuple->snoop_out = get_fd(path, "out")) < 0 ||
1160afa8e06SEd Maste 	    (fd_tuple->real_dev = open_f(path, flags, mode)) < 0) {
1170afa8e06SEd Maste 		warn("%s: get_fd/open", __func__);
1180afa8e06SEd Maste 		goto fail;
1190afa8e06SEd Maste 	}
1200afa8e06SEd Maste 
1210afa8e06SEd Maste 	return (fd_tuple->real_dev);
1220afa8e06SEd Maste fail:
1230afa8e06SEd Maste 	if (fd_tuple->snoop_in != -1)
1240afa8e06SEd Maste 		close(fd_tuple->snoop_in);
1250afa8e06SEd Maste 	if (fd_tuple->snoop_out != -1)
1260afa8e06SEd Maste 		close(fd_tuple->snoop_out);
1270afa8e06SEd Maste 	if (fd_tuple->real_dev != -1)
1280afa8e06SEd Maste 		close(fd_tuple->real_dev);
1290afa8e06SEd Maste 
1300afa8e06SEd Maste 	free(fd_tuple);
1310afa8e06SEd Maste 	fd_tuple = NULL;
1320afa8e06SEd Maste 
1330afa8e06SEd Maste 	errno = EACCES;
1340afa8e06SEd Maste 
1350afa8e06SEd Maste 	return (-1);
1360afa8e06SEd Maste }
1370afa8e06SEd Maste 
1380afa8e06SEd Maste int
close(int fd)1390afa8e06SEd Maste close(int fd)
1400afa8e06SEd Maste {
1410afa8e06SEd Maste 	if (close_f == NULL) {
1420afa8e06SEd Maste 		close_f = dlsym(RTLD_NEXT, "close");
1430afa8e06SEd Maste 		if (close_f == NULL) {
1440afa8e06SEd Maste 			warnx("%s: dlsym", __func__);
1450afa8e06SEd Maste 			errno = EBADF;
1460afa8e06SEd Maste 			return (-1);
1470afa8e06SEd Maste 		}
1480afa8e06SEd Maste 	}
1490afa8e06SEd Maste 
1500afa8e06SEd Maste 	if (fd_tuple == NULL || fd_tuple->real_dev != fd)
1510afa8e06SEd Maste 		return (close_f(fd));
1520afa8e06SEd Maste 
1530afa8e06SEd Maste 	close_f(fd_tuple->snoop_in);
1540afa8e06SEd Maste 	close_f(fd_tuple->snoop_out);
1550afa8e06SEd Maste 	close_f(fd_tuple->real_dev);
1560afa8e06SEd Maste 
1570afa8e06SEd Maste 	free(fd_tuple);
1580afa8e06SEd Maste 	fd_tuple = NULL;
1590afa8e06SEd Maste 
1600afa8e06SEd Maste 	return (0);
1610afa8e06SEd Maste }
1620afa8e06SEd Maste 
1630afa8e06SEd Maste ssize_t
read(int fd,void * buf,size_t nbytes)1640afa8e06SEd Maste read(int fd, void *buf, size_t nbytes)
1650afa8e06SEd Maste {
1660afa8e06SEd Maste 	ssize_t n;
1670afa8e06SEd Maste 
1680afa8e06SEd Maste 	if (read_f == NULL) {
1690afa8e06SEd Maste 		read_f = dlsym(RTLD_NEXT, "read");
1700afa8e06SEd Maste 		if (read_f == NULL) {
1710afa8e06SEd Maste 			warnx("%s: dlsym", __func__);
1720afa8e06SEd Maste 			errno = EBADF;
1730afa8e06SEd Maste 			return (-1);
1740afa8e06SEd Maste 		}
1750afa8e06SEd Maste 	}
1760afa8e06SEd Maste 
1770afa8e06SEd Maste 	if (write_f == NULL) {
1780afa8e06SEd Maste 		write_f = dlsym(RTLD_NEXT, "write");
1790afa8e06SEd Maste 		if (write_f == NULL) {
1800afa8e06SEd Maste 			warnx("%s: dlsym", __func__);
1810afa8e06SEd Maste 			errno = EBADF;
1820afa8e06SEd Maste 			return (-1);
1830afa8e06SEd Maste 		}
1840afa8e06SEd Maste 	}
1850afa8e06SEd Maste 
1860afa8e06SEd Maste 	if (fd_tuple == NULL || fd_tuple->real_dev != fd)
1870afa8e06SEd Maste 		return (read_f(fd, buf, nbytes));
1880afa8e06SEd Maste 
1890afa8e06SEd Maste 	if ((n = read_f(fd, buf, nbytes)) < 0 ||
1900afa8e06SEd Maste 	    write_f(fd_tuple->snoop_in, buf, n) != n)
1910afa8e06SEd Maste 		return (-1);
1920afa8e06SEd Maste 
1930afa8e06SEd Maste 	return (n);
1940afa8e06SEd Maste }
1950afa8e06SEd Maste 
1960afa8e06SEd Maste ssize_t
write(int fd,const void * buf,size_t nbytes)1970afa8e06SEd Maste write(int fd, const void *buf, size_t nbytes)
1980afa8e06SEd Maste {
1990afa8e06SEd Maste 	ssize_t n;
2000afa8e06SEd Maste 
2010afa8e06SEd Maste 	if (write_f == NULL) {
2020afa8e06SEd Maste 		write_f = dlsym(RTLD_NEXT, "write");
2030afa8e06SEd Maste 		if (write_f == NULL) {
2040afa8e06SEd Maste 			warnx("%s: dlsym", __func__);
2050afa8e06SEd Maste 			errno = EBADF;
2060afa8e06SEd Maste 			return (-1);
2070afa8e06SEd Maste 		}
2080afa8e06SEd Maste 	}
2090afa8e06SEd Maste 
2100afa8e06SEd Maste 	if (fd_tuple == NULL || fd_tuple->real_dev != fd)
2110afa8e06SEd Maste 		return (write_f(fd, buf, nbytes));
2120afa8e06SEd Maste 
2130afa8e06SEd Maste 	if ((n = write_f(fd, buf, nbytes)) < 0 ||
2140afa8e06SEd Maste 	    write_f(fd_tuple->snoop_out, buf, n) != n)
2150afa8e06SEd Maste 		return (-1);
2160afa8e06SEd Maste 
2170afa8e06SEd Maste 	return (n);
2180afa8e06SEd Maste }
219