Module Name: src Committed By: ozaki-r Date: Thu Dec 17 02:38:33 UTC 2015
Modified Files: src/sys/net: if_llatbl.h src/sys/netinet: if_arp.c Log Message: Fix memory leak of llentry#la_opaque llentry#la_opaque which is for token ring is allocated in arp.c and freed in arp.c when freeing llentry. However, llentry can be freed from other places, e.g., lltable_free. In such cases, la_opaque is never freed. To fix that, add a new callback (lle_ll_free) to llentry and register a destruction function of la_opque to it. On freeing a llentry, we can surely free la_opque via the callback. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/net/if_llatbl.h cvs rdiff -u -r1.197 -r1.198 src/sys/netinet/if_arp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_llatbl.h diff -u src/sys/net/if_llatbl.h:1.6 src/sys/net/if_llatbl.h:1.7 --- src/sys/net/if_llatbl.h:1.6 Wed Nov 25 06:21:26 2015 +++ src/sys/net/if_llatbl.h Thu Dec 17 02:38:33 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_llatbl.h,v 1.6 2015/11/25 06:21:26 ozaki-r Exp $ */ +/* $NetBSD: if_llatbl.h,v 1.7 2015/12/17 02:38:33 ozaki-r Exp $ */ /* * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. * Copyright (c) 2004-2008 Qing Li. All rights reserved. @@ -79,6 +79,7 @@ struct llentry { struct lltable *lle_tbl; struct llentries *lle_head; void (*lle_free)(struct llentry *); + void (*lle_ll_free)(struct llentry *); struct mbuf *la_hold; int la_numheld; /* # of packets currently held */ time_t la_expire; @@ -202,9 +203,11 @@ struct llentry { } while (0) #define LLE_FREE_LOCKED(lle) do { \ - if ((lle)->lle_refcnt == 1) \ + if ((lle)->lle_refcnt == 1) { \ + if ((lle)->lle_ll_free != NULL) \ + (lle)->lle_ll_free(lle); \ (lle)->lle_free(lle); \ - else { \ + } else { \ LLE_REMREF(lle); \ LLE_WUNLOCK(lle); \ } \ Index: src/sys/netinet/if_arp.c diff -u src/sys/netinet/if_arp.c:1.197 src/sys/netinet/if_arp.c:1.198 --- src/sys/netinet/if_arp.c:1.197 Wed Dec 16 05:44:59 2015 +++ src/sys/netinet/if_arp.c Thu Dec 17 02:38:33 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.197 2015/12/16 05:44:59 ozaki-r Exp $ */ +/* $NetBSD: if_arp.c,v 1.198 2015/12/17 02:38:33 ozaki-r Exp $ */ /*- * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.197 2015/12/16 05:44:59 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.198 2015/12/17 02:38:33 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -175,6 +175,11 @@ static void arp_dad_start(struct ifaddr static void arp_dad_stop(struct ifaddr *); static void arp_dad_duplicated(struct ifaddr *); +static void arp_init_llentry(struct ifnet *, struct llentry *); +#if NTOKEN > 0 +static void arp_free_llentry_tokenring(struct llentry *); +#endif + struct ifqueue arpintrq = { .ifq_head = NULL, .ifq_tail = NULL, @@ -424,6 +429,30 @@ arp_setgate(struct rtentry *rt, struct s return gate; } +static void +arp_init_llentry(struct ifnet *ifp, struct llentry *lle) +{ + + switch (ifp->if_type) { +#if NTOKEN > 0 + case IFT_ISO88025: + lle->la_opaque = kmem_intr_alloc(sizeof(struct token_rif), + KM_NOSLEEP); + lle->lle_ll_free = arp_free_llentry_tokenring; + break; +#endif + } +} + +#if NTOKEN > 0 +static void +arp_free_llentry_tokenring(struct llentry *lle) +{ + + kmem_intr_free(lle->la_opaque, sizeof(struct token_rif)); +} +#endif + /* * Parallel to llc_rtrequest. */ @@ -646,20 +675,11 @@ arp_rtrequest(int req, struct rtentry *r } rt->rt_llinfo = la; LLE_ADDREF(la); - switch (ifp->if_type) { -#if NTOKEN > 0 - case IFT_ISO88025: - la->la_opaque = kmem_alloc(sizeof(struct token_rif), - KM_SLEEP); - break; -#endif /* NTOKEN > 0 */ - default: - break; - } la->la_rt = rt; rt->rt_refcnt++; rt->rt_flags |= RTF_LLINFO; arp_inuse++, arp_allocated++; + arp_init_llentry(ifp, la); LLE_WUNLOCK(la); la = NULL; @@ -682,19 +702,6 @@ arp_rtrequest(int req, struct rtentry *r IF_AFDATA_WLOCK(ifp); LLE_WLOCK(la); - if (la->la_opaque != NULL) { - switch (ifp->if_type) { -#if NTOKEN > 0 - case IFT_ISO88025: - kmem_free(la->la_opaque, - sizeof(struct token_rif)); - break; -#endif /* NTOKEN > 0 */ - default: - break; - } - } - if (la->la_rt != NULL) { /* * Don't rtfree (may actually free objects) here.