NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
port-evbarm/49020: Writing to tap device may cause panic on RPI
>Number: 49020
>Category: port-evbarm
>Synopsis: Writing to tap device may cause panic on RPI
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-evbarm-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 18 21:25:00 +0000 2014
>Originator: Takahiro HAYASHI
>Release: NetBSD 6.99.47 2014-07-18 11:57:12 UTC
>Organization:
>Environment:
System: NetBSD raspi 6.99.47 NetBSD 6.99.47 (MYRPI) #13: Fri Jul 18 20:50:08
JST 2014 root@halt:/build/head/obj.evbarm/sys/arch/evbarm/compile/MYRPI evbarm
Architecture: earmhf
Machine: evbarm
>Description:
Writing to tap device may cause panic on Raspberry-Pi.
tap(4) needs to be written data with ethernet link-level header,
whose length is 14. It means payload is not aligned.
ip6_input() tries to adjust alignment but does not do because
__NO_STRICT_ALIGNMENT is defined in arm/types.h on RPI.
This causes ip6->ip6_dst not aligned and copying struct
> sin6->sin6_addr = *addr;
in sockaddr_in6_init1() (this is inline func in in6.h) fails.
# ./a.out
writing data 0x212e0 len 70 to tap0 (f2:0b:a4:61:b0:fb)
data_abort_handler: data_aborts fsr=0x1 far=0xdbf1fa5e
Fatal kernel mode data abort: 'Alignment Fault 1'
trapframe: 0xdbf2be98
FSR=00000001, FAR=dbf1fa5e, spsr=80000013
r0 =00000000, r1 =00000000, r2 =00000018, r3 =0000001c
r4 =c0489444, r5 =00000000, r6 =dbf1fa46, r7 =dbf1fa5e
r8 =dbf1fa4e, r9 =00000004, r10=00000010, r11=dbf2bf4c
r12=00000000, ssp=dbf2bee8, slr=dbf2bf0c, pc =c00c4914
Stopped in pid 0.3 (system) at netbsd:ip6_input+0x7d0: ldmia r7, {r0-r3}
db> bt
0xdbf2bf4c: netbsd:ip6_input+0xc
0xdbf2bf64: netbsd:ip6intr+0x6c
0xdbf2bfac: netbsd:softint_dispatch+0xec
Bad frame pointer: 0xdb98bd34
>How-To-Repeat:
Enable tap* devices in your kernel and
configure tap0 and run this program.
> ifconfig tap0 create up
> ./a.out
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <err.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_ether.h>
#include <net/if_tap.h>
static struct ether_addr *getmyenaddr(char *);
/* total_len 0t70 (14+40+16)
* ether 00:16:3e:00:00:01 -> 0:0:0:0:0:0 (filled later)
* IP6 (hlim 64, next-header ICMPv6 (58) payload length: 16)
* 2001:db8::2 > 2001:db8::1: ICMP6, echo reply, seq 0
*/
static uint8_t data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ether_dhost */
0x00, 0x16, 0x3e, 0x00, 0x00, 0x01, /* ether_shost */
0x86, 0xdd, /* ETHERTYPE_IPV6 */
0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3a, 0x40, /* plen 16 ICMPv6 hlim 64 */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* src */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* dst */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x81, 0x00, 0x11, 0x0c, 0x12, 0x34, 0x00, 0x00, /* echo-reply */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int
main(int ac, char **av)
{
int fd;
struct ifreq ifr;
struct ether_addr *ea;
if ((fd = open("/dev/tap0", O_RDWR, 0)) < 0)
err(1, "tapopen");
memset(&ifr, 0, sizeof ifr);
if (ioctl(fd, TAPGIFNAME, &ifr) != 0)
err(1, "TAPGIFNAME");
if ((ea = getmyenaddr(ifr.ifr_name)) == NULL)
err(1, "getmyenaddr");
memcpy(&data[0], ea, ETHER_ADDR_LEN);
printf("writing data %p len %zd to %s (%s)\n",
data, sizeof data, ifr.ifr_name, ether_ntoa(ea));
fflush(stdout);
usleep(100000);
write(fd, data, sizeof data);
close(fd);
}
static struct ether_addr *
getmyenaddr(char *ifname)
{
struct ifaddrs *ifap0, *ifap;
struct ether_addr *ea = NULL;
static struct ether_addr ea0;
if (getifaddrs(&ifap0) == -1) {
perror("getifaddrs");
return NULL;
}
for (ifap = ifap0; ifap; ifap = ifap->ifa_next) {
if (strncmp(ifap->ifa_name, ifname, IFNAMSIZ))
continue;
if (ifap->ifa_addr->sa_family != AF_LINK)
continue;
ea = (struct ether_addr *)
LLADDR((struct sockaddr_dl *)ifap->ifa_addr);
memcpy(&ea0, ea, sizeof(ea0));
freeifaddrs(ifap0);
return &ea0;
}
freeifaddrs(ifap0);
return NULL;
}
__EOF__
>Fix:
To avoid this issue, comment out __NO_STRICT_ALIGNMENT in types.h.
Is it a good idea that tap_dev_write() puts data on mbuf
ETHER_ALIGN (2) bytes later for padding and do m_adj(m, 2) ?
--
t-hash
Home |
Main Index |
Thread Index |
Old Index