1314818Sngie/* $NetBSD: t_bpf.c,v 1.7 2017/02/01 08:04:49 ozaki-r Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 Antti Kantee. All Rights Reserved. 5272343Sngie * 6272343Sngie * Redistribution and use in source and binary forms, with or without 7272343Sngie * modification, are permitted provided that the following conditions 8272343Sngie * are met: 9272343Sngie * 1. Redistributions of source code must retain the above copyright 10272343Sngie * notice, this list of conditions and the following disclaimer. 11272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 12272343Sngie * notice, this list of conditions and the following disclaimer in the 13272343Sngie * documentation and/or other materials provided with the distribution. 14272343Sngie * 15272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16272343Sngie * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17272343Sngie * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18272343Sngie * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21272343Sngie * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25272343Sngie * SUCH DAMAGE. 26272343Sngie */ 27272343Sngie#include <sys/cdefs.h> 28314818Sngie__RCSID("$NetBSD: t_bpf.c,v 1.7 2017/02/01 08:04:49 ozaki-r Exp $"); 29272343Sngie 30272343Sngie#include <sys/param.h> 31272343Sngie#include <sys/ioctl.h> 32272343Sngie#include <sys/socket.h> 33272343Sngie#include <sys/mbuf.h> 34272343Sngie#include <sys/sysctl.h> 35272343Sngie#include <sys/mman.h> 36272343Sngie#include <unistd.h> 37272343Sngie 38272343Sngie#include <net/if.h> 39272343Sngie#include <net/bpf.h> 40272343Sngie 41272343Sngie#include <fcntl.h> 42272343Sngie#include <stdio.h> 43272343Sngie#include <string.h> 44272343Sngie 45272343Sngie#include <rump/rump.h> 46272343Sngie#include <rump/rump_syscalls.h> 47272343Sngie 48272343Sngie/* XXX: atf-c.h has collisions with mbuf */ 49272343Sngie#undef m_type 50272343Sngie#undef m_data 51272343Sngie#include <atf-c.h> 52272343Sngie 53314818Sngie#include "h_macros.h" 54272343Sngie#include "../config/netconfig.c" 55272343Sngie 56272343SngieATF_TC(bpfwriteleak); 57272343SngieATF_TC_HEAD(bpfwriteleak, tc) 58272343Sngie{ 59272343Sngie 60272343Sngie atf_tc_set_md_var(tc, "descr", "Checks that writing to /dev/bpf " 61272343Sngie "does not leak mbufs"); 62272343Sngie} 63272343Sngie 64272343Sngiestatic int 65272343Sngiegetmtdata(void) 66272343Sngie{ 67272343Sngie struct mbstat mbstat; 68272343Sngie size_t mbstatlen = sizeof(mbstat); 69272343Sngie const int mbstat_mib[] = { CTL_KERN, KERN_MBUF, MBUF_STATS }; 70272343Sngie 71272343Sngie RL(rump_sys___sysctl(mbstat_mib, __arraycount(mbstat_mib), 72272343Sngie &mbstat, &mbstatlen, NULL, 0)); 73272343Sngie return mbstat.m_mtypes[MT_DATA]; 74272343Sngie} 75272343Sngie 76272343SngieATF_TC_BODY(bpfwriteleak, tc) 77272343Sngie{ 78272343Sngie char buf[28]; /* sizeof(garbage) > etherhdrlen */ 79272343Sngie struct ifreq ifr; 80272343Sngie int ifnum, bpfd; 81272343Sngie 82272343Sngie RZ(rump_init()); 83272343Sngie RZ(rump_pub_shmif_create(NULL, &ifnum)); 84272343Sngie sprintf(ifr.ifr_name, "shmif%d", ifnum); 85272343Sngie 86272343Sngie RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR)); 87272343Sngie RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr)); 88272343Sngie RL(rump_sys_ioctl(bpfd, BIOCSFEEDBACK, &ifr)); 89272343Sngie 90272343Sngie if (getmtdata() != 0) 91272343Sngie atf_tc_fail("test precondition failed: MT_DATA mbufs != 0"); 92272343Sngie 93272343Sngie ATF_REQUIRE_ERRNO(ENETDOWN, rump_sys_write(bpfd, buf, sizeof(buf))==-1); 94272343Sngie 95272343Sngie ATF_REQUIRE_EQ(getmtdata(), 0); 96272343Sngie} 97272343Sngie 98272343Sngie#if (SIZE_MAX > UINT_MAX) 99272343SngieATF_TC(bpfwritetrunc); 100272343SngieATF_TC_HEAD(bpfwritetrunc, tc) 101272343Sngie{ 102272343Sngie atf_tc_set_md_var(tc, "descr", "Checks that write to /dev/bpf " 103272343Sngie "does not truncate size_t to int"); 104272343Sngie} 105272343Sngie 106272343SngieATF_TC_BODY(bpfwritetrunc, tc) 107272343Sngie{ 108272343Sngie int bpfd; 109272343Sngie struct ifreq ifr; 110272343Sngie struct iovec *iov; 111272343Sngie size_t iovlen, sz; 112272343Sngie const size_t extra_bytes = 28; 113272343Sngie const size_t total = extra_bytes + UINT_MAX + 1; 114272343Sngie long iov_max, vm_page_size; /* round_page wants vm_page_size variable */ 115272343Sngie 116272343Sngie memset(&ifr, 0, sizeof(ifr)); 117272343Sngie 118272343Sngie iov_max = sysconf(_SC_IOV_MAX); 119272343Sngie vm_page_size = sysconf(_SC_PAGE_SIZE); 120272343Sngie ATF_REQUIRE(iov_max > 1 && vm_page_size > 1); 121272343Sngie 122272343Sngie /* 123272343Sngie * Minimize memory consumption by using many iovecs 124272343Sngie * all pointing to one memory region. 125272343Sngie */ 126272343Sngie iov = calloc(iov_max, sizeof(struct iovec)); 127272343Sngie ATF_REQUIRE(iov != NULL); 128272343Sngie 129272343Sngie sz = round_page((total + (iov_max - 1)) / iov_max); 130272343Sngie 131272343Sngie iov[0].iov_len = sz; 132272343Sngie iov[0].iov_base = mmap(NULL, sz, PROT_READ, MAP_ANON, -1, 0); 133272343Sngie ATF_REQUIRE(iov[0].iov_base != MAP_FAILED); 134272343Sngie 135272343Sngie iovlen = 1; 136272343Sngie while (sz + iov[0].iov_len <= total) 137272343Sngie { 138272343Sngie iov[iovlen].iov_len = iov[0].iov_len; 139272343Sngie iov[iovlen].iov_base = iov[0].iov_base; 140272343Sngie sz += iov[0].iov_len; 141272343Sngie iovlen++; 142272343Sngie } 143272343Sngie 144272343Sngie if (sz < total) 145272343Sngie { 146272343Sngie iov[iovlen].iov_len = total - sz; 147272343Sngie iov[iovlen].iov_base = iov[0].iov_base; 148272343Sngie iovlen++; 149272343Sngie } 150272343Sngie 151272343Sngie /* Sanity checks */ 152272343Sngie ATF_REQUIRE(iovlen >= 1 && iovlen <= (size_t)iov_max); 153272343Sngie ATF_REQUIRE_EQ(iov[iovlen-1].iov_len, total % iov[0].iov_len); 154272343Sngie 155272343Sngie RZ(rump_init()); 156272343Sngie netcfg_rump_makeshmif("bpfwritetrunc", ifr.ifr_name); 157272343Sngie netcfg_rump_if(ifr.ifr_name, "10.1.1.1", "255.0.0.0"); 158272343Sngie 159272343Sngie RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR)); 160272343Sngie RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr)); 161272343Sngie 162272343Sngie ATF_CHECK_ERRNO(EMSGSIZE, rump_sys_writev(bpfd, iov, iovlen) == -1); 163272343Sngie 164272343Sngie munmap(iov[0].iov_base, iov[0].iov_len); 165272343Sngie free(iov); 166272343Sngie} 167272343Sngie#endif /* #if (SIZE_MAX > UINT_MAX) */ 168272343Sngie 169314818SngieATF_TC(bpf_ioctl_BLEN); 170314818SngieATF_TC_HEAD(bpf_ioctl_BLEN, tc) 171314818Sngie{ 172314818Sngie 173314818Sngie atf_tc_set_md_var(tc, "descr", "Checks behaviors of BIOCGBLEN and " 174314818Sngie "BIOCSBLEN"); 175314818Sngie} 176314818Sngie 177314818SngieATF_TC_BODY(bpf_ioctl_BLEN, tc) 178314818Sngie{ 179314818Sngie struct ifreq ifr; 180314818Sngie int ifnum, bpfd; 181314818Sngie u_int blen = 0; 182314818Sngie 183314818Sngie RZ(rump_init()); 184314818Sngie RZ(rump_pub_shmif_create(NULL, &ifnum)); 185314818Sngie sprintf(ifr.ifr_name, "shmif%d", ifnum); 186314818Sngie 187314818Sngie RL(bpfd = rump_sys_open("/dev/bpf", O_RDWR)); 188314818Sngie 189314818Sngie RL(rump_sys_ioctl(bpfd, BIOCGBLEN, &blen)); 190314818Sngie ATF_REQUIRE(blen != 0); 191314818Sngie blen = 100; 192314818Sngie RL(rump_sys_ioctl(bpfd, BIOCSBLEN, &blen)); 193314818Sngie RL(rump_sys_ioctl(bpfd, BIOCGBLEN, &blen)); 194314818Sngie ATF_REQUIRE_EQ(blen, 100); 195314818Sngie 196314818Sngie RL(rump_sys_ioctl(bpfd, BIOCSETIF, &ifr)); 197314818Sngie 198314818Sngie ATF_REQUIRE_EQ_MSG(rump_sys_ioctl(bpfd, BIOCSBLEN, &blen), -1, 199314818Sngie "Don't allow to change buflen after binding bpf to an interface"); 200314818Sngie} 201314818Sngie 202272343SngieATF_TP_ADD_TCS(tp) 203272343Sngie{ 204272343Sngie 205272343Sngie ATF_TP_ADD_TC(tp, bpfwriteleak); 206272343Sngie#if (SIZE_MAX > UINT_MAX) 207272343Sngie ATF_TP_ADD_TC(tp, bpfwritetrunc); 208272343Sngie#endif 209314818Sngie ATF_TP_ADD_TC(tp, bpf_ioctl_BLEN); 210272343Sngie return atf_no_error(); 211272343Sngie} 212