]> git.baikalelectronics.ru Git - kernel.git/commitdiff
netfilter: conntrack: fix vtag checks for ABORT/SHUTDOWN_COMPLETE
authorSriram Yagnaraman <sriram.yagnaraman@est.tech>
Tue, 24 Jan 2023 01:47:18 +0000 (02:47 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Feb 2023 06:52:46 +0000 (07:52 +0100)
[ Upstream commit a9993591fa94246b16b444eea55d84c54608282a ]

RFC 9260, Sec 8.5.1 states that for ABORT/SHUTDOWN_COMPLETE, the chunk
MUST be accepted if the vtag of the packet matches its own tag and the
T bit is not set OR if it is set to its peer's vtag and the T bit is set
in chunk flags. Otherwise the packet MUST be silently dropped.

Update vtag verification for ABORT/SHUTDOWN_COMPLETE based on the above
description.

Fixes: b0bbff62ec62 ("[NETFILTER]: Add nf_conntrack subsystem.")
Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/netfilter/nf_conntrack_proto_sctp.c

index 7626f3e1c70a774968676d1111ee6376284afc17..72d0aa603cd61d44151e1a595150dc3cc681e5df 100644 (file)
@@ -412,22 +412,29 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
        for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
                /* Special cases of Verification tag check (Sec 8.5.1) */
                if (sch->type == SCTP_CID_INIT) {
-                       /* Sec 8.5.1 (A) */
+                       /* (A) vtag MUST be zero */
                        if (sh->vtag != 0)
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_ABORT) {
-                       /* Sec 8.5.1 (B) */
-                       if (sh->vtag != ct->proto.sctp.vtag[dir] &&
-                           sh->vtag != ct->proto.sctp.vtag[!dir])
+                       /* (B) vtag MUST match own vtag if T flag is unset OR
+                        * MUST match peer's vtag if T flag is set
+                        */
+                       if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[dir]) ||
+                           ((sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[!dir]))
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
-                       /* Sec 8.5.1 (C) */
-                       if (sh->vtag != ct->proto.sctp.vtag[dir] &&
-                           sh->vtag != ct->proto.sctp.vtag[!dir] &&
-                           sch->flags & SCTP_CHUNK_FLAG_T)
+                       /* (C) vtag MUST match own vtag if T flag is unset OR
+                        * MUST match peer's vtag if T flag is set
+                        */
+                       if ((!(sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[dir]) ||
+                           ((sch->flags & SCTP_CHUNK_FLAG_T) &&
+                            sh->vtag != ct->proto.sctp.vtag[!dir]))
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
-                       /* Sec 8.5.1 (D) */
+                       /* (D) vtag must be same as init_vtag as found in INIT_ACK */
                        if (sh->vtag != ct->proto.sctp.vtag[dir])
                                goto out_unlock;
                } else if (sch->type == SCTP_CID_HEARTBEAT) {