The em-driver will panic if one issues a SIOCGIFADDR ioctl to a em-device with only an inet6 address configured. em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=18b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWCSUM,TSO4> ether 00:11:25:16:db:58 inet6 fe80::211:25ff:fe16:db58%em0 prefixlen 64 scopeid 0x1 media: Ethernet autoselect status: no carrier Fatal trap 12: page fault while in kernel mode cpuid = 0; apic id = 00 fault virtual address = 0x306d66 fault code = supervisor read, page not present instruction pointer = 0x20:0xc087113b stack pointer = 0x28:0xe63b4b4c frame pointer = 0x28:0xe63b4b7c code segment = base rx0, limit 0xfffff, type 0x1b = DPL 0, pres 1, def32 1, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 1576 (foo) Backtrace #9 0xc06ad62b in calltrap () at /usr/src/sys/i386/i386/exception.s:139 #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 #11 0xc05e44ff in in6_control (so=0xc46cd318, cmd=3284147200, data=0xc48fcd80 "em0", ifp=0xc3c01c00, td=0xc4227000) at /usr/src/sys/netinet6/in6.c:785 #12 0xc059f258 in ifioctl (so=0xc46cd318, cmd=3223349537, data=0xc48fcd80 "em0", td=0xc4227000) at /usr/src/sys/net/if.c:1874 #13 0xc055ae97 in soo_ioctl (fp=0x306d65, cmd=3223349537, data=0xc48fcd80, active_cred=0xc4265700, td=0xc4227000) at /usr/src/sys/kern/sys_socket.c:202 #14 0xc0555dba in kern_ioctl (td=0xc4227000, fd=3, com=3223349537, data=0xc48fcd80 "em0") at file.h:266 #15 0xc0555bc5 in ioctl (td=0xc4227000, uap=0xe63b4d00) at /usr/src/sys/kern/sys_generic.c:542 The offending line is (kgdb) f 10 #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 977 if (ifa->ifa_addr->sa_family == AF_INET) { Fix: For SIOCGIFADDR the cast to a struct ifaddr is invalid and will cause ifa_addr to point to a bogous address. I believe it's safe to simply remove SIOCGIFADDR, the intialization shouldn't be needed in this case. How-To-Repeat: The following code should trigger the panic, but not if an inet4 address is configured on the interface. #include <string.h> #include <sys/ioctl.h> #include <sys/sockio.h> #include <sys/socket.h> #include <net/if.h> int main(int argc, char *argv[]) { int sock; struct ifreq ifreq; sock = socket(AF_INET6, SOCK_DGRAM, 0); bzero(&ifreq, sizeof(struct ifreq)); strcpy(ifreq.ifr_name, "em0"); ioctl(sock, SIOCGIFADDR, &ifreq); return (0); }
On Thu, May 24, 2007 at 01:00:10PM +0200, Fredrik Lindberg wrote: > The em-driver will panic if one issues a SIOCGIFADDR ioctl to a em-device > with only an inet6 address configured. > > em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 > options=18b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWCSUM,TSO4> > ether 00:11:25:16:db:58 > inet6 fe80::211:25ff:fe16:db58%em0 prefixlen 64 scopeid 0x1 > media: Ethernet autoselect > status: no carrier > > Fatal trap 12: page fault while in kernel mode > cpuid = 0; apic id = 00 > fault virtual address = 0x306d66 > fault code = supervisor read, page not present > instruction pointer = 0x20:0xc087113b > stack pointer = 0x28:0xe63b4b4c > frame pointer = 0x28:0xe63b4b7c > code segment = base rx0, limit 0xfffff, type 0x1b > = DPL 0, pres 1, def32 1, gran 1 > processor eflags = interrupt enabled, resume, IOPL = 0 > current process = 1576 (foo) > > Backtrace > #9 0xc06ad62b in calltrap () at /usr/src/sys/i386/i386/exception.s:139 > #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, > data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 > #11 0xc05e44ff in in6_control (so=0xc46cd318, cmd=3284147200, > data=0xc48fcd80 "em0", ifp=0xc3c01c00, td=0xc4227000) > at /usr/src/sys/netinet6/in6.c:785 > #12 0xc059f258 in ifioctl (so=0xc46cd318, cmd=3223349537, data=0xc48fcd80 "em0", > td=0xc4227000) at /usr/src/sys/net/if.c:1874 > #13 0xc055ae97 in soo_ioctl (fp=0x306d65, cmd=3223349537, data=0xc48fcd80, > active_cred=0xc4265700, td=0xc4227000) at /usr/src/sys/kern/sys_socket.c:202 > #14 0xc0555dba in kern_ioctl (td=0xc4227000, fd=3, com=3223349537, > data=0xc48fcd80 "em0") at file.h:266 > #15 0xc0555bc5 in ioctl (td=0xc4227000, uap=0xe63b4d00) > at /usr/src/sys/kern/sys_generic.c:542 > > The offending line is > (kgdb) f 10 > #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, > data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 > 977 if (ifa->ifa_addr->sa_family == AF_INET) { > > This is because SIOCGIFADDR expects a pointer to "struct ifreq" as an argument and not "struct ifaddr" -- it got broken in rev. 1.119 by yongari@ which shouldn't have touched SIOCGIFADDR at all. The fix is simple -- just remove the line that tests for SIOCGIFADDR, and it will get correctly passed down to ether_ioctl() later, like it was before rev. 1.119: %%% Index: if_em.c =================================================================== RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v retrieving revision 1.178 diff -u -p -r1.178 if_em.c --- if_em.c 23 May 2007 20:41:20 -0000 1.178 +++ if_em.c 24 May 2007 11:57:41 -0000 @@ -973,7 +973,6 @@ em_ioctl(struct ifnet *ifp, u_long comma switch (command) { case SIOCSIFADDR: - case SIOCGIFADDR: if (ifa->ifa_addr->sa_family == AF_INET) { /* * XXX %%% Thanks for the report! Cheers, -- Ruslan Ermilov ru@FreeBSD.org FreeBSD committer
On 5/24/07, Ruslan Ermilov <ru@freebsd.org> wrote: > On Thu, May 24, 2007 at 01:00:10PM +0200, Fredrik Lindberg wrote: > > The em-driver will panic if one issues a SIOCGIFADDR ioctl to a em-device > > with only an inet6 address configured. > > > > em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 > > options=18b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWCSUM,TSO4> > > ether 00:11:25:16:db:58 > > inet6 fe80::211:25ff:fe16:db58%em0 prefixlen 64 scopeid 0x1 > > media: Ethernet autoselect > > status: no carrier > > > > Fatal trap 12: page fault while in kernel mode > > cpuid = 0; apic id = 00 > > fault virtual address = 0x306d66 > > fault code = supervisor read, page not present > > instruction pointer = 0x20:0xc087113b > > stack pointer = 0x28:0xe63b4b4c > > frame pointer = 0x28:0xe63b4b7c > > code segment = base rx0, limit 0xfffff, type 0x1b > > = DPL 0, pres 1, def32 1, gran 1 > > processor eflags = interrupt enabled, resume, IOPL = 0 > > current process = 1576 (foo) > > > > Backtrace > > #9 0xc06ad62b in calltrap () at /usr/src/sys/i386/i386/exception.s:139 > > #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, > > data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 > > #11 0xc05e44ff in in6_control (so=0xc46cd318, cmd=3284147200, > > data=0xc48fcd80 "em0", ifp=0xc3c01c00, td=0xc4227000) > > at /usr/src/sys/netinet6/in6.c:785 > > #12 0xc059f258 in ifioctl (so=0xc46cd318, cmd=3223349537, data=0xc48fcd80 "em0", > > td=0xc4227000) at /usr/src/sys/net/if.c:1874 > > #13 0xc055ae97 in soo_ioctl (fp=0x306d65, cmd=3223349537, data=0xc48fcd80, > > active_cred=0xc4265700, td=0xc4227000) at /usr/src/sys/kern/sys_socket.c:202 > > #14 0xc0555dba in kern_ioctl (td=0xc4227000, fd=3, com=3223349537, > > data=0xc48fcd80 "em0") at file.h:266 > > #15 0xc0555bc5 in ioctl (td=0xc4227000, uap=0xe63b4d00) > > at /usr/src/sys/kern/sys_generic.c:542 > > > > The offending line is > > (kgdb) f 10 > > #10 0xc087113b in em_ioctl (ifp=0xc3c01c00, command=3223349537, > > data=0xc48fcd80 "em0") at /usr/src/sys/modules/em/../../dev/em/if_em.c:977 > > 977 if (ifa->ifa_addr->sa_family == AF_INET) { > > > > > This is because SIOCGIFADDR expects a pointer to "struct ifreq" > as an argument and not "struct ifaddr" -- it got broken in rev. > 1.119 by yongari@ which shouldn't have touched SIOCGIFADDR at > all. The fix is simple -- just remove the line that tests for > SIOCGIFADDR, and it will get correctly passed down to ether_ioctl() > later, like it was before rev. 1.119: > > %%% > Index: if_em.c > =================================================================== > RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v > retrieving revision 1.178 > diff -u -p -r1.178 if_em.c > --- if_em.c 23 May 2007 20:41:20 -0000 1.178 > +++ if_em.c 24 May 2007 11:57:41 -0000 > @@ -973,7 +973,6 @@ em_ioctl(struct ifnet *ifp, u_long comma > > switch (command) { > case SIOCSIFADDR: > - case SIOCGIFADDR: > if (ifa->ifa_addr->sa_family == AF_INET) { > /* > * XXX > %%% > > Thanks for the report! Let me look over the code history a bit, I will try to get a fix in shortly. Jack
Responsible Changed From-To: freebsd-bugs->jfv jfv is reportedly looking at this.
The problematic commit/code was removed and is no longer an issue in the upcoming 10.2r release.