t_bpf.c revision 1.2.6.2 1 1.2.6.2 yamt /* $NetBSD: t_bpf.c,v 1.2.6.2 2012/10/30 19:00:05 yamt Exp $ */
2 1.1 pooka
3 1.1 pooka /*-
4 1.1 pooka * Copyright (c) 2010 Antti Kantee. All Rights Reserved.
5 1.1 pooka *
6 1.1 pooka * Redistribution and use in source and binary forms, with or without
7 1.1 pooka * modification, are permitted provided that the following conditions
8 1.1 pooka * are met:
9 1.1 pooka * 1. Redistributions of source code must retain the above copyright
10 1.1 pooka * notice, this list of conditions and the following disclaimer.
11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 pooka * notice, this list of conditions and the following disclaimer in the
13 1.1 pooka * documentation and/or other materials provided with the distribution.
14 1.1 pooka *
15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 pooka * SUCH DAMAGE.
26 1.1 pooka */
27 1.2.6.2 yamt #include <sys/cdefs.h>
28 1.2.6.2 yamt __RCSID("$NetBSD: t_bpf.c,v 1.2.6.2 2012/10/30 19:00:05 yamt Exp $");
29 1.1 pooka
30 1.1 pooka #include <sys/param.h>
31 1.1 pooka #include <sys/ioctl.h>
32 1.1 pooka #include <sys/socket.h>
33 1.1 pooka #include <sys/mbuf.h>
34 1.1 pooka #include <sys/sysctl.h>
35 1.2 christos #include <sys/mman.h>
36 1.2 christos #include <unistd.h>
37 1.1 pooka
38 1.1 pooka #include <net/if.h>
39 1.1 pooka #include <net/bpf.h>
40 1.1 pooka
41 1.1 pooka #include <fcntl.h>
42 1.1 pooka #include <stdio.h>
43 1.1 pooka #include <string.h>
44 1.1 pooka
45 1.1 pooka #include <rump/rump.h>
46 1.1 pooka #include <rump/rump_syscalls.h>
47 1.1 pooka
48 1.1 pooka /* XXX: atf-c.h has collisions with mbuf */
49 1.1 pooka #undef m_type
50 1.1 pooka #undef m_data
51 1.1 pooka #include <atf-c.h>
52 1.1 pooka
53 1.1 pooka #include "../../h_macros.h"
54 1.2 christos #include "../config/netconfig.c"
55 1.1 pooka
56 1.1 pooka ATF_TC(bpfwriteleak);
57 1.1 pooka ATF_TC_HEAD(bpfwriteleak, tc)
58 1.1 pooka {
59 1.1 pooka
60 1.1 pooka atf_tc_set_md_var(tc, "descr", "Checks that writing to /dev/bpf "
61 1.1 pooka "does not leak mbufs");
62 1.1 pooka }
63 1.1 pooka
64 1.1 pooka static int
65 1.1 pooka getmtdata(void)
66 1.1 pooka {
67 1.1 pooka struct mbstat mbstat;
68 1.1 pooka size_t mbstatlen = sizeof(mbstat);
69 1.1 pooka const int mbstat_mib[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
70 1.1 pooka
71 1.1 pooka RL(rump_sys___sysctl(mbstat_mib, __arraycount(mbstat_mib),
72 1.1 pooka &mbstat, &mbstatlen, NULL, 0));
73 1.1 pooka return mbstat.m_mtypes[MT_DATA];
74 1.1 pooka }
75 1.1 pooka
76 1.1 pooka ATF_TC_BODY(bpfwriteleak, tc)
77 1.1 pooka {
78 1.1 pooka char buf[28]; /* sizeof(garbage) > etherhdrlen */
79 1.1 pooka struct ifreq ifr;
80 1.1 pooka int ifnum, bpfd;
81 1.1 pooka
82 1.1 pooka RZ(rump_init());
83 1.1 pooka RZ(rump_pub_shmif_create(NULL, &ifnum));
84 1.1 pooka sprintf(ifr.ifr_name, "shmif%d", ifnum);
85 1.1 pooka
86 1.1 pooka RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
87 1.1 pooka RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
88 1.1 pooka RL(rump_sys_ioctl(bpfd, BIOCSFEEDBACK, &ifr));
89 1.1 pooka
90 1.1 pooka if (getmtdata() != 0)
91 1.1 pooka atf_tc_fail("test precondition failed: MT_DATA mbufs != 0");
92 1.1 pooka
93 1.1 pooka ATF_REQUIRE_ERRNO(ENETDOWN, rump_sys_write(bpfd, buf, sizeof(buf))==-1);
94 1.1 pooka
95 1.1 pooka ATF_REQUIRE_EQ(getmtdata(), 0);
96 1.1 pooka }
97 1.1 pooka
98 1.2 christos #if (SIZE_MAX > UINT_MAX)
99 1.2 christos ATF_TC(bpfwritetrunc);
100 1.2 christos ATF_TC_HEAD(bpfwritetrunc, tc)
101 1.2 christos {
102 1.2 christos atf_tc_set_md_var(tc, "descr", "Checks that write to /dev/bpf "
103 1.2 christos "does not truncate size_t to int");
104 1.2 christos }
105 1.2 christos
106 1.2 christos ATF_TC_BODY(bpfwritetrunc, tc)
107 1.2 christos {
108 1.2 christos int bpfd;
109 1.2 christos struct ifreq ifr;
110 1.2 christos struct iovec *iov;
111 1.2 christos size_t iovlen, sz;
112 1.2 christos const size_t extra_bytes = 28;
113 1.2 christos const size_t total = extra_bytes + UINT_MAX + 1;
114 1.2 christos long iov_max, vm_page_size; /* round_page wants vm_page_size variable */
115 1.2 christos
116 1.2 christos memset(&ifr, 0, sizeof(ifr));
117 1.2 christos
118 1.2 christos iov_max = sysconf(_SC_IOV_MAX);
119 1.2 christos vm_page_size = sysconf(_SC_PAGE_SIZE);
120 1.2 christos ATF_REQUIRE(iov_max > 1 && vm_page_size > 1);
121 1.2 christos
122 1.2.6.2 yamt /*
123 1.2.6.2 yamt * Minimize memory consumption by using many iovecs
124 1.2.6.2 yamt * all pointing to one memory region.
125 1.2.6.2 yamt */
126 1.2 christos iov = calloc(iov_max, sizeof(struct iovec));
127 1.2 christos ATF_REQUIRE(iov != NULL);
128 1.2 christos
129 1.2 christos sz = round_page((total + (iov_max - 1)) / iov_max);
130 1.2 christos
131 1.2 christos iov[0].iov_len = sz;
132 1.2 christos iov[0].iov_base = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
133 1.2 christos ATF_REQUIRE(iov[0].iov_base != MAP_FAILED);
134 1.2 christos
135 1.2 christos iovlen = 1;
136 1.2.6.2 yamt while (sz + iov[0].iov_len <= total)
137 1.2 christos {
138 1.2 christos iov[iovlen].iov_len = iov[0].iov_len;
139 1.2 christos iov[iovlen].iov_base = iov[0].iov_base;
140 1.2 christos sz += iov[0].iov_len;
141 1.2 christos iovlen++;
142 1.2 christos }
143 1.2 christos
144 1.2.6.2 yamt if (sz < total)
145 1.2 christos {
146 1.2 christos iov[iovlen].iov_len = total - sz;
147 1.2 christos iov[iovlen].iov_base = iov[0].iov_base;
148 1.2 christos iovlen++;
149 1.2 christos }
150 1.2 christos
151 1.2 christos /* Sanity checks */
152 1.2 christos ATF_REQUIRE(iovlen >= 1 && iovlen <= (size_t)iov_max);
153 1.2 christos ATF_REQUIRE_EQ(iov[iovlen-1].iov_len, total % iov[0].iov_len);
154 1.2 christos
155 1.2 christos RZ(rump_init());
156 1.2 christos netcfg_rump_makeshmif("bpfwritetrunc", ifr.ifr_name);
157 1.2 christos netcfg_rump_if(ifr.ifr_name, "10.1.1.1", "255.0.0.0");
158 1.2 christos
159 1.2 christos RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
160 1.2 christos RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
161 1.2 christos
162 1.2 christos ATF_CHECK_ERRNO(EMSGSIZE, rump_sys_writev(bpfd, iov, iovlen) == -1);
163 1.2 christos
164 1.2 christos munmap(iov[0].iov_base, iov[0].iov_len);
165 1.2 christos free(iov);
166 1.2 christos }
167 1.2 christos #endif /* #if (SIZE_MAX > UINT_MAX) */
168 1.2 christos
169 1.1 pooka ATF_TP_ADD_TCS(tp)
170 1.1 pooka {
171 1.1 pooka
172 1.1 pooka ATF_TP_ADD_TC(tp, bpfwriteleak);
173 1.2 christos #if (SIZE_MAX > UINT_MAX)
174 1.2 christos ATF_TP_ADD_TC(tp, bpfwritetrunc);
175 1.2 christos #endif
176 1.1 pooka return atf_no_error();
177 1.1 pooka }
178