Date: Wed, 21 Apr 2010 08:28:48 +0300 From: Mikolaj Golub <to.my.trociny@gmail.com> To: freebsd-net <freebsd-net@FreeBSD.org> Subject: Races on alias deletion Message-ID: <86fx2pfk6n.fsf@zhuzha.ua1>
next in thread | raw e-mail | index | archive | help
--=-=-= Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 8bit Hi, Accidentally due to misconfiguration of our tools we ran simultaneously deletion of the same interface alias and crashed the box (FreeBSD-7.1). So I did some experiments on my 8-STABLE (I have CURRENT in virtualbox only) to investigate this running concurrently two scripts, which were adding and deleting the same address: while true; do ifconfig $IFACE alias $IP ifconfig $IFACE -alias $IP done The box crashed just after I started the second script. The crash was in in_control() on removing ia->ia_ifa from ifp->if_addrhead list, because there was no check if the address is still in the list before removing. panic: Bad link elm 0xcd2f3b00 prev->next != elm #0 doadump () at pcpu.h:246 #1 0xc04ec829 in db_fncall (dummy1=-1064461270, dummy2=0, dummy3=-1, dummy4=0xe9a737fc "\0208§é") at /usr/src/sys/ddb/db_command.c:548 #2 0xc04ecc5f in db_command (last_cmdp=0xc0e0ab9c, cmd_table=0x0, dopager=0) at /usr/src/sys/ddb/db_command.c:445 #3 0xc04ecd14 in db_command_script (command=0xc0e0bac4 "call doadump") at /usr/src/sys/ddb/db_command.c:516 #4 0xc04f0e50 in db_script_exec (scriptname=0xe9a73908 "kdb.enter.panic", warnifnotfound=Variable "warnifnotfound" is not available. ) at /usr/src/sys/ddb/db_script.c:302 #5 0xc04f0f37 in db_script_kdbenter (eventname=0xc0cc760a "panic") at /usr/src/sys/ddb/db_script.c:324 #6 0xc04eec18 in db_trap (type=3, code=0) at /usr/src/sys/ddb/db_main.c:228 #7 0xc08d9aa6 in kdb_trap (type=3, code=0, tf=0xe9a73a44) at /usr/src/sys/kern/subr_kdb.c:535 #8 0xc0befbeb in trap (frame=0xe9a73a44) at /usr/src/sys/i386/i386/trap.c:690 #9 0xc0bd130b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #10 0xc08d9c2a in kdb_enter (why=0xc0cc760a "panic", msg=0xc0cc760a "panic") at cpufunc.h:71 #11 0xc08a95b6 in panic (fmt=0xc0c61bc0 "Bad link elm %p prev->next != elm") at /usr/src/sys/kern/kern_shutdown.c:562 #12 0xc09ba87f in in_control (so=0xcdbd519c, cmd=2149607705, data=0xcd3db120 "fxp0", ifp=0xc5b94c00, td=0xc92ddb90) at /usr/src/sys/netinet/in.c:604 #13 0xc095d400 in ifioctl (so=0xcdbd519c, cmd=2149607705, data=0xcd3db120 "fxp0", td=0xc92ddb90) at /usr/src/sys/net/if.c:2516 #14 0xc08f69d5 in soo_ioctl (fp=0xcdc90af0, cmd=2149607705, data=0xcd3db120, active_cred=0xc9d78400, td=0xc92ddb90) at /usr/src/sys/kern/sys_socket.c:212 #15 0xc08f0a2d in kern_ioctl (td=0xc92ddb90, fd=3, com=2149607705, data=0xcd3db120 "fxp0") at file.h:262 #16 0xc08f0bb4 in ioctl (td=0xc92ddb90, uap=0xe9a73cf8) at /usr/src/sys/kern/sys_generic.c:678 #17 0xc0bef320 in syscall (frame=0xe9a73d38) at /usr/src/sys/i386/i386/trap.c:1111 #18 0xc0bd13a0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #19 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 12 #12 0xc09ba87f in in_control (so=0xcdbd519c, cmd=2149607705, data=0xcd3db120 "fxp0", ifp=0xc5b94c00, td=0xc92ddb90) at /usr/src/sys/netinet/in.c:604 604 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); (kgdb) list 599 default: 600 panic("in_control: unsupported ioctl"); 601 } 602 603 IF_ADDR_LOCK(ifp); 604 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); 605 IF_ADDR_UNLOCK(ifp); 606 ifa_free(&ia->ia_ifa); /* if_addrhead */ 607 608 IN_IFADDR_WLOCK(); The fist patch in the attachments fixed this type of crashes for me, but the box started to crash in in_lltable_prefix_free (now it was required for scripts to run a few seconds). (kgdb) bt #0 doadump () at pcpu.h:246 #1 0xc04ec829 in db_fncall (dummy1=1, dummy2=0, dummy3=-1056922880, dummy4=0xe8636760 "") at /usr/src/sys/ddb/db_command.c:548 #2 0xc04ecc21 in db_command (last_cmdp=0xc0e0ac1c, cmd_table=0x0, dopager=1) at /usr/src/sys/ddb/db_command.c:445 #3 0xc04ecd7a in db_command_loop () at /usr/src/sys/ddb/db_command.c:498 #4 0xc04eec1d in db_trap (type=12, code=0) at /usr/src/sys/ddb/db_main.c:229 #5 0xc08d9aa6 in kdb_trap (type=12, code=0, tf=0xe863694c) at /usr/src/sys/kern/subr_kdb.c:535 #6 0xc0beeedf in trap_fatal (frame=0xe863694c, eva=420) at /usr/src/sys/i386/i386/trap.c:929 #7 0xc0bef800 in trap (frame=0xe863694c) at /usr/src/sys/i386/i386/trap.c:328 #8 0xc0bd139b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #9 0xc08a6a8b in _rw_wlock_hard (rw=0xc79e1508, tid=3334964384, file=0xc0ce01e4 "/usr/src/sys/netinet/in.c", line=1370) at /usr/src/sys/kern/kern_rwlock.c:677 #10 0xc08a75d6 in _rw_wlock (rw=0xc79e1508, file=0xc0ce01e4 "/usr/src/sys/netinet/in.c", line=1370) at /usr/src/sys/kern/kern_rwlock.c:237 #11 0xc09bb17e in in_lltable_prefix_free (llt=0xc5dabc00, prefix=0xe8636a94, mask=0xe8636a84) at /usr/src/sys/netinet/in.c:1370 #12 0xc09631d1 in lltable_prefix_free (af=2, prefix=0xe8636a94, mask=0xe8636a84) at /usr/src/sys/net/if_llatbl.c:217 #13 0xc09b8d77 in in_ifscrub (ifp=0xc5b94c00, ia=0xc6ec0500) at /usr/src/sys/netinet/in.c:1197 #14 0xc09ba6dc in in_control (so=0xc79d2338, cmd=2149607705, data=0xc629b0c0 "fxp0", ifp=0xc5b94c00, td=0xc6c784a0) at /usr/src/sys/netinet/in.c:586 #15 0xc095d400 in ifioctl (so=0xc79d2338, cmd=2149607705, data=0xc629b0c0 "fxp0", td=0xc6c784a0) at /usr/src/sys/net/if.c:2516 #16 0xc08f69d5 in soo_ioctl (fp=0xc6304738, cmd=2149607705, data=0xc629b0c0, active_cred=0xc79d8d80, td=0xc6c784a0) at /usr/src/sys/kern/sys_socket.c:212 #17 0xc08f0a2d in kern_ioctl (td=0xc6c784a0, fd=3, com=2149607705, data=0xc629b0c0 "fxp0") at file.h:262 #18 0xc08f0bb4 in ioctl (td=0xc6c784a0, uap=0xe8636cf8) at /usr/src/sys/kern/sys_generic.c:678 #19 0xc0bef3b0 in syscall (frame=0xe8636d38) at /usr/src/sys/i386/i386/trap.c:1111 #20 0xc0bd1430 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #21 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 11 #11 0xc09bb17e in in_lltable_prefix_free (llt=0xc5dabc00, prefix=0xe8636a94, mask=0xe8636a84) at /usr/src/sys/netinet/in.c:1370 1370 LLE_WLOCK(lle); (kgdb) list 1365 LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { 1366 1367 if (IN_ARE_MASKED_ADDR_EQUAL((struct sockaddr_in *)L3_ADDR(lle), 1368 pfx, msk)) { 1369 callout_drain(&lle->la_timer); 1370 LLE_WLOCK(lle); 1371 llentry_free(lle); 1372 } 1373 } 1374 } (kgdb) p *lle $1 = {lle_next = {le_next = 0xdeadc0de, le_prev = 0xdeadc0de}, lle_lock = {lock_object = { lo_name = 0xdeadc0de <Address 0xdeadc0de out of bounds>, lo_flags = 3735929054, lo_data = 3735929054, lo_witness = 0xdeadc0de}, rw_lock = 3735929054}, lle_tbl = 0xdeadc0de, lle_head = 0xdeadc0de, la_hold = 0xdeadc0de, la_expire = -559038242, la_flags = 49374, la_asked = 57005, la_preempt = 49374, ln_byhint = 57005, ln_state = -16162, ln_router = 57005, ln_ntick = -559038242, lle_refcnt = -559038242, ll_addr = {mac_aligned = 16045693110842147038, mac16 = {49374, 57005, 49374}}, lle_timer = {ln_timer_ch = { c_links = {sle = {sle_next = 0xdeadc0de}, tqe = {tqe_next = 0xdeadc0de, tqe_prev = 0xdeadc0de}}, c_time = -559038242, c_arg = 0xdeadc0de, c_func = 0xdeadc0de, c_lock = 0xdeadc0de, c_flags = -559038242, c_cpu = -559038242}, la_timer = {c_links = {sle = {sle_next = 0xdeadc0de}, tqe = { tqe_next = 0xdeadc0de, tqe_prev = 0xdeadc0de}}, c_time = -559038242, c_arg = 0xdeadc0de, c_func = 0xdeadc0de, c_lock = 0xdeadc0de, c_flags = -559038242, c_cpu = -559038242}}} (kgdb) fr 12 #12 0xc09631d1 in lltable_prefix_free (af=2, prefix=0xe8636a94, mask=0xe8636a84) at /usr/src/sys/net/if_llatbl.c:217 217 llt->llt_prefix_free(llt, prefix, mask); (kgdb) list 212 LLTABLE_RLOCK(); 213 SLIST_FOREACH(llt, &V_lltables, llt_link) { 214 if (llt->llt_af != af) 215 continue; 216 217 llt->llt_prefix_free(llt, prefix, mask); 218 } 219 LLTABLE_RUNLOCK(); 220 } 221 So lltable is RLOCKed while the entries are deleted from the table. When callout_drain() is run by one thread other thread has time to destroy lle. Is LLTABLE_RLOCK (and not LLTABLE_WLOCK) in lltable_prefix_free used intentionally? I tried the patch (the second in the attaches) with WLOCK instead of RLOCK and this fixed this type of crashes for me. After this the box was able to live some time with two test scripts running but then crashed in sysctl_iflist(), processing ifa, which is destroyed by other thread: (kgdb) bt #0 doadump () at pcpu.h:246 #1 0xc08a92fe in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:416 #2 0xc08a95d2 in panic (fmt=Variable "fmt" is not available. ) at /usr/src/sys/kern/kern_shutdown.c:579 #3 0xc0beef23 in trap_fatal (frame=0xe8456a64, eva=3735929054) at /usr/src/sys/i386/i386/trap.c:938 #4 0xc0bef113 in trap_pfault (frame=0xe8456a64, usermode=0, eva=3735929054) at /usr/src/sys/i386/i386/trap.c:851 #5 0xc0befb05 in trap (frame=0xe8456a64) at /usr/src/sys/i386/i386/trap.c:533 #6 0xc0bd139b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #7 0xc096f85e in rt_msg2 (type=12, rtinfo=0xe8456b08, cp=0x0, w=0xe8456b38) at /usr/src/sys/net/rtsock.c:1022 #8 0xc096ff7b in sysctl_rtsock (oidp=0xc0dcb900, arg1=0xe8456c18, arg2=4, req=0xe8456ba4) at /usr/src/sys/net/rtsock.c:1408 #9 0xc08b4598 in sysctl_root (oidp=Variable "oidp" is not available. ) at /usr/src/sys/kern/kern_sysctl.c:1418 #10 0xc08b475c in userland_sysctl (td=0xc636b250, name=0xe8456c10, namelen=6, old=0x0, oldlenp=0xbfbfe048, inkernel=0, new=0x0, newlen=0, retval=0xe8456c70, flags=0) at /usr/src/sys/kern/kern_sysctl.c:1522 #11 0xc08b4b14 in __sysctl (td=0xc636b250, uap=0xe8456cf8) at /usr/src/sys/kern/kern_sysctl.c:1448 #12 0xc0bef3b0 in syscall (frame=0xe8456d38) at /usr/src/sys/i386/i386/trap.c:1111 #13 0xc0bd1430 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #14 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 8 #8 0xc096ff7b in sysctl_rtsock (oidp=0xc0dcb900, arg1=0xe8456c18, arg2=4, req=0xe8456ba4) at /usr/src/sys/net/rtsock.c:1408 1408 len = rt_msg2(RTM_NEWADDR, &info, NULL, w); (kgdb) list 1370,1410 1370 static int 1371 sysctl_iflist(int af, struct walkarg *w) 1372 { 1373 struct ifnet *ifp; 1374 struct ifaddr *ifa; 1375 struct rt_addrinfo info; 1376 int len, error = 0; 1377 1378 bzero((caddr_t)&info, sizeof(info)); 1379 IFNET_RLOCK(); 1380 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 1381 if (w->w_arg && w->w_arg != ifp->if_index) 1382 continue; 1383 ifa = ifp->if_addr; 1384 info.rti_info[RTAX_IFP] = ifa->ifa_addr; 1385 len = rt_msg2(RTM_IFINFO, &info, NULL, w); 1386 info.rti_info[RTAX_IFP] = NULL; 1387 if (w->w_req && w->w_tmem) { 1388 struct if_msghdr *ifm; 1389 1390 ifm = (struct if_msghdr *)w->w_tmem; 1391 ifm->ifm_index = ifp->if_index; 1392 ifm->ifm_flags = ifp->if_flags | ifp->if_drv_flags; 1393 ifm->ifm_data = ifp->if_data; 1394 ifm->ifm_addrs = info.rti_addrs; 1395 error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len); 1396 if (error) 1397 goto done; 1398 } 1399 while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != NULL) { 1400 if (af && af != ifa->ifa_addr->sa_family) 1401 continue; 1402 if (prison_if(w->w_req->td->td_ucred, 1403 ifa->ifa_addr) != 0) 1404 continue; 1405 info.rti_info[RTAX_IFA] = ifa->ifa_addr; 1406 info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; 1407 info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; 1408 len = rt_msg2(RTM_NEWADDR, &info, NULL, w); 1409 if (w->w_req && w->w_tmem) { 1410 struct ifa_msghdr *ifam; (kgdb) fr 7 #7 0xc096f85e in rt_msg2 (type=12, rtinfo=0xe8456b08, cp=0x0, w=0xe8456b38) at /usr/src/sys/net/rtsock.c:1022 1022 rtinfo->rti_addrs |= (1 << i); (kgdb) p *rtinfo $2 = {rti_addrs = 4, rti_info = {0x0, 0x0, 0xdeadc0de, 0x0, 0x0, 0xdeadc0de, 0x0, 0xdeadc0de}, rti_flags = 0, rti_ifa = 0x0, rti_ifp = 0x0} The third patch fixed this type of crashes. But the crashes were still possible: panic: Bad link elm 0xc876ea00 prev->next != elm #0 doadump () at pcpu.h:246 #1 0xc04ec829 in db_fncall (dummy1=-1064461270, dummy2=0, dummy3=-1, dummy4=0xe880d784 "\230×\200è") at /usr/src/sys/ddb/db_command.c:548 #2 0xc04ecc5f in db_command (last_cmdp=0xc0e0ac9c, cmd_table=0x0, dopager=0) at /usr/src/sys/ddb/db_command.c:445 #3 0xc04ecd14 in db_command_script (command=0xc0e0bbc4 "call doadump") at /usr/src/sys/ddb/db_command.c:516 #4 0xc04f0e50 in db_script_exec (scriptname=0xe880d890 "kdb.enter.panic", warnifnotfound=Variable "warnifnotfound" is not available. ) at /usr/src/sys/ddb/db_script.c:302 #5 0xc04f0f37 in db_script_kdbenter (eventname=0xc0cc770a "panic") at /usr/src/sys/ddb/db_script.c:324 #6 0xc04eec18 in db_trap (type=3, code=0) at /usr/src/sys/ddb/db_main.c:228 #7 0xc08d9aa6 in kdb_trap (type=3, code=0, tf=0xe880d9cc) at /usr/src/sys/kern/subr_kdb.c:535 #8 0xc0befcfb in trap (frame=0xe880d9cc) at /usr/src/sys/i386/i386/trap.c:690 #9 0xc0bd141b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #10 0xc08d9c2a in kdb_enter (why=0xc0cc770a "panic", msg=0xc0cc770a "panic") at cpufunc.h:71 #11 0xc08a95b6 in panic (fmt=0xc0c61cc0 "Bad link elm %p prev->next != elm") at /usr/src/sys/kern/kern_shutdown.c:562 #12 0xc09b8efc in in_ifinit (ifp=0xc5b94c00, ia=0xc876ea00, sin=0xc185fcf6, scrub=0) at /usr/src/sys/netinet/in.c:844 #13 0xc09ba58b in in_control (so=0xc7b13ce0, cmd=2151704858, data=0xc7841bc0 "fxp0", ifp=0xc5b94c00, td=0xc818db90) at /usr/src/sys/netinet/in.c:564 #14 0xc095d400 in ifioctl (so=0xc7b13ce0, cmd=2151704858, data=0xc7841bc0 "fxp0", td=0xc818db90) at /usr/src/sys/net/if.c:2516 #15 0xc08f69d5 in soo_ioctl (fp=0xc70a84d0, cmd=2151704858, data=0xc7841bc0, active_cred=0xc78dc400, td=0xc818db90) at /usr/src/sys/kern/sys_socket.c:212 #16 0xc08f0a2d in kern_ioctl (td=0xc818db90, fd=3, com=2151704858, data=0xc7841bc0 "fxp0") at file.h:262 #17 0xc08f0bb4 in ioctl (td=0xc818db90, uap=0xe880dcf8) at /usr/src/sys/kern/sys_generic.c:678 #18 0xc0bef430 in syscall (frame=0xe880dd38) at /usr/src/sys/i386/i386/trap.c:1111 #19 0xc0bd14b0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #20 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 12 #12 0xc09b8efc in in_ifinit (ifp=0xc5b94c00, ia=0xc876ea00, sin=0xc185fcf6, scrub=0) at /usr/src/sys/netinet/in.c:844 844 LIST_REMOVE(ia, ia_hash); (kgdb) list in_ifinit 832 * and routing table entry. 833 */ 834 static int 835 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, 836 int scrub) 837 { 838 register u_long i = ntohl(sin->sin_addr.s_addr); 839 struct sockaddr_in oldaddr; 840 int s = splimp(), flags = RTF_UP, error = 0; 841 (kgdb) 842 oldaddr = ia->ia_addr; 843 if (oldaddr.sin_family == AF_INET) 844 LIST_REMOVE(ia, ia_hash); 845 ia->ia_addr = *sin; 846 if (ia->ia_addr.sin_family == AF_INET) { 847 IN_IFADDR_WLOCK(); 848 LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), 849 ia, ia_hash); 850 IN_IFADDR_WUNLOCK(); 851 } Applying the fourth patch fixed this. But it is still possible to crash the box: #0 doadump () at pcpu.h:246 #1 0xc04ec829 in db_fncall (dummy1=1, dummy2=0, dummy3=-1056922624, dummy4=0xe847c890 "") at /usr/src/sys/ddb/db_command.c:548 #2 0xc04ecc21 in db_command (last_cmdp=0xc0e0ad1c, cmd_table=0x0, dopager=1) at /usr/src/sys/ddb/db_command.c:445 #3 0xc04ecd7a in db_command_loop () at /usr/src/sys/ddb/db_command.c:498 #4 0xc04eec1d in db_trap (type=12, code=0) at /usr/src/sys/ddb/db_main.c:229 #5 0xc08d9aa6 in kdb_trap (type=12, code=0, tf=0xe847ca7c) at /usr/src/sys/kern/subr_kdb.c:535 #6 0xc0beefbf in trap_fatal (frame=0xe847ca7c, eva=3735929146) at /usr/src/sys/i386/i386/trap.c:929 #7 0xc0bef8e0 in trap (frame=0xe847ca7c) at /usr/src/sys/i386/i386/trap.c:328 #8 0xc0bd147b in calltrap () at /usr/src/sys/i386/i386/exception.s:165 #9 0xc09b9c24 in in_control (so=0xc6e29670, cmd=2149607705, data=0xc6246ba0 "fxp0", ifp=0xc5b94c00, td=0xc6a59940) at /usr/src/sys/netinet/in.c:331 #10 0xc095d400 in ifioctl (so=0xc6e29670, cmd=2149607705, data=0xc6246ba0 "fxp0", td=0xc6a59940) at /usr/src/sys/net/if.c:2516 #11 0xc08f69d5 in soo_ioctl (fp=0xc6374700, cmd=2149607705, data=0xc6246ba0, active_cred=0xc7131280, td=0xc6a59940) at /usr/src/sys/kern/sys_socket.c:212 #12 0xc08f0a2d in kern_ioctl (td=0xc6a59940, fd=3, com=2149607705, data=0xc6246ba0 "fxp0") at file.h:262 #13 0xc08f0bb4 in ioctl (td=0xc6a59940, uap=0xe847ccf8) at /usr/src/sys/kern/sys_generic.c:678 #14 0xc0bef490 in syscall (frame=0xe847cd38) at /usr/src/sys/i386/i386/trap.c:1111 #15 0xc0bd1510 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261 #16 0x00000033 in ?? () Previous frame inner to this frame (corrupt stack?) (kgdb) fr 9 #9 0xc09b9c24 in in_control (so=0xc6e29670, cmd=2149607705, data=0xc6246ba0 "fxp0", ifp=0xc5b94c00, td=0xc6a59940) at /usr/src/sys/netinet/in.c:331 331 if (iap->ia_ifp == ifp && (kgdb) list 326 * first one on the interface, if possible. 327 */ 328 dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; 329 IN_IFADDR_RLOCK(); 330 LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) { 331 if (iap->ia_ifp == ifp && 332 iap->ia_addr.sin_addr.s_addr == dst.s_addr) { 333 if (td == NULL || prison_check_ip4(td->td_ucred, 334 &dst) == 0) 335 ia = iap; (kgdb) p iap $1 = (struct in_ifaddr *) 0xdeadc0de But I don't have the patch for this yet :-). Also I have noticed that after running my tests long enough (but not so long to crash the box) the error message starts to appear on every attempt to add tested alias IP (although the alias is created): ifconfig: ioctl (SIOCAIFADDR): File exists This is because the route is not deleted on alias removal (some reference leak?). After removing the route manually the error does not appear. -- Mikolaj Golub --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=in.c.in_control.patch --- sys/netinet/in.c.orig 2010-04-16 15:15:07.000000000 +0300 +++ sys/netinet/in.c 2010-04-18 17:22:57.000000000 +0300 @@ -601,8 +601,17 @@ in_control(struct socket *so, u_long cmd } IF_ADDR_LOCK(ifp); - TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (&ia->ia_ifa == ifa) { + TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); + break; + } + } IF_ADDR_UNLOCK(ifp); + if (ifa == NULL) { + error = EADDRNOTAVAIL; + goto out; + } ifa_free(&ia->ia_ifa); /* if_addrhead */ IN_IFADDR_WLOCK(); --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=if_llatbl.c.lltable_prefix_free.patch --- sys/net/if_llatbl.c.orig 2010-04-18 22:38:58.000000000 +0300 +++ sys/net/if_llatbl.c 2010-04-18 22:39:13.000000000 +0300 @@ -209,14 +209,14 @@ lltable_prefix_free(int af, struct socka { struct lltable *llt; - LLTABLE_RLOCK(); + LLTABLE_WLOCK(); SLIST_FOREACH(llt, &V_lltables, llt_link) { if (llt->llt_af != af) continue; llt->llt_prefix_free(llt, prefix, mask); } - LLTABLE_RUNLOCK(); + LLTABLE_WUNLOCK(); } --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=rtsock.c.sysctl_iflist.patch --- sys/net/rtsock.c.orig 2010-04-19 08:19:48.000000000 +0300 +++ sys/net/rtsock.c 2010-04-19 08:26:02.000000000 +0300 @@ -1380,6 +1380,7 @@ sysctl_iflist(int af, struct walkarg *w) TAILQ_FOREACH(ifp, &V_ifnet, if_link) { if (w->w_arg && w->w_arg != ifp->if_index) continue; + IF_ADDR_LOCK(ifp); ifa = ifp->if_addr; info.rti_info[RTAX_IFP] = ifa->ifa_addr; len = rt_msg2(RTM_IFINFO, &info, NULL, w); @@ -1419,10 +1420,13 @@ sysctl_iflist(int af, struct walkarg *w) goto done; } } + IF_ADDR_UNLOCK(ifp); info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = info.rti_info[RTAX_BRD] = NULL; } done: + if (ifp) + IF_ADDR_UNLOCK(ifp); IFNET_RUNLOCK(); return (error); } --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=in.c.in_ifinit.2.patch --- sys/netinet/in.c.in_control 2010-04-18 21:00:37.000000000 +0300 +++ sys/netinet/in.c 2010-04-20 13:08:41.000000000 +0300 @@ -836,19 +836,25 @@ in_ifinit(struct ifnet *ifp, struct in_i int scrub) { register u_long i = ntohl(sin->sin_addr.s_addr); + register struct in_ifaddr *iap; struct sockaddr_in oldaddr; int s = splimp(), flags = RTF_UP, error = 0; oldaddr = ia->ia_addr; - if (oldaddr.sin_family == AF_INET) - LIST_REMOVE(ia, ia_hash); + IN_IFADDR_WLOCK(); + if (oldaddr.sin_family == AF_INET) { + LIST_FOREACH(iap, INADDR_HASH(oldaddr.sin_addr.s_addr), ia_hash) { + if (iap == ia) { + LIST_REMOVE(ia, ia_hash); + break; + } + } + } ia->ia_addr = *sin; - if (ia->ia_addr.sin_family == AF_INET) { - IN_IFADDR_WLOCK(); + if (ia->ia_addr.sin_family == AF_INET) LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); - IN_IFADDR_WUNLOCK(); - } + IN_IFADDR_WUNLOCK(); /* * Give the interface a chance to initialize * if this is its first address, --=-=-=--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86fx2pfk6n.fsf>