The previous version of this diff exposed UAF issue we had after
tdb_delete(). bluhm@ fixed this and proposes to put per-cpu counters
diff again to tree. This is the updated diff to be against the resent
sources.

Index: sys/net/pfkeyv2_convert.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2_convert.c,v
retrieving revision 1.77
diff -u -p -r1.77 pfkeyv2_convert.c
--- sys/net/pfkeyv2_convert.c   11 Dec 2021 16:33:46 -0000      1.77
+++ sys/net/pfkeyv2_convert.c   15 Dec 2021 15:45:26 -0000
@@ -963,18 +963,21 @@ export_satype(void **p, struct tdb *tdb)
 void
 export_counter(void **p, struct tdb *tdb)
 {
+       uint64_t counters[tdb_ncounters];
        struct sadb_x_counter *scnt = (struct sadb_x_counter *)*p;
 
+       counters_read(tdb->tdb_counters, counters, tdb_ncounters);
+
        scnt->sadb_x_counter_len = sizeof(struct sadb_x_counter) /
            sizeof(uint64_t);
        scnt->sadb_x_counter_pad = 0;
-       scnt->sadb_x_counter_ipackets = tdb->tdb_ipackets;
-       scnt->sadb_x_counter_opackets = tdb->tdb_opackets;
-       scnt->sadb_x_counter_ibytes = tdb->tdb_ibytes;
-       scnt->sadb_x_counter_obytes = tdb->tdb_obytes;
-       scnt->sadb_x_counter_idrops = tdb->tdb_idrops;
-       scnt->sadb_x_counter_odrops = tdb->tdb_odrops;
-       scnt->sadb_x_counter_idecompbytes = tdb->tdb_idecompbytes;
-       scnt->sadb_x_counter_ouncompbytes = tdb->tdb_ouncompbytes;
+       scnt->sadb_x_counter_ipackets = counters[tdb_ipackets];
+       scnt->sadb_x_counter_opackets = counters[tdb_opackets];
+       scnt->sadb_x_counter_ibytes = counters[tdb_ibytes];
+       scnt->sadb_x_counter_obytes = counters[tdb_obytes];
+       scnt->sadb_x_counter_idrops = counters[tdb_idrops];
+       scnt->sadb_x_counter_odrops = counters[tdb_odrops];
+       scnt->sadb_x_counter_idecompbytes = counters[tdb_idecompbytes];
+       scnt->sadb_x_counter_ouncompbytes = counters[tdb_ouncompbytes];
        *p += sizeof(struct sadb_x_counter);
 }
Index: sys/netinet/ip_ah.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ah.c,v
retrieving revision 1.169
diff -u -p -r1.169 ip_ah.c
--- sys/netinet/ip_ah.c 11 Dec 2021 16:33:46 -0000      1.169
+++ sys/netinet/ip_ah.c 15 Dec 2021 15:45:26 -0000
@@ -608,7 +608,7 @@ ah_input(struct mbuf **mp, struct tdb *t
        /* Update the counters. */
        ibytes = (m->m_pkthdr.len - skip - hl * sizeof(u_int32_t));
        tdb->tdb_cur_bytes += ibytes;
-       tdb->tdb_ibytes += ibytes;
+       tdbstat_add(tdb, tdb_ibytes, ibytes);
        ahstat_add(ahs_ibytes, ibytes);
 
        /* Hard expiration. */
Index: sys/netinet/ip_esp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_esp.c,v
retrieving revision 1.189
diff -u -p -r1.189 ip_esp.c
--- sys/netinet/ip_esp.c        11 Dec 2021 16:33:47 -0000      1.189
+++ sys/netinet/ip_esp.c        15 Dec 2021 15:45:26 -0000
@@ -420,7 +420,7 @@ esp_input(struct mbuf **mp, struct tdb *
 
        /* Update the counters */
        tdb->tdb_cur_bytes += plen;
-       tdb->tdb_ibytes += plen;
+       tdbstat_add(tdb, tdb_ibytes, plen);
        espstat_add(esps_ibytes, plen);
 
        /* Hard expiration */
Index: sys/netinet/ip_ipcomp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipcomp.c,v
retrieving revision 1.89
diff -u -p -r1.89 ip_ipcomp.c
--- sys/netinet/ip_ipcomp.c     11 Dec 2021 16:33:47 -0000      1.89
+++ sys/netinet/ip_ipcomp.c     15 Dec 2021 15:45:26 -0000
@@ -193,7 +193,7 @@ ipcomp_input(struct mbuf **mp, struct td
        /* update the counters */
        ibytes = m->m_pkthdr.len - (skip + hlen);
        tdb->tdb_cur_bytes += ibytes;
-       tdb->tdb_ibytes += ibytes;
+       tdbstat_add(tdb, tdb_ibytes, ibytes);
        ipcompstat_add(ipcomps_ibytes, ibytes);
 
        /* Hard expiration */
Index: sys/netinet/ip_ipsp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v
retrieving revision 1.265
diff -u -p -r1.265 ip_ipsp.c
--- sys/netinet/ip_ipsp.c       14 Dec 2021 17:50:37 -0000      1.265
+++ sys/netinet/ip_ipsp.c       15 Dec 2021 15:45:26 -0000
@@ -1062,6 +1062,9 @@ tdb_alloc(u_int rdomain)
        tdbp->tdb_rdomain = rdomain;
        tdbp->tdb_rdomain_post = rdomain;
 
+       /* Initialize counters. */
+       tdbp->tdb_counters = counters_alloc(tdb_ncounters);
+
        /* Initialize timeouts. */
        timeout_set_proc(&tdbp->tdb_timer_tmo, tdb_timeout, tdbp);
        timeout_set_proc(&tdbp->tdb_first_tmo, tdb_firstuse, tdbp);
@@ -1099,6 +1102,8 @@ tdb_free(struct tdb *tdbp)
                tdbp->tdb_tag = 0;
        }
 #endif
+
+       counters_free(tdbp->tdb_counters, tdb_ncounters);
 
        KASSERT(tdbp->tdb_onext == NULL);
        KASSERT(tdbp->tdb_inext == NULL);
Index: sys/netinet/ip_ipsp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v
retrieving revision 1.231
diff -u -p -r1.231 ip_ipsp.h
--- sys/netinet/ip_ipsp.h       14 Dec 2021 17:50:37 -0000      1.231
+++ sys/netinet/ip_ipsp.h       15 Dec 2021 15:45:26 -0000
@@ -136,17 +136,6 @@ struct ipsecstat {
        uint64_t        ipsec_exctdb;           /* TDBs with hardlimit excess */
 };
 
-struct tdb_data {
-       uint64_t        tdd_ipackets;           /* Input IPsec packets */
-       uint64_t        tdd_opackets;           /* Output IPsec packets */
-       uint64_t        tdd_ibytes;             /* Input bytes */
-       uint64_t        tdd_obytes;             /* Output bytes */
-       uint64_t        tdd_idrops;             /* Dropped on input */
-       uint64_t        tdd_odrops;             /* Dropped on output */
-       uint64_t        tdd_idecompbytes;       /* Input bytes, decompressed */
-       uint64_t        tdd_ouncompbytes;       /* Output bytes, uncompressed */
-};
-
 #ifdef _KERNEL
 
 #include <sys/timeout.h>
@@ -400,7 +389,8 @@ struct tdb {                                /* tunnel 
descriptor blo
        u_int64_t       tdb_last_used;  /* When was this SA last used */
        u_int64_t       tdb_last_marked;/* Last SKIPCRYPTO status change */
 
-       struct tdb_data tdb_data;       /* stats about this TDB */
+       struct cpumem   *tdb_counters;  /* stats about this TDB */
+
        u_int64_t       tdb_cryptoid;   /* Crypto session ID */
 
        u_int32_t       tdb_spi;        /* [I] SPI */
@@ -446,15 +436,37 @@ struct tdb {                              /* tunnel 
descriptor blo
        TAILQ_HEAD(tdb_policy_head, ipsec_policy) tdb_policy_head; /* [p] */
        TAILQ_ENTRY(tdb)        tdb_sync_entry;
 };
-#define tdb_ipackets           tdb_data.tdd_ipackets
-#define tdb_opackets           tdb_data.tdd_opackets
-#define tdb_ibytes             tdb_data.tdd_ibytes
-#define tdb_obytes             tdb_data.tdd_obytes
-#define tdb_idrops             tdb_data.tdd_idrops
-#define tdb_odrops             tdb_data.tdd_odrops
-#define tdb_idecompbytes       tdb_data.tdd_idecompbytes
-#define tdb_ouncompbytes       tdb_data.tdd_ouncompbytes
 
+enum tdb_counters {
+       tdb_ipackets,           /* Input IPsec packets */
+       tdb_opackets,           /* Output IPsec packets */
+       tdb_ibytes,             /* Input bytes */
+       tdb_obytes,             /* Output bytes */
+       tdb_idrops,             /* Dropped on input */
+       tdb_odrops,             /* Dropped on output */
+       tdb_idecompbytes,       /* Input bytes, decompressed */
+       tdb_ouncompbytes,       /* Output bytes, uncompressed */
+       tdb_ncounters
+};
+
+static inline void
+tdbstat_inc(struct tdb *tdb, enum tdb_counters c)
+{
+       counters_inc(tdb->tdb_counters, c);
+}
+
+static inline void
+tdbstat_add(struct tdb *tdb, enum tdb_counters c, uint64_t v)
+{
+       counters_add(tdb->tdb_counters, c, v);
+}
+
+static inline void
+tdbstat_pkt(struct tdb *tdb, enum tdb_counters pc, enum tdb_counters bc,
+    uint64_t bytes)
+{
+       counters_pkt(tdb->tdb_counters, pc, bc, bytes);
+}
 
 struct tdb_ident {
        u_int32_t spi;
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.377
diff -u -p -r1.377 ip_output.c
--- sys/netinet/ip_output.c     3 Dec 2021 17:18:34 -0000       1.377
+++ sys/netinet/ip_output.c     15 Dec 2021 15:45:26 -0000
@@ -662,7 +662,7 @@ ip_output_ipsec_send(struct tdb *tdb, st
        error = ipsp_process_packet(m, tdb, AF_INET, 0);
        if (error) {
                ipsecstat_inc(ipsec_odrops);
-               tdb->tdb_odrops++;
+               tdbstat_inc(tdb, tdb_odrops);
        }
        if (ip_mtudisc && error == EMSGSIZE)
                ip_output_ipsec_pmtu_update(tdb, ro, dst, rtableid, 0);
Index: sys/netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.197
diff -u -p -r1.197 ipsec_input.c
--- sys/netinet/ipsec_input.c   8 Dec 2021 14:24:18 -0000       1.197
+++ sys/netinet/ipsec_input.c   15 Dec 2021 15:45:26 -0000
@@ -340,8 +340,7 @@ ipsec_common_input(struct mbuf **mp, int
                }
        }
 
-       tdbp->tdb_ipackets++;
-       tdbp->tdb_ibytes += m->m_pkthdr.len;
+       tdbstat_pkt(tdbp, tdb_ipackets, tdb_ibytes, m->m_pkthdr.len);
 
        /*
         * Call appropriate transform and return -- callback takes care of
@@ -350,7 +349,7 @@ ipsec_common_input(struct mbuf **mp, int
        prot = (*(tdbp->tdb_xform->xf_input))(mp, tdbp, skip, protoff);
        if (prot == IPPROTO_DONE) {
                ipsecstat_inc(ipsec_idrops);
-               tdbp->tdb_idrops++;
+               tdbstat_inc(tdbp, tdb_idrops);
        }
        tdb_unref(tdbp);
        return prot;
@@ -359,7 +358,7 @@ ipsec_common_input(struct mbuf **mp, int
        m_freemp(mp);
        ipsecstat_inc(ipsec_idrops);
        if (tdbp != NULL)
-               tdbp->tdb_idrops++;
+               tdbstat_inc(tdbp, tdb_idrops);
        tdb_unref(tdbp);
        return IPPROTO_DONE;
 }
@@ -537,7 +536,7 @@ ipsec_common_input_cb(struct mbuf **mp, 
                m->m_flags |= M_TUNNEL;
 
        ipsecstat_add(ipsec_idecompbytes, m->m_pkthdr.len);
-       tdbp->tdb_idecompbytes += m->m_pkthdr.len;
+       tdbstat_add(tdbp, tdb_idecompbytes, m->m_pkthdr.len);
 
 #if NBPFILTER > 0
        encif = enc_getif(tdbp->tdb_rdomain_post, tdbp->tdb_tap);
Index: sys/netinet/ipsec_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_output.c,v
retrieving revision 1.94
diff -u -p -r1.94 ipsec_output.c
--- sys/netinet/ipsec_output.c  11 Dec 2021 16:33:47 -0000      1.94
+++ sys/netinet/ipsec_output.c  15 Dec 2021 15:45:26 -0000
@@ -367,7 +367,7 @@ ipsp_process_packet(struct mbuf *m, stru
        }
 
        ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len);
-       tdb->tdb_ouncompbytes += m->m_pkthdr.len;
+       tdbstat_add(tdb, tdb_ouncompbytes, m->m_pkthdr.len);
 
        /* Non expansion policy for IPCOMP */
        if (tdb->tdb_sproto == IPPROTO_IPCOMP) {
@@ -507,8 +507,7 @@ ipsp_process_done(struct mbuf *m, struct
        m_tag_prepend(m, mtag);
 
        ipsecstat_pkt(ipsec_opackets, ipsec_obytes, m->m_pkthdr.len);
-       tdb->tdb_opackets++;
-       tdb->tdb_obytes += m->m_pkthdr.len;
+       tdbstat_pkt(tdb, tdb_opackets, tdb_obytes, m->m_pkthdr.len);
 
        /* If there's another (bundled) TDB to apply, do so. */
        tdbo = tdb_ref(tdb->tdb_onext);
Index: sys/netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.263
diff -u -p -r1.263 ip6_output.c
--- sys/netinet6/ip6_output.c   3 Dec 2021 17:18:34 -0000       1.263
+++ sys/netinet6/ip6_output.c   15 Dec 2021 15:45:26 -0000
@@ -2875,7 +2875,7 @@ ip6_output_ipsec_send(struct tdb *tdb, s
                    rtableid, transportmode);
                if (error) {
                        ipsecstat_inc(ipsec_odrops);
-                       tdb->tdb_odrops++;
+                       tdbstat_inc(tdb, tdb_odrops);
                        m_freem(m);
                        return error;
                }
@@ -2897,7 +2897,7 @@ ip6_output_ipsec_send(struct tdb *tdb, s
        error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
        if (error) {
                ipsecstat_inc(ipsec_odrops);
-               tdb->tdb_odrops++;
+               tdbstat_inc(tdb, tdb_odrops);
        }
        if (ip_mtudisc && error == EMSGSIZE)
                ip6_output_ipsec_pmtu_update(tdb, ro, &dst, ifidx, rtableid, 0);

Reply via email to