t_bpf.c revision 1.4 1 1.4 christos /* $NetBSD: t_bpf.c,v 1.4 2012/01/13 16:28:44 christos 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.1 pooka
28 1.1 pooka #include <sys/param.h>
29 1.1 pooka #include <sys/ioctl.h>
30 1.1 pooka #include <sys/socket.h>
31 1.1 pooka #include <sys/mbuf.h>
32 1.1 pooka #include <sys/sysctl.h>
33 1.2 christos #include <sys/mman.h>
34 1.2 christos #include <unistd.h>
35 1.1 pooka
36 1.1 pooka #include <net/if.h>
37 1.1 pooka #include <net/bpf.h>
38 1.1 pooka
39 1.1 pooka #include <fcntl.h>
40 1.1 pooka #include <stdio.h>
41 1.1 pooka #include <string.h>
42 1.1 pooka
43 1.1 pooka #include <rump/rump.h>
44 1.1 pooka #include <rump/rump_syscalls.h>
45 1.1 pooka
46 1.1 pooka /* XXX: atf-c.h has collisions with mbuf */
47 1.1 pooka #undef m_type
48 1.1 pooka #undef m_data
49 1.1 pooka #include <atf-c.h>
50 1.1 pooka
51 1.1 pooka #include "../../h_macros.h"
52 1.2 christos #include "../config/netconfig.c"
53 1.1 pooka
54 1.1 pooka ATF_TC(bpfwriteleak);
55 1.1 pooka ATF_TC_HEAD(bpfwriteleak, tc)
56 1.1 pooka {
57 1.1 pooka
58 1.1 pooka atf_tc_set_md_var(tc, "descr", "Checks that writing to /dev/bpf "
59 1.1 pooka "does not leak mbufs");
60 1.1 pooka }
61 1.1 pooka
62 1.1 pooka static int
63 1.1 pooka getmtdata(void)
64 1.1 pooka {
65 1.1 pooka struct mbstat mbstat;
66 1.1 pooka size_t mbstatlen = sizeof(mbstat);
67 1.1 pooka const int mbstat_mib[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
68 1.1 pooka
69 1.1 pooka RL(rump_sys___sysctl(mbstat_mib, __arraycount(mbstat_mib),
70 1.1 pooka &mbstat, &mbstatlen, NULL, 0));
71 1.1 pooka return mbstat.m_mtypes[MT_DATA];
72 1.1 pooka }
73 1.1 pooka
74 1.1 pooka ATF_TC_BODY(bpfwriteleak, tc)
75 1.1 pooka {
76 1.1 pooka char buf[28]; /* sizeof(garbage) > etherhdrlen */
77 1.1 pooka struct ifreq ifr;
78 1.1 pooka int ifnum, bpfd;
79 1.1 pooka
80 1.1 pooka RZ(rump_init());
81 1.1 pooka RZ(rump_pub_shmif_create(NULL, &ifnum));
82 1.1 pooka sprintf(ifr.ifr_name, "shmif%d", ifnum);
83 1.1 pooka
84 1.1 pooka RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
85 1.1 pooka RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
86 1.1 pooka RL(rump_sys_ioctl(bpfd, BIOCSFEEDBACK, &ifr));
87 1.1 pooka
88 1.1 pooka if (getmtdata() != 0)
89 1.1 pooka atf_tc_fail("test precondition failed: MT_DATA mbufs != 0");
90 1.1 pooka
91 1.1 pooka ATF_REQUIRE_ERRNO(ENETDOWN, rump_sys_write(bpfd, buf, sizeof(buf))==-1);
92 1.1 pooka
93 1.1 pooka ATF_REQUIRE_EQ(getmtdata(), 0);
94 1.1 pooka }
95 1.1 pooka
96 1.2 christos #if (SIZE_MAX > UINT_MAX)
97 1.2 christos ATF_TC(bpfwritetrunc);
98 1.2 christos ATF_TC_HEAD(bpfwritetrunc, tc)
99 1.2 christos {
100 1.2 christos atf_tc_set_md_var(tc, "descr", "Checks that write to /dev/bpf "
101 1.2 christos "does not truncate size_t to int");
102 1.2 christos }
103 1.2 christos
104 1.2 christos ATF_TC_BODY(bpfwritetrunc, tc)
105 1.2 christos {
106 1.2 christos int bpfd;
107 1.2 christos struct ifreq ifr;
108 1.2 christos struct iovec *iov;
109 1.2 christos size_t iovlen, sz;
110 1.2 christos const size_t extra_bytes = 28;
111 1.2 christos const size_t total = extra_bytes + UINT_MAX + 1;
112 1.2 christos long iov_max, vm_page_size; /* round_page wants vm_page_size variable */
113 1.2 christos
114 1.2 christos memset(&ifr, 0, sizeof(ifr));
115 1.2 christos
116 1.2 christos iov_max = sysconf(_SC_IOV_MAX);
117 1.2 christos vm_page_size = sysconf(_SC_PAGE_SIZE);
118 1.2 christos ATF_REQUIRE(iov_max > 1 && vm_page_size > 1);
119 1.2 christos
120 1.2 christos /* Minimize memory consumption by using many iovecs
121 1.2 christos * all pointing to one memory region */
122 1.2 christos iov = calloc(iov_max, sizeof(struct iovec));
123 1.2 christos ATF_REQUIRE(iov != NULL);
124 1.2 christos
125 1.2 christos sz = round_page((total + (iov_max - 1)) / iov_max);
126 1.2 christos
127 1.2 christos iov[0].iov_len = sz;
128 1.2 christos iov[0].iov_base = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0);
129 1.2 christos ATF_REQUIRE(iov[0].iov_base != MAP_FAILED);
130 1.2 christos
131 1.2 christos iovlen = 1;
132 1.2 christos while(sz + iov[0].iov_len <= total)
133 1.2 christos {
134 1.2 christos iov[iovlen].iov_len = iov[0].iov_len;
135 1.2 christos iov[iovlen].iov_base = iov[0].iov_base;
136 1.2 christos sz += iov[0].iov_len;
137 1.2 christos iovlen++;
138 1.2 christos }
139 1.2 christos
140 1.2 christos if(sz < total)
141 1.2 christos {
142 1.2 christos iov[iovlen].iov_len = total - sz;
143 1.2 christos iov[iovlen].iov_base = iov[0].iov_base;
144 1.2 christos iovlen++;
145 1.2 christos }
146 1.2 christos
147 1.2 christos /* Sanity checks */
148 1.2 christos ATF_REQUIRE(iovlen >= 1 && iovlen <= (size_t)iov_max);
149 1.2 christos ATF_REQUIRE_EQ(iov[iovlen-1].iov_len, total % iov[0].iov_len);
150 1.2 christos
151 1.2 christos RZ(rump_init());
152 1.2 christos netcfg_rump_makeshmif("bpfwritetrunc", ifr.ifr_name);
153 1.2 christos netcfg_rump_if(ifr.ifr_name, "10.1.1.1", "255.0.0.0");
154 1.2 christos
155 1.2 christos RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR));
156 1.2 christos RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr));
157 1.2 christos
158 1.2 christos ATF_CHECK_ERRNO(EMSGSIZE, rump_sys_writev(bpfd, iov, iovlen) == -1);
159 1.2 christos
160 1.2 christos munmap(iov[0].iov_base, iov[0].iov_len);
161 1.2 christos free(iov);
162 1.2 christos }
163 1.2 christos #endif /* #if (SIZE_MAX > UINT_MAX) */
164 1.2 christos
165 1.1 pooka ATF_TP_ADD_TCS(tp)
166 1.1 pooka {
167 1.1 pooka
168 1.1 pooka ATF_TP_ADD_TC(tp, bpfwriteleak);
169 1.2 christos #if (SIZE_MAX > UINT_MAX)
170 1.2 christos ATF_TP_ADD_TC(tp, bpfwritetrunc);
171 1.2 christos #endif
172 1.1 pooka return atf_no_error();
173 1.1 pooka }
174