From bb48024284327768debd03a197d7c4179ec6ca05 Mon Sep 17 00:00:00 2001 From: "Mintz, Yuval" Date: Sun, 6 Nov 2016 17:12:27 +0200 Subject: qed: Prevent stack corruption on MFW interaction 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 Signed-off-by: David S. Miller --- 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(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 048f9a342413..f5a4ebb3963f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -8581,7 +8581,6 @@ union drv_union_data { 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 d8e499ebb99d..6dd3ce443484 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; -- cgit v1.2.3