Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Aug 2023 10:10:12 GMT
From:      Zhenlei Huang <zlei@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 96c4b704ec16 - stable/13 - net: Do not overwrite if_vlan's PCP
Message-ID:  <202308301010.37UAACGk021430@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by zlei:

URL: https://cgit.FreeBSD.org/src/commit/?id=96c4b704ec169044aa98867965e046a4728bcba1

commit 96c4b704ec169044aa98867965e046a4728bcba1
Author:     Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2023-08-23 09:48:12 +0000
Commit:     Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2023-08-30 10:09:25 +0000

    net: Do not overwrite if_vlan's PCP
    
    In commit c7cffd65c5d8 the function ether_8021q_frame() was slightly
    refactored to use pointer of struct ether_8021q_tag as parameter qtag to
    include the new option proto.
    
    It is wrong to write to qtag->pcp as it will effectively change the memory
    that qtag points to. Unfortunately the transmit routine of if_vlan parses
    pointer of the member ifv_qtag of its softc which stores vlan interface's
    PCP internally, when transmitting mbufs that contains PCP the vlan
    interface's PCP will get overwritten.
    
    Fix by operating on a local copy of qtag->pcp. Also mark 'struct ether_8021q_tag'
    as const so that compilers can pick up such kind of bug.
    
    PR:     273304
    Reviewed by:    kp
    Fixes:  c7cffd65c5d85 Add support for stacked VLANs (IEEE 802.1ad, AKA Q-in-Q)
    MFC after:      3 days
    Differential Revision:  https://reviews.freebsd.org/D39505
    
    (cherry picked from commit 838c8c47860a0203130bd558d507a0565a2eba8f)
---
 sys/net/ethernet.h     | 2 +-
 sys/net/if_ethersubr.c | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h
index b935c024541c..7a763c15ff26 100644
--- a/sys/net/ethernet.h
+++ b/sys/net/ethernet.h
@@ -448,7 +448,7 @@ void	ether_vlan_mtap(struct bpf_if *, struct mbuf *,
 	    void *, u_int);
 struct mbuf  *ether_vlanencap_proto(struct mbuf *, uint16_t, uint16_t);
 bool	ether_8021q_frame(struct mbuf **mp, struct ifnet *ife,
-		struct ifnet *p, struct ether_8021q_tag *);
+		struct ifnet *p, const struct ether_8021q_tag *);
 void	ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr);
 
 static __inline struct mbuf *ether_vlanencap(struct mbuf *m, uint16_t tag)
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 64cca2452871..87faf9f26df4 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1355,11 +1355,12 @@ SYSCTL_INT(_net_link_vlan, OID_AUTO, mtag_pcp, CTLFLAG_RW,
 
 bool
 ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
-    struct ether_8021q_tag *qtag)
+    const struct ether_8021q_tag *qtag)
 {
 	struct m_tag *mtag;
 	int n;
 	uint16_t tag;
+	uint8_t pcp = qtag->pcp;
 	static const char pad[8];	/* just zeros */
 
 	/*
@@ -1392,7 +1393,7 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
 	 * If PCP is set in mbuf, use it
 	 */
 	if ((*mp)->m_flags & M_VLANTAG) {
-		qtag->pcp = EVL_PRIOFTAG((*mp)->m_pkthdr.ether_vtag);
+		pcp = EVL_PRIOFTAG((*mp)->m_pkthdr.ether_vtag);
 	}
 
 	/*
@@ -1406,7 +1407,7 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p,
 	    MTAG_8021Q_PCP_OUT, NULL)) != NULL)
 		tag = EVL_MAKETAG(qtag->vid, *(uint8_t *)(mtag + 1), 0);
 	else
-		tag = EVL_MAKETAG(qtag->vid, qtag->pcp, 0);
+		tag = EVL_MAKETAG(qtag->vid, pcp, 0);
 	if ((p->if_capenable & IFCAP_VLAN_HWTAGGING) &&
 	    (qtag->proto == ETHERTYPE_VLAN)) {
 		(*mp)->m_pkthdr.ether_vtag = tag;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202308301010.37UAACGk021430>