On Tue, Jul 04, 2017 at 05:19:46PM +0200, Alexander Bluhm wrote:
> Panic happens during /usr/src/regress/sys/ffs/nfs setup.
> 
> login: panic: free: non-malloced addr 0xd4b81630 type rtable
> Stopped at      db_enter+0x7:   leave
>     TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
>  382123  44974      0    0x100002          0    1  sh
> *424094  92583      0           0          0    0  mountd
> db_enter(d09d2ab3,f5820bb8,d0baf53c,f5820bb8,d4aa5600) at db_enter+0x7
> panic(d0baf53c,d4b81630,d0aaab21,d4aa5600,2) at panic+0x71
> free(d4b81630,5,0,d09157dc,d4ad2a9c) at free+0xd5
> vfs_free_addrlist(d5f88954,d4ad15f0,f5820c5c,d0779a59,d4ad2a9c) at 
> vfs_free_add
> rlist+0x45
> vfs_export(d5e58c00,d5f88954,f5820cb0,d4ad15f0,d4a99454) at vfs_export+0x63
> ffs_mount(d5e58c00,f5820e92,cf7cd2fc,f5820e2c,d4a99454) at ffs_mount+0x55d
> sys_mount(d4a99454,f5820f54,f5820f7c,0,286) at sys_mount+0x2f0
> syscall() at syscall+0x250
> --- syscall (number -813903004) ---

Replacing free() with rn_freehead() in vfs_free_addrlist() fixes
this panic.  NFS test passes, doing a full test run now.

bluhm

Index: kern/vfs_subr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.259
diff -u -p -r1.259 vfs_subr.c
--- kern/vfs_subr.c     20 Apr 2017 14:13:00 -0000      1.259
+++ kern/vfs_subr.c     4 Jul 2017 16:36:03 -0000
@@ -1405,7 +1405,7 @@ vfs_hang_addrlist(struct mount *mp, stru
        switch (i) {
        case AF_INET:
                if ((rnh = nep->ne_rtable_inet) == NULL) {
-                       if (!rn_inithead((void **)&nep->ne_rtable_inet,
+                       if (!rn_inithead(&nep->ne_rtable_inet,
                            offsetof(struct sockaddr_in, sin_addr))) {
                                error = ENOBUFS;
                                goto out;
@@ -1450,7 +1450,7 @@ vfs_free_addrlist(struct netexport *nep)
 
        if ((rnh = nep->ne_rtable_inet) != NULL) {
                rn_walktree(rnh, vfs_free_netcred, rnh);
-               free(rnh, M_RTABLE, 0);
+               rn_freehead(rnh);
                nep->ne_rtable_inet = NULL;
        }
 }
Index: net/pf_table.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_table.c,v
retrieving revision 1.126
diff -u -p -r1.126 pf_table.c
--- net/pf_table.c      8 May 2017 20:24:03 -0000       1.126
+++ net/pf_table.c      4 Jul 2017 16:30:17 -0000
@@ -2010,9 +2010,9 @@ pfr_create_ktable(struct pfr_table *tbl,
                rs->tables++;
        }
 
-       if (!rn_inithead((void **)&kt->pfrkt_ip4,
+       if (!rn_inithead(&kt->pfrkt_ip4,
            offsetof(struct sockaddr_in, sin_addr)) ||
-           !rn_inithead((void **)&kt->pfrkt_ip6,
+           !rn_inithead(&kt->pfrkt_ip6,
            offsetof(struct sockaddr_in6, sin6_addr))) {
                pfr_destroy_ktable(kt, 0);
                return (NULL);
@@ -2046,10 +2046,8 @@ pfr_destroy_ktable(struct pfr_ktable *kt
                pfr_clean_node_mask(kt, &addrq);
                pfr_destroy_kentries(&addrq);
        }
-       if (kt->pfrkt_ip4 != NULL)
-               free((caddr_t)kt->pfrkt_ip4, M_RTABLE, 0);
-       if (kt->pfrkt_ip6 != NULL)
-               free((caddr_t)kt->pfrkt_ip6, M_RTABLE, 0);
+       rn_freehead(kt->pfrkt_ip4);
+       rn_freehead(kt->pfrkt_ip6);
        if (kt->pfrkt_shadow != NULL)
                pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
        if (kt->pfrkt_rs != NULL) {
Index: net/pipex.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pipex.c,v
retrieving revision 1.102
diff -u -p -r1.102 pipex.c
--- net/pipex.c 6 Jun 2017 13:07:22 -0000       1.102
+++ net/pipex.c 4 Jul 2017 16:30:17 -0000
@@ -151,12 +151,12 @@ pipex_iface_init(struct pipex_iface_cont
        pipex_iface->ifnet_this = ifp;
 
        if (pipex_rd_head4 == NULL) {
-               if (!rn_inithead((void **)&pipex_rd_head4,
+               if (!rn_inithead(&pipex_rd_head4,
                    offsetof(struct sockaddr_in, sin_addr)))
                        panic("rn_inithead() failed on pipex_init()");
        }
        if (pipex_rd_head6 == NULL) {
-               if (!rn_inithead((void **)&pipex_rd_head6,
+               if (!rn_inithead(&pipex_rd_head6,
                    offsetof(struct sockaddr_in6, sin6_addr)))
                        panic("rn_inithead() failed on pipex_init()");
        }
Index: net/radix.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/radix.c,v
retrieving revision 1.58
diff -u -p -r1.58 radix.c
--- net/radix.c 20 Jun 2017 09:03:39 -0000      1.58
+++ net/radix.c 4 Jul 2017 16:30:17 -0000
@@ -60,7 +60,8 @@ static unsigned int    max_keylen;    /* size
 
 
 struct radix_node_head *mask_rnhead;   /* head of shared mask tree */
-struct pool             rtmask_pool;   /* pool for radix_mask structures */
+struct pool             rthead_pool;   /* pool for radix_node_head structs */
+struct pool             rtmask_pool;   /* pool for radix_mask structs */
 
 static inline int rn_satisfies_leaf(char *, struct radix_node *, int);
 static inline int rn_lexobetter(void *, void *);
@@ -1097,7 +1098,7 @@ rn_initmask(void)
 
        KASSERT(max_keylen > 0);
 
-       mask_rnhead = malloc(sizeof(*mask_rnhead), M_RTABLE, M_NOWAIT);
+       mask_rnhead = pool_get(&rthead_pool, PR_NOWAIT);
        if (mask_rnhead == NULL)
                return (1);
 
@@ -1106,7 +1107,7 @@ rn_initmask(void)
 }
 
 int
-rn_inithead(void **head, int off)
+rn_inithead(struct radix_node_head **head, int off)
 {
        struct radix_node_head *rnh;
 
@@ -1116,7 +1117,7 @@ rn_inithead(void **head, int off)
        if (rn_initmask())
                panic("failed to initialize the mask tree");
 
-       rnh = malloc(sizeof(*rnh), M_RTABLE, M_NOWAIT);
+       rnh = pool_get(&rthead_pool, PR_NOWAIT);
        if (rnh == NULL)
                return (0);
        *head = rnh;
@@ -1124,6 +1125,14 @@ rn_inithead(void **head, int off)
        return (1);
 }
 
+void
+rn_freehead(struct radix_node_head *rnh)
+{
+       if (rnh == NULL)
+               return;
+       pool_put(&rthead_pool, rnh);
+}
+
 int
 rn_inithead0(struct radix_node_head *rnh, int offset)
 {
@@ -1158,6 +1167,8 @@ rn_init(unsigned int keylen)
        if (max_keylen == 0) {
                pool_init(&rtmask_pool, sizeof(struct radix_mask), 0,
                    IPL_SOFTNET, 0, "rtmask", NULL);
+               pool_init(&rthead_pool, sizeof(struct radix_node_head), 0,
+                   IPL_SOFTNET, 0, "rthead", NULL);
        }
 
        if (keylen <= max_keylen)
Index: net/radix.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/radix.h,v
retrieving revision 1.30
diff -u -p -r1.30 radix.h
--- net/radix.h 19 Jun 2017 09:42:45 -0000      1.30
+++ net/radix.h 4 Jul 2017 16:30:17 -0000
@@ -97,7 +97,8 @@ struct radix_node_head {
 };
 
 void   rn_init(unsigned int);
-int    rn_inithead(void **, int);
+int    rn_inithead(struct radix_node_head **, int);
+void   rn_freehead(struct radix_node_head *);
 
 int    rn_walktree(struct radix_node_head *,
            int (*)(struct radix_node *, void *, u_int), void *);
Index: netinet/ip_spd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_spd.c,v
retrieving revision 1.92
diff -u -p -r1.92 ip_spd.c
--- netinet/ip_spd.c    6 Apr 2017 14:25:18 -0000       1.92
+++ netinet/ip_spd.c    4 Jul 2017 16:30:17 -0000
@@ -98,7 +98,7 @@ spd_table_add(unsigned int rtableid)
        }
 
        if (spd_tables[rdomain] == NULL) {
-               if (rn_inithead((void **)&rnh,
+               if (rn_inithead(&rnh,
                    offsetof(struct sockaddr_encap, sen_type)) == 0)
                        rnh = NULL;
                spd_tables[rdomain] = rnh;

Reply via email to