]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Fix invalid DPIA AUX reply causing system hang
authorStylon Wang <stylon.wang@amd.com>
Wed, 26 Oct 2022 13:00:40 +0000 (21:00 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 26 Nov 2022 08:27:43 +0000 (09:27 +0100)
commit 8d8494c3467d366eb0f7c8198dab80be8bdc47d2 upstream.

[Why]
Some DPIA AUX replies have incorrect data length from original request.
This could lead to overwriting of destination buffer if reply length is
larger, which could cause invalid access to stack since many destination
buffers are declared as local variables.

[How]
Check for invalid length from DPIA AUX replies and trigger a retry if
reply length is not the same as original request. A DRM_WARN() dmesg log
is also produced.

Reviewed-by: Roman Li <Roman.Li@amd.com>
Acked-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Stylon Wang <stylon.wang@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org # 6.0.x
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h

index 54c76ed1ad751e95afa666ecb376def995e47ccf..88b49f31ac8cf3188bf0e39f7339a18f7aec37cc 100644 (file)
@@ -146,6 +146,14 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
 /* Number of bytes in PSP footer for firmware. */
 #define PSP_FOOTER_BYTES 0x100
 
+/*
+ * DMUB Async to Sync Mechanism Status
+ */
+#define DMUB_ASYNC_TO_SYNC_ACCESS_FAIL 1
+#define DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT 2
+#define DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS 3
+#define DMUB_ASYNC_TO_SYNC_ACCESS_INVALID 4
+
 /**
  * DOC: overview
  *
@@ -10149,6 +10157,8 @@ static int amdgpu_dm_set_dmub_async_sync_status(bool is_cmd_aux,
                        *operation_result = AUX_RET_ERROR_TIMEOUT;
                } else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_FAIL) {
                        *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
+               } else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_INVALID) {
+                       *operation_result = AUX_RET_ERROR_INVALID_REPLY;
                } else {
                        *operation_result = AUX_RET_ERROR_UNKNOWN;
                }
@@ -10196,6 +10206,16 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux, struct dc_context
                        payload->reply[0] = adev->dm.dmub_notify->aux_reply.command;
                        if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
                            payload->reply[0] == AUX_TRANSACTION_REPLY_AUX_ACK) {
+
+                               if (payload->length != adev->dm.dmub_notify->aux_reply.length) {
+                                       DRM_WARN("invalid read from DPIA AUX %x(%d) got length %d!\n",
+                                                       payload->address, payload->length,
+                                                       adev->dm.dmub_notify->aux_reply.length);
+                                       return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux, ctx,
+                                                       DMUB_ASYNC_TO_SYNC_ACCESS_INVALID,
+                                                       (uint32_t *)operation_result);
+                               }
+
                                memcpy(payload->data, adev->dm.dmub_notify->aux_reply.data,
                                       adev->dm.dmub_notify->aux_reply.length);
                        }
index 90b306a1dd687e0c66657981d79f3d1bb588787f..4f2228d742f441ead38486e58ca11bd36754937a 100644 (file)
 
 #define AMDGPU_DMUB_NOTIFICATION_MAX 5
 
-/*
- * DMUB Async to Sync Mechanism Status
- */
-#define DMUB_ASYNC_TO_SYNC_ACCESS_FAIL 1
-#define DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT 2
-#define DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS 3
 /*
 #include "include/amdgpu_dal_power_if.h"
 #include "amdgpu_dm_irq.h"