Re: [PATCH v2] brcmfmac: replace deprecated strncpy

From: Justin Stitt
Date: Tue Oct 17 2023 - 13:29:07 EST


On Tue, Oct 17, 2023 at 9:49 AM Franky Lin <franky.lin@xxxxxxxxxxxx> wrote:
>
> Hi Justin,
>
> On Mon, Oct 16, 2023 at 3:14 PM Justin Stitt <justinstitt@xxxxxxxxxx> wrote:
> >
> > strncpy() is deprecated for use on NUL-terminated destination strings
> > [1] and as such we should prefer more robust and less ambiguous string
> > interfaces.
> >
> > This patch replaces multiple strncpy uses. For easier reading, I'll list
> > each destination buffer and mention whether it requires either
> > NUL-termination or NUL-padding.
>
> Kudos to the detailed analysis of each instance. One thing I can think
> of to make this better is to split it into smaller patches so if any
> regression is observed, only the specific code causing it needs to be
> reverted. Maybe instance 2, 3, 4 can be handled in one patch since
> they are touching the country code in one file. The other instances
> each can be an individual patch.
>
> The "brcmfmac" in the title is not accurate. The change touches both
> brcmfmac and brcmsmac. So "brcm80211" would be more appropriate.

Got it, will send new revision with a new subject + split up patches.

>
> Thanks,
> - Franky
>
> >
> > 1) ifp->ndev->name
> >
> > We expect ifp->ndev->name to be NUL-terminated based on its use in
> > format strings within core.c:
> > 67 | char *brcmf_ifname(struct brcmf_if *ifp)
> > 68 | {
> > 69 | if (!ifp)
> > 70 | return "<if_null>";
> > 71 |
> > 72 | if (ifp->ndev)
> > 73 | return ifp->ndev->name;
> > 74 |
> > 75 | return "<if_none>";
> > 76 | }
> > ...
> > 288 | static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
> > 289 | struct net_device *ndev) {
> > ...
> > 330 | brcmf_dbg(INFO, "%s: insufficient headroom (%d)\n",
> > 331 | brcmf_ifname(ifp), head_delta);
> > ...
> > 336 | bphy_err(drvr, "%s: failed to expand headroom\n",
> > 337 | brcmf_ifname(ifp));
> >
> > In this context, a suitable replacement is `strscpy` [2] due to the fact
> > that it guarantees NUL-termination on the destination buffer without
> > unnecessarily NUL-padding.
> >
> > 2) wlc->pub->srom_ccode
> >
> > We're just copying two bytes from ccode into wlc->pub->srom_ccode with
> > no expectation that srom_ccode be NUL-terminated.
> > wlc->pub->srom_ccode is only used in regulatory_hint():
> > 1193 | if (wl->pub->srom_ccode[0] &&
> > 1194 | regulatory_hint(wl->wiphy, wl->pub->srom_ccode))
> > 1195 | wiphy_err(wl->wiphy, "%s: regulatory hint failed\n", __func__);
> >
> > We can see that only index 0 and index 1 are accessed.
> > 3307 | int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
> > 3308 | {
> > ... | ...
> > 3322 | request->alpha2[0] = alpha2[0];
> > 3323 | request->alpha2[1] = alpha2[1];
> > ... | ...
> > 3332 | }
> >
> > Since this is just a simple byte copy with correct lengths, let's use
> > memcpy(). There should be no functional change.
> >
> > 3) wlc->country_default, 4) wlc->autocountry_default
> >
> > FWICT, these two aren't used anywhere. At any rate, let's apply the same
> > reasoning as above and just use memcpy().
> >
> > 5) di->name
> >
> > We expect di->name to be NUL-terminated based on its usage with format
> > strings:
> > | brcms_dbg_dma(di->core,
> > | "%s: DMA64 tx doesn't have AE set\n",
> > | di->name);
> >
> > Looking at its allocation we can see that it is already zero-allocated
> > which means NUL-padding is not required:
> > | di = kzalloc(sizeof(struct dma_info), GFP_ATOMIC);
> >
> > 6) wlc->modulecb[i].name
> >
> > We expect each name in wlc->modulecb to be NUL-terminated based on their
> > usage with strcmp():
> > | if (!strcmp(wlc->modulecb[i].name, name) &&
> >
> > NUL-padding is not required as wlc is zero-allocated in:
> > brcms_c_attach_malloc() ->
> > | wlc = kzalloc(sizeof(struct brcms_c_info), GFP_ATOMIC);
> >
> > Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1]
> > Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2]
> > Link: https://github.com/KSPP/linux/issues/90
> > Cc: linux-hardening@xxxxxxxxxxxxxxx
> > Signed-off-by: Justin Stitt <justinstitt@xxxxxxxxxx>
> > ---
> > Changes in v2:
> > - add other strncpy replacements
> > - Link to v1: https://lore.kernel.org/r/20231016-strncpy-drivers-net-wireless-broadcom-brcm80211-brcmfmac-cfg80211-c-v1-1-4234807ca07e@xxxxxxxxxx
> > ---
> > Note: build-tested only.
> >
> > I've grouped these all into a single patch instead of a series as many
> > of the replacements are related to others and rely on context from one
> > another to justify changes.
> > ---
> > drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
> > drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +-
> > drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c | 6 +++---
> > drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c | 3 +--
> > drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c | 4 ++--
> > 5 files changed, 8 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> > index 2a90bb24ba77..7daa418df877 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> > @@ -866,7 +866,7 @@ struct wireless_dev *brcmf_apsta_add_vif(struct wiphy *wiphy, const char *name,
> > goto fail;
> > }
> >
> > - strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
> > + strscpy(ifp->ndev->name, name, sizeof(ifp->ndev->name));
> > err = brcmf_net_attach(ifp, true);
> > if (err) {
> > bphy_err(drvr, "Registering netdevice failed\n");
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
> > index d4492d02e4ea..6e0c90f4718b 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
> > @@ -2334,7 +2334,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
> > goto fail;
> > }
> >
> > - strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
> > + strscpy(ifp->ndev->name, name, sizeof(ifp->ndev->name));
> > ifp->ndev->name_assign_type = name_assign_type;
> > err = brcmf_net_attach(ifp, true);
> > if (err) {
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
> > index 5a6d9c86552a..f6962e558d7c 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
> > @@ -341,7 +341,7 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
> > /* store the country code for passing up as a regulatory hint */
> > wlc_cm->world_regd = brcms_world_regd(ccode, ccode_len);
> > if (brcms_c_country_valid(ccode))
> > - strncpy(wlc->pub->srom_ccode, ccode, ccode_len);
> > + memcpy(wlc->pub->srom_ccode, ccode, ccode_len);
> >
> > /*
> > * If no custom world domain is found in the SROM, use the
> > @@ -354,10 +354,10 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc)
> > }
> >
> > /* save default country for exiting 11d regulatory mode */
> > - strncpy(wlc->country_default, ccode, ccode_len);
> > + memcpy(wlc->country_default, ccode, ccode_len);
> >
> > /* initialize autocountry_default to driver default */
> > - strncpy(wlc->autocountry_default, ccode, ccode_len);
> > + memcpy(wlc->autocountry_default, ccode, ccode_len);
> >
> > brcms_c_set_country(wlc_cm, wlc_cm->world_regd);
> >
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
> > index b7df576bb84d..3d5c1ef8f7f2 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c
> > @@ -584,8 +584,7 @@ struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
> > rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
> >
> > /* make a private copy of our callers name */
> > - strncpy(di->name, name, MAXNAMEL);
> > - di->name[MAXNAMEL - 1] = '\0';
> > + strscpy(di->name, name, sizeof(di->name));
> >
> > di->dmadev = core->dma_dev;
> >
> > diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
> > index b3663c5ef382..34460b5815d0 100644
> > --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
> > +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
> > @@ -5551,8 +5551,8 @@ int brcms_c_module_register(struct brcms_pub *pub,
> > /* find an empty entry and just add, no duplication check! */
> > for (i = 0; i < BRCMS_MAXMODULES; i++) {
> > if (wlc->modulecb[i].name[0] == '\0') {
> > - strncpy(wlc->modulecb[i].name, name,
> > - sizeof(wlc->modulecb[i].name) - 1);
> > + strscpy(wlc->modulecb[i].name, name,
> > + sizeof(wlc->modulecb[i].name));
> > wlc->modulecb[i].hdl = hdl;
> > wlc->modulecb[i].down_fn = d_fn;
> > return 0;
> >
> > ---
> > base-commit: cbf3a2cb156a2c911d8f38d8247814b4c07f49a2
> > change-id: 20231016-strncpy-drivers-net-wireless-broadcom-brcm80211-brcmfmac-cfg80211-c-a20108421685
> >
> > Best regards,
> > --
> > Justin Stitt <justinstitt@xxxxxxxxxx>
> >

Thanks
Justin