2022-05-22 15:59:21

by Pavel Skripkin

[permalink] [raw]
Subject: [PATCH v2 0/4] staging: r8188eu: add error handling of usb read errors

Hi,

it's reincarnation of my old series for adding sane error handling in
r8818eu.

*Problem*

Old code was returning just stack variable in case of read error. It's
not the best approach, since passing around stack data might cause
device misconfiguration or even kernel data leakage

To solve this I've changed rtw_read{8,16,32} prototypes to return an error via
return value and data via passed pointer. Some work should be done to
propogate an error down to calltrace, but it's good way to at least
start doing sane I/O error handling

Tested locally on qemu with TP-Link TL-WN722N v2/v3 [Realtek RTL8188EUS]
device. More testing is welcomed, of course :)

_NOTE_
Series is based on top of staging-testing branch and should be
applied after Dan's patch https://lore.kernel.org/linux-staging/YoXS4OaD1oauPvmj@kili/


Changes since v1:
addresses issues found by Dan and self review. Mostly related to returning
_FAIL instead of -errno, since callers expect _FAIL/_SUCCESS

v1: https://lore.kernel.org/linux-staging/[email protected]/


Pavel Skripkin (4):
staging: r8188eu: add error handling of rtw_read8
staging: r8188eu: add error handling of rtw_read16
staging: r8188eu: add error handling of rtw_read32
MAINTAINERS: add myself as r8188eu reviewer

MAINTAINERS | 1 +
drivers/staging/r8188eu/core/rtw_cmd.c | 15 +-
drivers/staging/r8188eu/core/rtw_efuse.c | 33 ++-
drivers/staging/r8188eu/core/rtw_fw.c | 72 ++++--
drivers/staging/r8188eu/core/rtw_led.c | 16 +-
drivers/staging/r8188eu/core/rtw_mlme_ext.c | 62 ++++-
drivers/staging/r8188eu/core/rtw_pwrctrl.c | 9 +-
drivers/staging/r8188eu/core/rtw_wlan_util.c | 20 +-
.../r8188eu/hal/Hal8188ERateAdaptive.c | 21 +-
drivers/staging/r8188eu/hal/HalPhyRf_8188e.c | 21 +-
drivers/staging/r8188eu/hal/HalPwrSeqCmd.c | 9 +-
drivers/staging/r8188eu/hal/hal_com.c | 27 +-
drivers/staging/r8188eu/hal/rtl8188e_cmd.c | 37 ++-
drivers/staging/r8188eu/hal/rtl8188e_dm.c | 6 +-
.../staging/r8188eu/hal/rtl8188e_hal_init.c | 130 +++++++---
drivers/staging/r8188eu/hal/rtl8188e_phycfg.c | 30 ++-
drivers/staging/r8188eu/hal/usb_halinit.c | 240 +++++++++++++++---
drivers/staging/r8188eu/hal/usb_ops_linux.c | 33 ++-
drivers/staging/r8188eu/include/rtw_io.h | 6 +-
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 47 +++-
drivers/staging/r8188eu/os_dep/os_intfs.c | 19 +-
21 files changed, 679 insertions(+), 175 deletions(-)

--
2.36.1



2022-05-23 06:09:13

by Pavel Skripkin

[permalink] [raw]
Subject: [PATCH v2 2/4] staging: r8188eu: add error handling of rtw_read16

rtw_read16() reads data from device via USB API which may fail. In case
of any failure previous code returned stack data to callers, which is
wrong.

Fix it by changing rtw_read16() prototype and prevent caller from
touching random stack data

Signed-off-by: Pavel Skripkin <[email protected]>
---

Changes since v1:
- Fixed style issue

---
.../staging/r8188eu/hal/rtl8188e_hal_init.c | 21 ++++++++++++---
drivers/staging/r8188eu/hal/rtl8188e_phycfg.c | 8 ++++--
drivers/staging/r8188eu/hal/usb_halinit.c | 27 ++++++++++++++++---
drivers/staging/r8188eu/hal/usb_ops_linux.c | 13 ++++++---
drivers/staging/r8188eu/include/rtw_io.h | 2 +-
drivers/staging/r8188eu/os_dep/ioctl_linux.c | 9 ++++---
drivers/staging/r8188eu/os_dep/os_intfs.c | 6 ++++-
7 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
index e67ecbd1ba79..6662ebc30f7b 100644
--- a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
@@ -249,11 +249,14 @@ static void efuse_read_phymap_from_txpktbuf(
hi32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H));

if (i == 0) {
+ u16 reg;
+
/* Although lenc is only used in a debug statement,
* do not remove it as the rtw_read16() call consumes
* 2 bytes from the EEPROM source.
*/
- rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
+ res = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, &reg);
+ (void)res;

len = le32_to_cpu(lo32) & 0x0000ffff;

@@ -355,25 +358,35 @@ int rtl8188e_IOL_exec_cmds_sync(struct adapter *adapter, struct xmit_frame *xmit
void rtl8188e_EfusePowerSwitch(struct adapter *pAdapter, u8 PwrState)
{
u16 tmpV16;
+ int res;

if (PwrState) {
rtw_write8(pAdapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);

/* 1.2V Power: From VDDON with Power Cut(0x0000h[15]), defualt valid */
- tmpV16 = rtw_read16(pAdapter, REG_SYS_ISO_CTRL);
+ res = rtw_read16(pAdapter, REG_SYS_ISO_CTRL, &tmpV16);
+ if (res)
+ return;
+
if (!(tmpV16 & PWC_EV12V)) {
tmpV16 |= PWC_EV12V;
rtw_write16(pAdapter, REG_SYS_ISO_CTRL, tmpV16);
}
/* Reset: 0x0000h[28], default valid */
- tmpV16 = rtw_read16(pAdapter, REG_SYS_FUNC_EN);
+ res = rtw_read16(pAdapter, REG_SYS_FUNC_EN, &tmpV16);
+ if (res)
+ return;
+
if (!(tmpV16 & FEN_ELDR)) {
tmpV16 |= FEN_ELDR;
rtw_write16(pAdapter, REG_SYS_FUNC_EN, tmpV16);
}

/* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
- tmpV16 = rtw_read16(pAdapter, REG_SYS_CLKR);
+ res = rtw_read16(pAdapter, REG_SYS_CLKR, &tmpV16);
+ if (res)
+ return;
+
if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
tmpV16 |= (LOADER_CLK_EN | ANA8M);
rtw_write16(pAdapter, REG_SYS_CLKR, tmpV16);
diff --git a/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c b/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c
index 985339a974fc..298c3d9bc7be 100644
--- a/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c
+++ b/drivers/staging/r8188eu/hal/rtl8188e_phycfg.c
@@ -484,13 +484,17 @@ PHY_BBConfig8188E(
{
int rtStatus = _SUCCESS;
struct hal_data_8188e *pHalData = &Adapter->haldata;
- u32 RegVal;
+ u16 RegVal;
u8 CrystalCap;
+ int res;

phy_InitBBRFRegisterDefinition(Adapter);

/* Enable BB and RF */
- RegVal = rtw_read16(Adapter, REG_SYS_FUNC_EN);
+ res = rtw_read16(Adapter, REG_SYS_FUNC_EN, &RegVal);
+ if (res)
+ return _FAIL;
+
rtw_write16(Adapter, REG_SYS_FUNC_EN, (u16)(RegVal | BIT(13) | BIT(0) | BIT(1)));

/* 20090923 Joseph: Advised by Steven and Jenyu. Power sequence before init RF. */
diff --git a/drivers/staging/r8188eu/hal/usb_halinit.c b/drivers/staging/r8188eu/hal/usb_halinit.c
index 5daef0117a5c..40d907dd2b58 100644
--- a/drivers/staging/r8188eu/hal/usb_halinit.c
+++ b/drivers/staging/r8188eu/hal/usb_halinit.c
@@ -52,6 +52,8 @@ void rtl8188eu_interface_configure(struct adapter *adapt)
u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
{
u16 value16;
+ int res;
+
/* HW Power on sequence */
struct hal_data_8188e *haldata = &adapt->haldata;
if (haldata->bMacPwrCtrlOn)
@@ -65,7 +67,10 @@ u32 rtl8188eu_InitPowerOn(struct adapter *adapt)
rtw_write16(adapt, REG_CR, 0x00); /* suggseted by zhouzhou, by page, 20111230 */

/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
- value16 = rtw_read16(adapt, REG_CR);
+ res = rtw_read16(adapt, REG_CR, &value16);
+ if (res)
+ return _FAIL;
+
value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN
| PROTOCOL_EN | SCHEDULE_EN | ENSEC | CALTMR_EN);
/* for SDIO - Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy. Added by tynli. 2011.08.31. */
@@ -166,7 +171,14 @@ static void _InitNormalChipRegPriority(struct adapter *Adapter, u16 beQ,
u16 bkQ, u16 viQ, u16 voQ, u16 mgtQ,
u16 hiQ)
{
- u16 value16 = (rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7);
+ u16 value16;
+ int res;
+
+ res = rtw_read16(Adapter, REG_TRXDMA_CTRL, &value16);
+ if (res)
+ return;
+
+ value16 &= 0x7;

value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
_TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
@@ -631,7 +643,10 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter)
/* Hw bug which Hw initials RxFF boundary size to a value which is larger than the real Rx buffer size in 88E. */
/* */
/* Enable MACTXEN/MACRXEN block */
- value16 = rtw_read16(Adapter, REG_CR);
+ res = rtw_read16(Adapter, REG_CR, &value16);
+ if (res)
+ return _FAIL;
+
value16 |= (MACTXEN | MACRXEN);
rtw_write8(Adapter, REG_CR, value16);

@@ -704,7 +719,11 @@ u32 rtl8188eu_hal_init(struct adapter *Adapter)
rtw_write16(Adapter, REG_TX_RPT_TIME, 0x3DF0);

/* enable tx DMA to drop the redundate data of packet */
- rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK) | DROP_DATA_EN));
+ res = rtw_read16(Adapter, REG_TXDMA_OFFSET_CHK, &value16);
+ if (res)
+ return _FAIL;
+
+ rtw_write16(Adapter, REG_TXDMA_OFFSET_CHK, (value16 | DROP_DATA_EN));

/* 2010/08/26 MH Merge from 8192CE. */
if (pwrctrlpriv->rf_pwrstate == rf_on) {
diff --git a/drivers/staging/r8188eu/hal/usb_ops_linux.c b/drivers/staging/r8188eu/hal/usb_ops_linux.c
index f399a7fd8b97..7d62f1f3d26e 100644
--- a/drivers/staging/r8188eu/hal/usb_ops_linux.c
+++ b/drivers/staging/r8188eu/hal/usb_ops_linux.c
@@ -103,16 +103,21 @@ int __must_check rtw_read8(struct adapter *adapter, u32 addr, u8 *data)
return usb_read(intf, value, data, 1);
}

-u16 rtw_read16(struct adapter *adapter, u32 addr)
+int __must_check rtw_read16(struct adapter *adapter, u32 addr, u16 *data)
{
struct io_priv *io_priv = &adapter->iopriv;
struct intf_hdl *intf = &io_priv->intf;
u16 value = addr & 0xffff;
- __le16 data;
+ __le16 le_data;
+ int res;

- usb_read(intf, value, &data, 2);
+ res = usb_read(intf, value, &le_data, 2);
+ if (res)
+ return res;

- return le16_to_cpu(data);
+ *data = le16_to_cpu(le_data);
+
+ return 0;
}

u32 rtw_read32(struct adapter *adapter, u32 addr)
diff --git a/drivers/staging/r8188eu/include/rtw_io.h b/drivers/staging/r8188eu/include/rtw_io.h
index 1198d3850a6d..ce3369e33d66 100644
--- a/drivers/staging/r8188eu/include/rtw_io.h
+++ b/drivers/staging/r8188eu/include/rtw_io.h
@@ -221,7 +221,7 @@ void _rtw_attrib_read(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
void _rtw_attrib_write(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);

int __must_check rtw_read8(struct adapter *adapter, u32 addr, u8 *data);
-u16 rtw_read16(struct adapter *adapter, u32 addr);
+int __must_check rtw_read16(struct adapter *adapter, u32 addr, u16 *data);
u32 rtw_read32(struct adapter *adapter, u32 addr);
void _rtw_read_mem(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
u32 rtw_read_port(struct adapter *adapter, u8 *pmem);
diff --git a/drivers/staging/r8188eu/os_dep/ioctl_linux.c b/drivers/staging/r8188eu/os_dep/ioctl_linux.c
index 6e5ee2a74ee4..6ed1439b940c 100644
--- a/drivers/staging/r8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/r8188eu/os_dep/ioctl_linux.c
@@ -3348,6 +3348,7 @@ static int rtw_dbg_port(struct net_device *dev,

/* FIXME: is this read necessary? */
res = rtw_read8(padapter, reg, &val8);
+ (void)res;
}
break;

@@ -3356,8 +3357,8 @@ static int rtw_dbg_port(struct net_device *dev,
u16 reg = arg;
u16 start_value = 200;
u32 write_num = extra_arg;
-
- int i;
+ u16 val16;
+ int i, res;
struct xmit_frame *xmit_frame;

xmit_frame = rtw_IOL_accquire_xmit_frame(padapter);
@@ -3371,7 +3372,9 @@ static int rtw_dbg_port(struct net_device *dev,
if (rtl8188e_IOL_exec_cmds_sync(padapter, xmit_frame, 5000, 0) != _SUCCESS)
ret = -EPERM;

- rtw_read16(padapter, reg);
+ /* FIXME: is this read necessary? */
+ res = rtw_read16(padapter, reg, &val16);
+ (void)res;
}
break;
case 0x08: /* continuous write dword test */
diff --git a/drivers/staging/r8188eu/os_dep/os_intfs.c b/drivers/staging/r8188eu/os_dep/os_intfs.c
index 891c85b088ca..d9325ef6ac28 100644
--- a/drivers/staging/r8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/r8188eu/os_dep/os_intfs.c
@@ -740,12 +740,16 @@ static void rtw_fifo_cleanup(struct adapter *adapter)
{
struct pwrctrl_priv *pwrpriv = &adapter->pwrctrlpriv;
u8 trycnt = 100;
+ int res;

/* pause tx */
rtw_write8(adapter, REG_TXPAUSE, 0xff);

/* keep sn */
- adapter->xmitpriv.nqos_ssn = rtw_read16(adapter, REG_NQOS_SEQ);
+ /* FIXME: return an error to caller */
+ res = rtw_read16(adapter, REG_NQOS_SEQ, &adapter->xmitpriv.nqos_ssn);
+ if (res)
+ return;

if (!pwrpriv->bkeepfwalive) {
/* RX DMA stop */
--
2.36.1


2022-06-06 06:37:00

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 2/4] staging: r8188eu: add error handling of rtw_read16

On Fri, May 20, 2022 at 12:09:55AM +0300, Pavel Skripkin wrote:
> rtw_read16() reads data from device via USB API which may fail. In case
> of any failure previous code returned stack data to callers, which is
> wrong.
>
> Fix it by changing rtw_read16() prototype and prevent caller from
> touching random stack data
>
> Signed-off-by: Pavel Skripkin <[email protected]>
> ---
>
> Changes since v1:
> - Fixed style issue
>
> ---
> .../staging/r8188eu/hal/rtl8188e_hal_init.c | 21 ++++++++++++---
> drivers/staging/r8188eu/hal/rtl8188e_phycfg.c | 8 ++++--
> drivers/staging/r8188eu/hal/usb_halinit.c | 27 ++++++++++++++++---
> drivers/staging/r8188eu/hal/usb_ops_linux.c | 13 ++++++---
> drivers/staging/r8188eu/include/rtw_io.h | 2 +-
> drivers/staging/r8188eu/os_dep/ioctl_linux.c | 9 ++++---
> drivers/staging/r8188eu/os_dep/os_intfs.c | 6 ++++-
> 7 files changed, 67 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
> index e67ecbd1ba79..6662ebc30f7b 100644
> --- a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
> +++ b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
> @@ -249,11 +249,14 @@ static void efuse_read_phymap_from_txpktbuf(
> hi32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H));
>
> if (i == 0) {
> + u16 reg;
> +
> /* Although lenc is only used in a debug statement,
> * do not remove it as the rtw_read16() call consumes
> * 2 bytes from the EEPROM source.
> */
> - rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
> + res = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, &reg);
> + (void)res;

Same here, that line isn't ok.

thanks,

greg k-h

2022-06-06 21:07:37

by Pavel Skripkin

[permalink] [raw]
Subject: Re: [PATCH v2 2/4] staging: r8188eu: add error handling of rtw_read16

Hi Greg,

On 6/6/22 08:48, Greg KH wrote:
>> diff --git a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
>> index e67ecbd1ba79..6662ebc30f7b 100644
>> --- a/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
>> +++ b/drivers/staging/r8188eu/hal/rtl8188e_hal_init.c
>> @@ -249,11 +249,14 @@ static void efuse_read_phymap_from_txpktbuf(
>> hi32 = cpu_to_le32(rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H));
>>
>> if (i == 0) {
>> + u16 reg;
>> +
>> /* Although lenc is only used in a debug statement,
>> * do not remove it as the rtw_read16() call consumes
>> * 2 bytes from the EEPROM source.
>> */
>> - rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L);
>> + res = rtw_read16(adapter, REG_PKTBUF_DBG_DATA_L, &reg);
>> + (void)res;
>
> Same here, that line isn't ok.
>
hm, that place is not obvious.

I guess, on-chip EEPROM acts like a FIFO, so this read must be completed
w/o any errors, so I will simply propagate an error to callers

And will place another "FIXME" for further work :)

thanks,


With regards,
Pavel Skripkin