git: 00cd3145d4c6 - stable/13 - pf: improve SCTP state validation
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Oct 2023 09:33:25 UTC
The branch stable/13 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=00cd3145d4c650446ae54007ec50745244942ef2 commit 00cd3145d4c650446ae54007ec50745244942ef2 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2023-09-01 11:33:56 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2023-10-02 08:51:43 +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 | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 07a4140e450f..3cb093ba8b02 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -700,7 +700,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 { @@ -1332,6 +1335,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; @@ -2044,6 +2048,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 cb4ab2da4633..551bfd01732f 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -4340,11 +4340,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, if ((pd->flags & PFDESC_TCP_NORM) && 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 ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub && pf_normalize_tcp_stateful(m, off, pd, &reason, th, s, @@ -4353,12 +4349,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; @@ -5312,6 +5309,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 */ @@ -5352,6 +5356,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, pd->dir, 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 ec3f63c9f262..a8ef4dc346b0 100644 --- a/sys/netpfil/pf/pf_norm.c +++ b/sys/netpfil/pf/pf_norm.c @@ -1529,6 +1529,7 @@ 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. */ if (state->src.scrub) uma_zfree(V_pf_state_scrub_z, state->src.scrub); if (state->dst.scrub) @@ -1537,6 +1538,23 @@ pf_normalize_tcp_cleanup(struct pf_kstate *state) /* 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, u_short *reason, struct tcphdr *th, struct pf_kstate *state,