summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMintz, Yuval <Yuval.Mintz@cavium.com>2016-11-06 17:12:27 +0200
committerDavid S. Miller <davem@davemloft.net>2016-11-09 13:27:25 -0500
commitbb48024284327768debd03a197d7c4179ec6ca05 (patch)
tree0cb38c93e295418812234bb180fdac7fc951d910
parentb12ab9b11966ee6c724e34b2f0f13ea76932b6bf (diff)
downloadlinux-bb48024284327768debd03a197d7c4179ec6ca05.tar.bz2
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 <Yuval.Mintz@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hsi.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c16
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;