Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Dec 2020 23:21:58 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 282381aa53a3 - main - rsu: Don't modify read-only firmware block.
Message-ID:  <202012302321.0BUNLwPo078519@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=282381aa53a3cb21de8e855797f61c27cbb73884

commit 282381aa53a3cb21de8e855797f61c27cbb73884
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2020-12-30 23:18:02 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2020-12-30 23:21:35 +0000

    rsu: Don't modify read-only firmware block.
    
    The firmware header loaded into an rsu(4) device has to be customized
    to reflect device settings.  The driver was overwriting the header
    from the shared firmware image before sending it to the device.  If
    two devices attached at the same time with different settings, one
    device could potentially get a corrupted header.  The recent changes
    in a095390344fb1795c1b118a2f84da8f6a7f254ab exposed this bug in the
    form of a panic as the firmware blobs are now marked read-only in
    object files and mapped read-only by the kernel.
    
    To avoid the bug, change the driver to allocate a copy of the firmware
    header on the stack that is initialized before writing it to the
    device.
    
    PR:             252163
    Reported by:    vidwer+fbsdbugs@gmail.com
    Tested by:      vidwer+fbsdbugs@gmail.com
    Reviewed by:    hselasky, bz, emaste
    Sponsored by:   DARPA
    Differential Revision:  https://reviews.freebsd.org/D27850
---
 sys/dev/usb/wlan/if_rsu.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 0505af9ae941..f2dc6657026e 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -3343,7 +3343,7 @@ static int
 rsu_load_firmware(struct rsu_softc *sc)
 {
 	const struct r92s_fw_hdr *hdr;
-	struct r92s_fw_priv *dmem;
+	struct r92s_fw_priv dmem;
 	struct ieee80211com *ic = &sc->sc_ic;
 	const uint8_t *imem, *emem;
 	uint32_t imemsz, ememsz;
@@ -3389,7 +3389,7 @@ rsu_load_firmware(struct rsu_softc *sc)
 	    hdr->minute);
 
 	/* Make sure that driver and firmware are in sync. */
-	if (hdr->privsz != htole32(sizeof(*dmem))) {
+	if (hdr->privsz != htole32(sizeof(dmem))) {
 		device_printf(sc->sc_dev, "unsupported firmware image\n");
 		error = EINVAL;
 		goto fail;
@@ -3475,24 +3475,23 @@ rsu_load_firmware(struct rsu_softc *sc)
 	}
 
 	/* Update DMEM section before loading. */
-	dmem = __DECONST(struct r92s_fw_priv *, &hdr->priv);
-	memset(dmem, 0, sizeof(*dmem));
-	dmem->hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
-	dmem->nendpoints = sc->sc_nendpoints;
-	dmem->chip_version = sc->cut;
-	dmem->rf_config = sc->sc_rftype;
-	dmem->vcs_type = R92S_VCS_TYPE_AUTO;
-	dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS;
-	dmem->turbo_mode = 0;
-	dmem->bw40_en = !! (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40);
-	dmem->amsdu2ampdu_en = !! (sc->sc_ht);
-	dmem->ampdu_en = !! (sc->sc_ht);
-	dmem->agg_offload = !! (sc->sc_ht);
-	dmem->qos_en = 1;
-	dmem->ps_offload = 1;
-	dmem->lowpower_mode = 1;	/* XXX TODO: configurable? */
+	memset(&dmem, 0, sizeof(dmem));
+	dmem.hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
+	dmem.nendpoints = sc->sc_nendpoints;
+	dmem.chip_version = sc->cut;
+	dmem.rf_config = sc->sc_rftype;
+	dmem.vcs_type = R92S_VCS_TYPE_AUTO;
+	dmem.vcs_mode = R92S_VCS_MODE_RTS_CTS;
+	dmem.turbo_mode = 0;
+	dmem.bw40_en = !! (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40);
+	dmem.amsdu2ampdu_en = !! (sc->sc_ht);
+	dmem.ampdu_en = !! (sc->sc_ht);
+	dmem.agg_offload = !! (sc->sc_ht);
+	dmem.qos_en = 1;
+	dmem.ps_offload = 1;
+	dmem.lowpower_mode = 1;	/* XXX TODO: configurable? */
 	/* Load DMEM section. */
-	error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
+	error = rsu_fw_loadsection(sc, (uint8_t *)&dmem, sizeof(dmem));
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "could not load firmware section %s\n", "DMEM");



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