Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net Protect ifp returned from route_output_get_ifa surely
details: https://anonhg.NetBSD.org/src/rev/84867b70d82e
branches: trunk
changeset: 358144:84867b70d82e
user: ozaki-r <ozaki-r%NetBSD.org@localhost>
date: Thu Dec 14 05:47:45 2017 +0000
description:
Protect ifp returned from route_output_get_ifa surely
An ifp returned from route_output_get_ifa was supposed to be protected
by a returned ifa; if the ifa belongs to ifp, holding the ifa prevents
the ifp from being freed. However route_output_get_ifa can return an ifp
to which a returned ifa doesn't belong. So we need to take a reference
to a returning ifp separately.
diffstat:
sys/net/rtsock.c | 22 ++++++++++++++++------
1 files changed, 16 insertions(+), 6 deletions(-)
diffs (86 lines):
diff -r 9cf7e999cc48 -r 84867b70d82e sys/net/rtsock.c
--- a/sys/net/rtsock.c Thu Dec 14 05:46:54 2017 +0000
+++ b/sys/net/rtsock.c Thu Dec 14 05:47:45 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: rtsock.c,v 1.232 2017/12/14 05:43:14 ozaki-r Exp $ */
+/* $NetBSD: rtsock.c,v 1.233 2017/12/14 05:47:45 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.232 2017/12/14 05:43:14 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.233 2017/12/14 05:47:45 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -608,7 +608,7 @@
static struct ifaddr * __noinline
route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt,
- struct ifnet **ifp, struct psref *psref)
+ struct ifnet **ifp, struct psref *psref_ifp, struct psref *psref)
{
struct ifaddr *ifa = NULL;
@@ -618,6 +618,7 @@
if (ifa == NULL)
goto next;
*ifp = ifa->ifa_ifp;
+ if_acquire(*ifp, psref_ifp);
if (info.rti_info[RTAX_IFA] == NULL &&
info.rti_info[RTAX_GATEWAY] == NULL)
goto next;
@@ -648,8 +649,14 @@
info.rti_info[RTAX_GATEWAY], psref);
}
out:
- if (ifa != NULL && *ifp == NULL)
+ if (ifa != NULL && *ifp == NULL) {
*ifp = ifa->ifa_ifp;
+ if_acquire(*ifp, psref_ifp);
+ }
+ if (ifa == NULL && *ifp != NULL) {
+ if_put(*ifp, psref_ifp);
+ *ifp = NULL;
+ }
return ifa;
}
@@ -660,7 +667,7 @@
int error = 0;
struct ifnet *ifp = NULL, *new_ifp;
struct ifaddr *ifa = NULL, *new_ifa;
- struct psref psref_ifa, psref_new_ifa, psref_ifp;
+ struct psref psref_ifa, psref_new_ifa, psref_ifp, psref_new_ifp;
bool newgw, ifp_changed = false;
/*
@@ -674,6 +681,7 @@
if (newgw || info->rti_info[RTAX_IFP] != NULL ||
info->rti_info[RTAX_IFA] != NULL) {
ifp = rt_getifp(info, &psref_ifp);
+ /* info refers ifp so we need to keep a reference */
ifa = rt_getifa(info, &psref_ifa);
if (ifa == NULL) {
error = ENETUNREACH;
@@ -698,7 +706,8 @@
* flags may also be different; ifp may be specified
* by ll sockaddr when protocol address is ambiguous
*/
- new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifa);
+ new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifp,
+ &psref_new_ifa);
if (new_ifa != NULL) {
ifa_release(ifa, &psref_ifa);
ifa = new_ifa;
@@ -736,6 +745,7 @@
(void)ifp_changed; /* XXX gcc */
#endif
out:
+ if_put(new_ifp, &psref_new_ifp);
if_put(ifp, &psref_ifp);
return error;
Home |
Main Index |
Thread Index |
Old Index