The branch stable/14 has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=48172aad8143d72fa2af363f4b6da0bf1c522789

commit 48172aad8143d72fa2af363f4b6da0bf1c522789
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2023-09-01 11:33:56 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2023-10-02 09:32:14 +0000

    pf: improve SCTP state validation
    
    Only create new states for INIT chunks, or when we're creating a
    secondary state for a multihomed association.
    
    Store and verify verification tag.
    
    MFC after:      3 weeks
    Sponsored by:   Orange Business Services
    
    (cherry picked from commit 51a78dd2764beabfd19a58b8a8b04387a547f02e)
---
 sys/net/pfvar.h          |  8 +++++++-
 sys/netpfil/pf/pf.c      | 25 +++++++++++++++----------
 sys/netpfil/pf/pf_norm.c | 17 +++++++++++++++++
 3 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index ec72c1079c70..a8567ab74fe3 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -900,7 +900,10 @@ struct pf_state_scrub {
 #define PFSS_DATA_NOTS 0x0080          /* no timestamp on data packets */
        u_int8_t        pfss_ttl;       /* stashed TTL                  */
        u_int8_t        pad;
-       u_int32_t       pfss_ts_mod;    /* timestamp modulation         */
+       union {
+               u_int32_t       pfss_ts_mod;    /* timestamp modulation         
*/
+               u_int32_t       pfss_v_tag;     /* SCTP verification tag        
*/
+       };
 };
 
 struct pf_state_host {
@@ -1583,6 +1586,7 @@ struct pf_pdesc {
 #define PFDESC_SCTP_DATA       0x0040
 #define PFDESC_SCTP_ASCONF     0x0080
 #define PFDESC_SCTP_OTHER      0x0100
+#define PFDESC_SCTP_ADD_IP     0x0200
        u_int16_t        sctp_flags;
        u_int32_t        sctp_initiate_tag;
 
@@ -2301,6 +2305,8 @@ int       pf_normalize_tcp_init(struct mbuf *, int, 
struct pf_pdesc *,
 int    pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
            u_short *, struct tcphdr *, struct pf_kstate *,
            struct pf_state_peer *, struct pf_state_peer *, int *);
+int    pf_normalize_sctp_init(struct mbuf *, int, struct pf_pdesc *,
+           struct pf_state_peer *, struct pf_state_peer *);
 int    pf_normalize_sctp(int, struct pfi_kkif *, struct mbuf *, int,
            int, void *, struct pf_pdesc *);
 u_int32_t
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 69373b720ad9..8958579b7e63 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -4904,11 +4904,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, 
struct pf_krule *a,
                if (s->state_flags & PFSTATE_SCRUB_TCP &&
                    pf_normalize_tcp_init(m, off, pd, th, &s->src, &s->dst)) {
                        REASON_SET(&reason, PFRES_MEMORY);
-                       pf_src_tree_remove_state(s);
-                       s->timeout = PFTM_UNLINKED;
-                       STATE_DEC_COUNTERS(s);
-                       pf_free_state(s);
-                       return (PF_DROP);
+                       goto drop;
                }
                if (s->state_flags & PFSTATE_SCRUB_TCP && s->src.scrub &&
                    pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
@@ -4917,12 +4913,13 @@ pf_create_state(struct pf_krule *r, struct pf_krule 
*nr, struct pf_krule *a,
                        DPFPRINTF(PF_DEBUG_URGENT,
                            ("pf_normalize_tcp_stateful failed on first "
                             "pkt\n"));
-                       pf_src_tree_remove_state(s);
-                       s->timeout = PFTM_UNLINKED;
-                       STATE_DEC_COUNTERS(s);
-                       pf_free_state(s);
-                       return (PF_DROP);
+                       goto drop;
                }
+       } else if (pd->proto == IPPROTO_SCTP) {
+               if (pf_normalize_sctp_init(m, off, pd, &s->src, &s->dst))
+                       goto drop;
+               if (! (pd->sctp_flags & (PFDESC_SCTP_INIT | 
PFDESC_SCTP_ADD_IP)))
+                       goto drop;
        }
        s->direction = pd->dir;
 
@@ -5890,6 +5887,13 @@ pf_test_state_sctp(struct pf_kstate **state, struct 
pfi_kkif *kif,
                }
        }
 
+       if (src->scrub != NULL) {
+               if (src->scrub->pfss_v_tag == 0) {
+                       src->scrub->pfss_v_tag = pd->hdr.sctp.v_tag;
+               } else  if (src->scrub->pfss_v_tag != pd->hdr.sctp.v_tag)
+                       return (PF_DROP);
+       }
+
        (*state)->expire = time_uptime;
 
        /* translate source/destination address, if necessary */
@@ -5930,6 +5934,7 @@ pf_sctp_multihome_delayed(struct pf_pdesc *pd, int off, 
struct pfi_kkif *kif,
 
        TAILQ_FOREACH_SAFE(j, &pd->sctp_multihome_jobs, next, tmp) {
                PF_RULES_RLOCK();
+               j->pd.sctp_flags |= PFDESC_SCTP_ADD_IP;
                action = pf_test_rule(&r, &sm, kif,
                    j->m, off, &j->pd, &ra, &rs, NULL);
                PF_RULES_RUNLOCK();
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index 83b94db87a19..d63cf0ebe54e 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -1565,11 +1565,28 @@ pf_normalize_tcp_init(struct mbuf *m, int off, struct 
pf_pdesc *pd,
 void
 pf_normalize_tcp_cleanup(struct pf_kstate *state)
 {
+       /* XXX Note: this also cleans up SCTP. */
        uma_zfree(V_pf_state_scrub_z, state->src.scrub);
        uma_zfree(V_pf_state_scrub_z, state->dst.scrub);
 
        /* Someday... flush the TCP segment reassembly descriptors. */
 }
+int
+pf_normalize_sctp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
+           struct pf_state_peer *src, struct pf_state_peer *dst)
+{
+       src->scrub = uma_zalloc(V_pf_state_scrub_z, M_ZERO | M_NOWAIT);
+       if (src->scrub == NULL)
+               return (1);
+
+       dst->scrub = uma_zalloc(V_pf_state_scrub_z, M_ZERO | M_NOWAIT);
+       if (dst->scrub == NULL) {
+               uma_zfree(V_pf_state_scrub_z, src);
+               return (1);
+       }
+
+       return (0);
+}
 
 int
 pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,

Reply via email to