1/*	$OpenBSD: copy.c,v 1.7 2023/07/06 07:47:04 deraadt Exp $	*/
2
3/* Written by Ted Unangst 2004 Public Domain */
4
5#include <sys/types.h>
6#include <sys/mount.h>
7#include <sys/sysctl.h>
8#include <sys/socket.h>
9#include <sys/ioctl.h>
10#include <sys/syslimits.h>
11#include <net/if.h>
12#include <string.h>
13#include <errno.h>
14
15#include <stdio.h>
16#include <err.h>
17#include <unistd.h>
18
19int failure;
20
21static void
22fail(const char *str)
23{
24	fprintf(stderr, "%s\n", str);
25	failure++;
26}
27
28int
29main(int argc, char **argv)
30{
31 	char buf[4096];
32	char path[PATH_MAX + 1];
33 	void *goodbuf;
34 	void *badbuf;
35 	int mib[6];
36 	struct kinfo_proc kinfo;
37 	size_t kinfosize = sizeof(kinfo);
38 	int s, i;
39 	struct ifreq ifrdesc;
40
41
42 	s = socket(AF_INET, SOCK_DGRAM, 0);
43 	if (s == -1)
44 		err(1, "socket");
45
46 	mib[0] = CTL_KERN;
47 	mib[1] = KERN_PROC;
48 	mib[2] = KERN_PROC_PID;
49 	mib[3] = getpid();
50 	mib[4] = sizeof(struct kinfo_proc);
51 	mib[5] = 1;
52
53 	if (sysctl(mib, 6, &kinfo, &kinfosize, 0, 0))
54 		err(1, "sysctl");
55
56	for (i = 0; i < PATH_MAX; i++)
57		path[i] = (i % NAME_MAX) ? 'a' : '/';
58	path[PATH_MAX] = '\0';
59
60 	goodbuf = buf;
61 	badbuf = (void*)(long)kinfo.p_paddr;
62
63 	/* printf("goodbuf %p badbuf %p\n", goodbuf, badbuf); */
64
65 	/* copyin */
66 	if (!sysctl(0, 6, &kinfo, &kinfosize, 0, 0))
67 		fail("copyin did not fail on 0 buf\n");
68 	if (!sysctl(badbuf, 6, &kinfo, &kinfosize, 0, 0))
69 		fail("copyin did not fail on bad buf\n");
70
71 	/* copyout */
72 	if (statfs("/", goodbuf))
73 		fail("copyout failed on a good buf\n");
74 	if (!statfs("/", 0) || errno != EFAULT)
75 		fail("copyout didn't fail on 0 buf\n");
76 	if (!statfs("/", badbuf) || errno != EFAULT)
77 		fail("copyout didn't fail on bad buf\n");
78
79 	/* copyoutstr */
80 	memset(&ifrdesc, 0, sizeof(ifrdesc));
81 	strlcpy(ifrdesc.ifr_name, "lo0", sizeof(ifrdesc.ifr_name));
82 	ifrdesc.ifr_data = goodbuf;
83 	if (ioctl(s, SIOCGIFDESCR, &ifrdesc))
84 		fail("SIOCIFDESCR ioctl failed\n");
85 	memset(&ifrdesc, 0, sizeof(ifrdesc));
86 	strlcpy(ifrdesc.ifr_name, "lo0", sizeof(ifrdesc.ifr_name));
87 	ifrdesc.ifr_data = 0;
88 	if (!ioctl(s, SIOCGIFDESCR, &ifrdesc))
89 		fail("copyoutstr didn't fail on 0 buf\n");
90 	memset(&ifrdesc, 0, sizeof(ifrdesc));
91 	strlcpy(ifrdesc.ifr_name, "lo0", sizeof(ifrdesc.ifr_name));
92 	ifrdesc.ifr_data = badbuf;
93 	if (!ioctl(s, SIOCGIFDESCR, &ifrdesc))
94 		fail("copyoutstr didn't fail on badbuf\n");
95
96 	/* copyinstr */
97 	if (statfs("/", goodbuf))
98 		fail("copyinstr failed on a good buf\n");
99 	if (!statfs(0, goodbuf) || errno != EFAULT)
100 		fail("copyinstr didn't fail on 0 buf\n");
101 	if (!statfs(badbuf, goodbuf) || errno != EFAULT)
102 		fail("copyinstr didn't fail on bad buf\n");
103	if (!statfs(path, goodbuf) || errno != ENAMETOOLONG)
104		fail("copyinstr didn't fail on long string\n");
105
106	if (failure)
107		errx(1, "%d failures", failure);
108 	return 0;
109}
110