diff mbox

[net-next] qed: Prevent stack corruption on MFW interaction

Message ID 1478445147-23163-1-git-send-email-Yuval.Mintz@cavium.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Mintz, Yuval Nov. 6, 2016, 3:12 p.m. UTC
Driver uses a union for copying data to & from management firmware
when interacting with it.
Problem is that the function always copies sizeof(union) while commit
2edbff8dcb5d ("qed: Learn resources from management firmware") is casting
a union elements which is of smaller size [24-byte instead of 88-bytes].

Also, the union contains some inappropriate elements which increase its
size [should have been 32-bytes]. While this shouldn't corrupt other
PF messages to the MFW [as management firmware enforces permissions so
that each PF is allowed to write only to its own mailbox] we fix this
here as well.

Fixes: 2edbff8dcb5d ("qed: Learn resources from management firmware")
Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
---
Hi Dave,

This fix is intended for `net-next' [as its fixing a patch not
yet in `net'].

Thanks,
Yuval
---
 drivers/net/ethernet/qlogic/qed/qed_hsi.h |  1 -
 drivers/net/ethernet/qlogic/qed/qed_mcp.c | 16 ++++++++++++----
 2 files changed, 12 insertions(+), 5 deletions(-)

Comments

David Laight Nov. 7, 2016, 12:17 p.m. UTC | #1
From: Yuval Mintz
> Sent: 06 November 2016 15:12
 
> Driver uses a union for copying data to & from management firmware
> when interacting with it.
> Problem is that the function always copies sizeof(union) while commit
> 2edbff8dcb5d ("qed: Learn resources from management firmware") is casting
> a union elements which is of smaller size [24-byte instead of 88-bytes].
> 
> Also, the union contains some inappropriate elements which increase its
> size [should have been 32-bytes]. While this shouldn't corrupt other
> PF messages to the MFW [as management firmware enforces permissions so
> that each PF is allowed to write only to its own mailbox] we fix this
> here as well.
...

Is it worth adding a compile-time assert on the size of the union?

	David
Mintz, Yuval Nov. 7, 2016, 12:25 p.m. UTC | #2
> > Driver uses a union for copying data to & from management firmware
> > when interacting with it.
> > Problem is that the function always copies sizeof(union) while commit
> > 2edbff8dcb5d ("qed: Learn resources from management firmware") is
> > casting a union elements which is of smaller size [24-byte instead of 88-bytes].
> >
> > Also, the union contains some inappropriate elements which increase
> > its size [should have been 32-bytes]. While this shouldn't corrupt
> > other PF messages to the MFW [as management firmware enforces
> > permissions so that each PF is allowed to write only to its own
> > mailbox] we fix this here as well.
> ...
> 
> Is it worth adding a compile-time assert on the size of the union?
> 
> 	David

I don't think so; The MFW team defines the elements and already enforces that.

It was simply a slip in my initial submission, where I omitted some
stuff that was already part of their HSI and wasn't required for that
submission, and missed the fact it was a union and not a struct
[hence uniting the removed fields to retain 'correct offsets' of fields].
David Miller Nov. 9, 2016, 6:27 p.m. UTC | #3
From: Yuval Mintz <Yuval.Mintz@cavium.com>
Date: Sun, 6 Nov 2016 17:12:27 +0200

> Driver uses a union for copying data to & from management firmware
> when interacting with it.
> Problem is that the function always copies sizeof(union) while commit
> 2edbff8dcb5d ("qed: Learn resources from management firmware") is casting
> a union elements which is of smaller size [24-byte instead of 88-bytes].
> 
> Also, the union contains some inappropriate elements which increase its
> size [should have been 32-bytes]. While this shouldn't corrupt other
> PF messages to the MFW [as management firmware enforces permissions so
> that each PF is allowed to write only to its own mailbox] we fix this
> here as well.
> 
> Fixes: 2edbff8dcb5d ("qed: Learn resources from management firmware")
> Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>

Applied.
diff mbox

Patch

diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 048f9a3..f5a4ebb 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -8581,7 +8581,6 @@  struct resource_info {
 	struct drv_version_stc drv_version;
 
 	struct lan_stats_stc lan_stats;
-	u64 reserved_stats[11];
 	struct ocbb_data_stc ocbb_info;
 	struct temperature_status_stc temp_info;
 	struct resource_info resource;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index d8e499e..6dd3ce4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1697,19 +1697,27 @@  int qed_mcp_get_resc_info(struct qed_hwfn *p_hwfn,
 			  u32 *p_mcp_resp, u32 *p_mcp_param)
 {
 	struct qed_mcp_mb_params mb_params;
-	union drv_union_data *p_union_data;
+	union drv_union_data union_data;
 	int rc;
 
 	memset(&mb_params, 0, sizeof(mb_params));
+	memset(&union_data, 0, sizeof(union_data));
 	mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
 	mb_params.param = QED_RESC_ALLOC_VERSION;
-	p_union_data = (union drv_union_data *)p_resc_info;
-	mb_params.p_data_src = p_union_data;
-	mb_params.p_data_dst = p_union_data;
+
+	/* Need to have a sufficient large struct, as the cmd_and_union
+	 * is going to do memcpy from and to it.
+	 */
+	memcpy(&union_data.resource, p_resc_info, sizeof(*p_resc_info));
+
+	mb_params.p_data_src = &union_data;
+	mb_params.p_data_dst = &union_data;
 	rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
 	if (rc)
 		return rc;
 
+	/* Copy the data back */
+	memcpy(p_resc_info, &union_data.resource, sizeof(*p_resc_info));
 	*p_mcp_resp = mb_params.mcp_resp;
 	*p_mcp_param = mb_params.mcp_param;