svn commit: r341008 - head/sys/net
Andrey V. Elsukov
ae at FreeBSD.org
Tue Nov 27 09:04:07 UTC 2018
Author: ae
Date: Tue Nov 27 09:04:06 2018
New Revision: 341008
URL: https://svnweb.freebsd.org/changeset/base/341008
Log:
Fix possible panic during ifnet detach in rtsock.
The panic can happen, when some application does dump of routing table
using sysctl interface. To prevent this, set IFF_DYING flag in
if_detach_internal() function, when ifnet under lock is removed from
the chain. In sysctl_rtsock() take IFNET_RLOCK_NOSLEEP() to prevent
ifnet detach during routes enumeration. In case, if some interface was
detached in the time before we take the lock, add the check, that ifnet
is not DYING. This prevents access to memory that could be freed after
ifnet is unlinked.
PR: 227720, 230498, 233306
Reviewed by: bz, eugen
MFC after: 1 week
Sponsored by: Yandex LLC
Differential Revision: https://reviews.freebsd.org/D18338
Modified:
head/sys/net/if.c
head/sys/net/rtsock.c
Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c Tue Nov 27 08:51:15 2018 (r341007)
+++ head/sys/net/if.c Tue Nov 27 09:04:06 2018 (r341008)
@@ -1068,6 +1068,8 @@ if_detach_internal(struct ifnet *ifp, int vmove, struc
CK_STAILQ_FOREACH(iter, &V_ifnet, if_link)
if (iter == ifp) {
CK_STAILQ_REMOVE(&V_ifnet, ifp, ifnet, if_link);
+ if (!vmove)
+ ifp->if_flags |= IFF_DYING;
found = 1;
break;
}
Modified: head/sys/net/rtsock.c
==============================================================================
--- head/sys/net/rtsock.c Tue Nov 27 08:51:15 2018 (r341007)
+++ head/sys/net/rtsock.c Tue Nov 27 09:04:06 2018 (r341008)
@@ -1559,6 +1559,8 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
struct rt_addrinfo info;
struct sockaddr_storage ss;
+ IFNET_RLOCK_NOSLEEP_ASSERT();
+
if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
return 0;
if ((rt->rt_flags & RTF_HOST) == 0
@@ -1571,7 +1573,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
info.rti_info[RTAX_NETMASK] = rtsock_fix_netmask(rt_key(rt),
rt_mask(rt), &ss);
info.rti_info[RTAX_GENMASK] = 0;
- if (rt->rt_ifp) {
+ if (rt->rt_ifp && !(rt->rt_ifp->if_flags & IFF_DYING)) {
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
if (rt->rt_ifp->if_flags & IFF_POINTOPOINT)
@@ -1934,8 +1936,10 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
rnh = rt_tables_get_rnh(fib, i);
if (rnh != NULL) {
RIB_RLOCK(rnh);
+ IFNET_RLOCK_NOSLEEP();
error = rnh->rnh_walktree(&rnh->head,
sysctl_dumpentry, &w);
+ IFNET_RUNLOCK_NOSLEEP();
RIB_RUNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
More information about the svn-src-all
mailing list