2023-02-22 14:45:00

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 1/2] soundwire: qcom: define hardcoded version magic numbers

Use a define instead of hard-coded register values for Soundwire
hardware version number, because it is a bit easier to read and allows
to drop explaining comment.

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/soundwire/qcom.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index ba502129150d..79bebcecde6d 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -28,6 +28,9 @@
#define SWRM_LINK_MANAGER_EE 0x018
#define SWRM_EE_CPU 1
#define SWRM_FRM_GEN_ENABLED BIT(0)
+#define SWRM_VERSION_1_3_0 0x01030000
+#define SWRM_VERSION_1_5_1 0x01050001
+#define SWRM_VERSION_1_7_0 0x01070000
#define SWRM_COMP_HW_VERSION 0x00
#define SWRM_COMP_CFG_ADDR 0x04
#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
@@ -351,8 +354,7 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
/* Its assumed that write is okay as we do not get any status back */
swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);

- /* version 1.3 or less */
- if (swrm->version <= 0x01030000)
+ if (swrm->version <= SWRM_VERSION_1_3_0)
usleep_range(150, 155);

if (cmd_id == SWR_BROADCAST_CMD_ID) {
@@ -695,7 +697,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK);
ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);

- if (ctrl->version >= 0x01070000) {
+ if (ctrl->version >= SWRM_VERSION_1_7_0) {
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
@@ -704,8 +706,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
}

/* Configure number of retries of a read/write cmd */
- if (ctrl->version >= 0x01050001) {
- /* Only for versions >= 1.5.1 */
+ if (ctrl->version >= SWRM_VERSION_1_5_1) {
ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CFG_ADDR,
SWRM_RD_WR_CMD_RETRIES |
SWRM_CONTINUE_EXEC_ON_CMD_IGNORE);
@@ -1239,7 +1240,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
bp_mode, nports);
if (ret) {
- if (ctrl->version <= 0x01030000)
+ if (ctrl->version <= SWRM_VERSION_1_3_0)
memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
else
return ret;
@@ -1442,7 +1443,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
pm_runtime_enable(dev);

/* Clk stop is not supported on WSA Soundwire masters */
- if (ctrl->version <= 0x01030000) {
+ if (ctrl->version <= SWRM_VERSION_1_3_0) {
ctrl->clock_stop_not_supported = true;
} else {
ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val);
@@ -1527,7 +1528,7 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
} else {
reset_control_reset(ctrl->audio_cgcr);

- if (ctrl->version >= 0x01070000) {
+ if (ctrl->version >= SWRM_VERSION_1_7_0) {
ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
--
2.34.1



2023-02-22 14:45:04

by Krzysztof Kozlowski

[permalink] [raw]
Subject: [PATCH 2/2] soundwire: qcom: gracefully handle too many ports in DT

There are two issues related to the number of ports coming from
Devicetree when exceeding in total QCOM_SDW_MAX_PORTS. Both lead to
incorrect memory accesses:
1. With DTS having too big value of input or output ports, the driver,
when copying port parameters from local/stack arrays into 'pconfig'
array in 'struct qcom_swrm_ctrl', will iterate over their sizes.

2. If DTS also has too many parameters for these ports (e.g.
qcom,ports-sinterval-low), the driver will overflow buffers on the
stack when reading these properties from DTS.

Add a sanity check so incorrect DTS will not cause kernel memory
corruption.

Signed-off-by: Krzysztof Kozlowski <[email protected]>
---
drivers/soundwire/qcom.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 79bebcecde6d..c296e0bf897b 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1218,6 +1218,9 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
ctrl->num_dout_ports = val;

nports = ctrl->num_dout_ports + ctrl->num_din_ports;
+ if (nports > QCOM_SDW_MAX_PORTS)
+ return -EINVAL;
+
/* Valid port numbers are from 1-14, so mask out port 0 explicitly */
set_bit(0, &ctrl->dout_port_mask);
set_bit(0, &ctrl->din_port_mask);
--
2.34.1


2023-02-22 14:46:02

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH 1/2] soundwire: qcom: define hardcoded version magic numbers



On 22.02.2023 15:44, Krzysztof Kozlowski wrote:
> Use a define instead of hard-coded register values for Soundwire
> hardware version number, because it is a bit easier to read and allows
> to drop explaining comment.
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>
> ---
Reviewed-by: Konrad Dybcio <[email protected]>

Konrad
> drivers/soundwire/qcom.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
> index ba502129150d..79bebcecde6d 100644
> --- a/drivers/soundwire/qcom.c
> +++ b/drivers/soundwire/qcom.c
> @@ -28,6 +28,9 @@
> #define SWRM_LINK_MANAGER_EE 0x018
> #define SWRM_EE_CPU 1
> #define SWRM_FRM_GEN_ENABLED BIT(0)
> +#define SWRM_VERSION_1_3_0 0x01030000
> +#define SWRM_VERSION_1_5_1 0x01050001
> +#define SWRM_VERSION_1_7_0 0x01070000
> #define SWRM_COMP_HW_VERSION 0x00
> #define SWRM_COMP_CFG_ADDR 0x04
> #define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
> @@ -351,8 +354,7 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
> /* Its assumed that write is okay as we do not get any status back */
> swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
>
> - /* version 1.3 or less */
> - if (swrm->version <= 0x01030000)
> + if (swrm->version <= SWRM_VERSION_1_3_0)
> usleep_range(150, 155);
>
> if (cmd_id == SWR_BROADCAST_CMD_ID) {
> @@ -695,7 +697,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
> u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK);
> ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);
>
> - if (ctrl->version >= 0x01070000) {
> + if (ctrl->version >= SWRM_VERSION_1_7_0) {
> ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
> ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
> SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
> @@ -704,8 +706,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
> }
>
> /* Configure number of retries of a read/write cmd */
> - if (ctrl->version >= 0x01050001) {
> - /* Only for versions >= 1.5.1 */
> + if (ctrl->version >= SWRM_VERSION_1_5_1) {
> ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CFG_ADDR,
> SWRM_RD_WR_CMD_RETRIES |
> SWRM_CONTINUE_EXEC_ON_CMD_IGNORE);
> @@ -1239,7 +1240,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
> ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
> bp_mode, nports);
> if (ret) {
> - if (ctrl->version <= 0x01030000)
> + if (ctrl->version <= SWRM_VERSION_1_3_0)
> memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
> else
> return ret;
> @@ -1442,7 +1443,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
> pm_runtime_enable(dev);
>
> /* Clk stop is not supported on WSA Soundwire masters */
> - if (ctrl->version <= 0x01030000) {
> + if (ctrl->version <= SWRM_VERSION_1_3_0) {
> ctrl->clock_stop_not_supported = true;
> } else {
> ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val);
> @@ -1527,7 +1528,7 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
> } else {
> reset_control_reset(ctrl->audio_cgcr);
>
> - if (ctrl->version >= 0x01070000) {
> + if (ctrl->version >= SWRM_VERSION_1_7_0) {
> ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
> ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
> SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);

2023-02-22 14:48:19

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH 2/2] soundwire: qcom: gracefully handle too many ports in DT



On 22.02.2023 15:44, Krzysztof Kozlowski wrote:
> There are two issues related to the number of ports coming from
> Devicetree when exceeding in total QCOM_SDW_MAX_PORTS. Both lead to
> incorrect memory accesses:
> 1. With DTS having too big value of input or output ports, the driver,
> when copying port parameters from local/stack arrays into 'pconfig'
> array in 'struct qcom_swrm_ctrl', will iterate over their sizes.
>
> 2. If DTS also has too many parameters for these ports (e.g.
> qcom,ports-sinterval-low), the driver will overflow buffers on the
> stack when reading these properties from DTS.
>
> Add a sanity check so incorrect DTS will not cause kernel memory
> corruption.
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>
> ---
Fixes: 02efb49aa805 ("soundwire: qcom: add support for SoundWire controller")

Reviewed-by: Konrad Dybcio <[email protected]>

Konrad
> drivers/soundwire/qcom.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
> index 79bebcecde6d..c296e0bf897b 100644
> --- a/drivers/soundwire/qcom.c
> +++ b/drivers/soundwire/qcom.c
> @@ -1218,6 +1218,9 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
> ctrl->num_dout_ports = val;
>
> nports = ctrl->num_dout_ports + ctrl->num_din_ports;
> + if (nports > QCOM_SDW_MAX_PORTS)
> + return -EINVAL;
> +
> /* Valid port numbers are from 1-14, so mask out port 0 explicitly */
> set_bit(0, &ctrl->dout_port_mask);
> set_bit(0, &ctrl->din_port_mask);

2023-02-22 14:51:23

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH 2/2] soundwire: qcom: gracefully handle too many ports in DT

On 22/02/2023 15:47, Konrad Dybcio wrote:
>
>
> On 22.02.2023 15:44, Krzysztof Kozlowski wrote:
>> There are two issues related to the number of ports coming from
>> Devicetree when exceeding in total QCOM_SDW_MAX_PORTS. Both lead to
>> incorrect memory accesses:
>> 1. With DTS having too big value of input or output ports, the driver,
>> when copying port parameters from local/stack arrays into 'pconfig'
>> array in 'struct qcom_swrm_ctrl', will iterate over their sizes.
>>
>> 2. If DTS also has too many parameters for these ports (e.g.
>> qcom,ports-sinterval-low), the driver will overflow buffers on the
>> stack when reading these properties from DTS.
>>
>> Add a sanity check so incorrect DTS will not cause kernel memory
>> corruption.
>>
>> Signed-off-by: Krzysztof Kozlowski <[email protected]>
>> ---
> Fixes: 02efb49aa805 ("soundwire: qcom: add support for SoundWire controller")

Can be... but is it really a bug of the kernel? Issue is visible with
incorrect DTS and it's not the kernel's job to fix it. If DTS has
incorrect values (e.g. IO addresses) system won't work anyway and that's
the same type of bug.

Best regards,
Krzysztof


2023-02-22 14:53:48

by Konrad Dybcio

[permalink] [raw]
Subject: Re: [PATCH 2/2] soundwire: qcom: gracefully handle too many ports in DT



On 22.02.2023 15:50, Krzysztof Kozlowski wrote:
> On 22/02/2023 15:47, Konrad Dybcio wrote:
>>
>>
>> On 22.02.2023 15:44, Krzysztof Kozlowski wrote:
>>> There are two issues related to the number of ports coming from
>>> Devicetree when exceeding in total QCOM_SDW_MAX_PORTS. Both lead to
>>> incorrect memory accesses:
>>> 1. With DTS having too big value of input or output ports, the driver,
>>> when copying port parameters from local/stack arrays into 'pconfig'
>>> array in 'struct qcom_swrm_ctrl', will iterate over their sizes.
>>>
>>> 2. If DTS also has too many parameters for these ports (e.g.
>>> qcom,ports-sinterval-low), the driver will overflow buffers on the
>>> stack when reading these properties from DTS.
>>>
>>> Add a sanity check so incorrect DTS will not cause kernel memory
>>> corruption.
>>>
>>> Signed-off-by: Krzysztof Kozlowski <[email protected]>
>>> ---
>> Fixes: 02efb49aa805 ("soundwire: qcom: add support for SoundWire controller")
>
> Can be... but is it really a bug of the kernel? Issue is visible with
> incorrect DTS and it's not the kernel's job to fix it. If DTS has
> incorrect values (e.g. IO addresses) system won't work anyway and that's
> the same type of bug.
I'm not sure to what extent the kernel should be responsible for
checking DT sanity, but in case of a buffer overflow, I really
think it definitely deserves a fixes tag.

Konrad

>
> Best regards,
> Krzysztof
>

2023-03-15 13:55:53

by Srinivas Kandagatla

[permalink] [raw]
Subject: Re: [PATCH 1/2] soundwire: qcom: define hardcoded version magic numbers



On 22/02/2023 14:44, Krzysztof Kozlowski wrote:
> Use a define instead of hard-coded register values for Soundwire
> hardware version number, because it is a bit easier to read and allows
> to drop explaining comment.
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>
> ---

Thanks Krzysztof,

Reviewed-by: Srinivas Kandagatla <[email protected]>


--srini

> drivers/soundwire/qcom.c | 17 +++++++++--------
> 1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
> index ba502129150d..79bebcecde6d 100644
> --- a/drivers/soundwire/qcom.c
> +++ b/drivers/soundwire/qcom.c
> @@ -28,6 +28,9 @@
> #define SWRM_LINK_MANAGER_EE 0x018
> #define SWRM_EE_CPU 1
> #define SWRM_FRM_GEN_ENABLED BIT(0)
> +#define SWRM_VERSION_1_3_0 0x01030000
> +#define SWRM_VERSION_1_5_1 0x01050001
> +#define SWRM_VERSION_1_7_0 0x01070000
> #define SWRM_COMP_HW_VERSION 0x00
> #define SWRM_COMP_CFG_ADDR 0x04
> #define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
> @@ -351,8 +354,7 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *swrm, u8 cmd_data,
> /* Its assumed that write is okay as we do not get any status back */
> swrm->reg_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
>
> - /* version 1.3 or less */
> - if (swrm->version <= 0x01030000)
> + if (swrm->version <= SWRM_VERSION_1_3_0)
> usleep_range(150, 155);
>
> if (cmd_id == SWR_BROADCAST_CMD_ID) {
> @@ -695,7 +697,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
> u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK);
> ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);
>
> - if (ctrl->version >= 0x01070000) {
> + if (ctrl->version >= SWRM_VERSION_1_7_0) {
> ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
> ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
> SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
> @@ -704,8 +706,7 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
> }
>
> /* Configure number of retries of a read/write cmd */
> - if (ctrl->version >= 0x01050001) {
> - /* Only for versions >= 1.5.1 */
> + if (ctrl->version >= SWRM_VERSION_1_5_1) {
> ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CFG_ADDR,
> SWRM_RD_WR_CMD_RETRIES |
> SWRM_CONTINUE_EXEC_ON_CMD_IGNORE);
> @@ -1239,7 +1240,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
> ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
> bp_mode, nports);
> if (ret) {
> - if (ctrl->version <= 0x01030000)
> + if (ctrl->version <= SWRM_VERSION_1_3_0)
> memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
> else
> return ret;
> @@ -1442,7 +1443,7 @@ static int qcom_swrm_probe(struct platform_device *pdev)
> pm_runtime_enable(dev);
>
> /* Clk stop is not supported on WSA Soundwire masters */
> - if (ctrl->version <= 0x01030000) {
> + if (ctrl->version <= SWRM_VERSION_1_3_0) {
> ctrl->clock_stop_not_supported = true;
> } else {
> ctrl->reg_read(ctrl, SWRM_COMP_MASTER_ID, &val);
> @@ -1527,7 +1528,7 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
> } else {
> reset_control_reset(ctrl->audio_cgcr);
>
> - if (ctrl->version >= 0x01070000) {
> + if (ctrl->version >= SWRM_VERSION_1_7_0) {
> ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
> ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
> SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);

2023-03-15 13:56:05

by Srinivas Kandagatla

[permalink] [raw]
Subject: Re: [PATCH 2/2] soundwire: qcom: gracefully handle too many ports in DT



On 22/02/2023 14:44, Krzysztof Kozlowski wrote:
> There are two issues related to the number of ports coming from
> Devicetree when exceeding in total QCOM_SDW_MAX_PORTS. Both lead to
> incorrect memory accesses:
> 1. With DTS having too big value of input or output ports, the driver,
> when copying port parameters from local/stack arrays into 'pconfig'
> array in 'struct qcom_swrm_ctrl', will iterate over their sizes.
>
> 2. If DTS also has too many parameters for these ports (e.g.
> qcom,ports-sinterval-low), the driver will overflow buffers on the
> stack when reading these properties from DTS.
>
> Add a sanity check so incorrect DTS will not cause kernel memory
> corruption.
>
> Signed-off-by: Krzysztof Kozlowski <[email protected]>
> ---


Thanks Krzysztof, it make sense.

Reviewed-by: Srinivas Kandagatla <[email protected]>


--srini
> drivers/soundwire/qcom.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
> index 79bebcecde6d..c296e0bf897b 100644
> --- a/drivers/soundwire/qcom.c
> +++ b/drivers/soundwire/qcom.c
> @@ -1218,6 +1218,9 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
> ctrl->num_dout_ports = val;
>
> nports = ctrl->num_dout_ports + ctrl->num_din_ports;
> + if (nports > QCOM_SDW_MAX_PORTS)
> + return -EINVAL;
> +
> /* Valid port numbers are from 1-14, so mask out port 0 explicitly */
> set_bit(0, &ctrl->dout_port_mask);
> set_bit(0, &ctrl->din_port_mask);

2023-03-15 14:15:08

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH 1/2] soundwire: qcom: define hardcoded version magic numbers

On 22-02-23, 15:44, Krzysztof Kozlowski wrote:
> Use a define instead of hard-coded register values for Soundwire
> hardware version number, because it is a bit easier to read and allows
> to drop explaining comment.

Applied both, thanks

--
~Vinod