From b4f069e9b26daf398f2e5d61c9660c82e9d30e62 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 1 Aug 2020 15:36:11 +0200 Subject: [PATCH] 5.4-stable patches added patches: drm-amd-display-clear-dm_state-for-fast-updates.patch drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch drm-dbi-fix-spi-type-1-9-bit-transfer.patch drm-hold-gem-reference-until-object-is-no-longer-accessed.patch revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch --- ...play-clear-dm_state-for-fast-updates.patch | 101 ++++++++++++++++++ ...kernel-infoleak-in-amdgpu_info_ioctl.patch | 47 ++++++++ ...rm-dbi-fix-spi-type-1-9-bit-transfer.patch | 47 ++++++++ ...e-until-object-is-no-longer-accessed.patch | 57 ++++++++++ ...ll-dereference-in-dpm-sysfs-handlers.patch | 54 ++++++++++ queue-5.4/series | 5 + 6 files changed, 311 insertions(+) create mode 100644 queue-5.4/drm-amd-display-clear-dm_state-for-fast-updates.patch create mode 100644 queue-5.4/drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch create mode 100644 queue-5.4/drm-dbi-fix-spi-type-1-9-bit-transfer.patch create mode 100644 queue-5.4/drm-hold-gem-reference-until-object-is-no-longer-accessed.patch create mode 100644 queue-5.4/revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch diff --git a/queue-5.4/drm-amd-display-clear-dm_state-for-fast-updates.patch b/queue-5.4/drm-amd-display-clear-dm_state-for-fast-updates.patch new file mode 100644 index 00000000000..9c3d938dc88 --- /dev/null +++ b/queue-5.4/drm-amd-display-clear-dm_state-for-fast-updates.patch @@ -0,0 +1,101 @@ +From fde9f39ac7f1ffd799a96ffa1e06b2051f0898f1 Mon Sep 17 00:00:00 2001 +From: Mazin Rezk +Date: Mon, 27 Jul 2020 05:40:46 +0000 +Subject: drm/amd/display: Clear dm_state for fast updates + +From: Mazin Rezk + +commit fde9f39ac7f1ffd799a96ffa1e06b2051f0898f1 upstream. + +This patch fixes a race condition that causes a use-after-free during +amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits +are requested and the second one finishes before the first. Essentially, +this bug occurs when the following sequence of events happens: + +1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is +deferred to the workqueue. + +2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is +deferred to the workqueue. + +3. Commit #2 starts before commit #1, dm_state #1 is used in the +commit_tail and commit #2 completes, freeing dm_state #1. + +4. Commit #1 starts after commit #2 completes, uses the freed dm_state +1 and dereferences a freelist pointer while setting the context. + +Since this bug has only been spotted with fast commits, this patch fixes +the bug by clearing the dm_state instead of using the old dc_state for +fast updates. In addition, since dm_state is only used for its dc_state +and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, +removing the dm_state should not have any consequences in fast updates. + +This use-after-free bug has existed for a while now, but only caused a +noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate +freelist pointer to middle of object") moving the freelist pointer from +dm_state->base (which was unused) to dm_state->context (which is +dereferenced). + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 +Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates") +Reported-by: Duncan <1i5t5.duncan@cox.net> +Signed-off-by: Mazin Rezk +Reviewed-by: Nicholas Kazlauskas +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++++++++------ + 1 file changed, 27 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -7464,20 +7464,38 @@ static int amdgpu_dm_atomic_check(struct + * the same resource. If we have a new DC context as part of + * the DM atomic state from validation we need to free it and + * retain the existing one instead. ++ * ++ * Furthermore, since the DM atomic state only contains the DC ++ * context and can safely be annulled, we can free the state ++ * and clear the associated private object now to free ++ * some memory and avoid a possible use-after-free later. + */ +- struct dm_atomic_state *new_dm_state, *old_dm_state; + +- new_dm_state = dm_atomic_get_new_state(state); +- old_dm_state = dm_atomic_get_old_state(state); ++ for (i = 0; i < state->num_private_objs; i++) { ++ struct drm_private_obj *obj = state->private_objs[i].ptr; + +- if (new_dm_state && old_dm_state) { +- if (new_dm_state->context) +- dc_release_state(new_dm_state->context); ++ if (obj->funcs == adev->dm.atomic_obj.funcs) { ++ int j = state->num_private_objs-1; + +- new_dm_state->context = old_dm_state->context; ++ dm_atomic_destroy_state(obj, ++ state->private_objs[i].state); + +- if (old_dm_state->context) +- dc_retain_state(old_dm_state->context); ++ /* If i is not at the end of the array then the ++ * last element needs to be moved to where i was ++ * before the array can safely be truncated. ++ */ ++ if (i != j) ++ state->private_objs[i] = ++ state->private_objs[j]; ++ ++ state->private_objs[j].ptr = NULL; ++ state->private_objs[j].state = NULL; ++ state->private_objs[j].old_state = NULL; ++ state->private_objs[j].new_state = NULL; ++ ++ state->num_private_objs = j; ++ break; ++ } + } + } + diff --git a/queue-5.4/drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch b/queue-5.4/drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch new file mode 100644 index 00000000000..85f18ff0f44 --- /dev/null +++ b/queue-5.4/drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch @@ -0,0 +1,47 @@ +From 543e8669ed9bfb30545fd52bc0e047ca4df7fb31 Mon Sep 17 00:00:00 2001 +From: Peilin Ye +Date: Tue, 28 Jul 2020 15:29:24 -0400 +Subject: drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Peilin Ye + +commit 543e8669ed9bfb30545fd52bc0e047ca4df7fb31 upstream. + +Compiler leaves a 4-byte hole near the end of `dev_info`, causing +amdgpu_info_ioctl() to copy uninitialized kernel stack memory to userspace +when `size` is greater than 356. + +In 2015 we tried to fix this issue by doing `= {};` on `dev_info`, which +unfortunately does not initialize that 4-byte hole. Fix it by using +memset() instead. + +Cc: stable@vger.kernel.org +Fixes: c193fa91b918 ("drm/amdgpu: information leak in amdgpu_info_ioctl()") +Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") +Suggested-by: Dan Carpenter +Reviewed-by: Christian König +Signed-off-by: Peilin Ye +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +@@ -667,9 +667,10 @@ static int amdgpu_info_ioctl(struct drm_ + return n ? -EFAULT : 0; + } + case AMDGPU_INFO_DEV_INFO: { +- struct drm_amdgpu_info_device dev_info = {}; ++ struct drm_amdgpu_info_device dev_info; + uint64_t vm_size; + ++ memset(&dev_info, 0, sizeof(dev_info)); + dev_info.device_id = dev->pdev->device; + dev_info.chip_rev = adev->rev_id; + dev_info.external_rev = adev->external_rev_id; diff --git a/queue-5.4/drm-dbi-fix-spi-type-1-9-bit-transfer.patch b/queue-5.4/drm-dbi-fix-spi-type-1-9-bit-transfer.patch new file mode 100644 index 00000000000..30a7a369ec8 --- /dev/null +++ b/queue-5.4/drm-dbi-fix-spi-type-1-9-bit-transfer.patch @@ -0,0 +1,47 @@ +From 900ab59e2621053b009f707f80b2c19ce0af5dee Mon Sep 17 00:00:00 2001 +From: Paul Cercueil +Date: Fri, 3 Jul 2020 16:13:41 +0200 +Subject: drm/dbi: Fix SPI Type 1 (9-bit) transfer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Paul Cercueil + +commit 900ab59e2621053b009f707f80b2c19ce0af5dee upstream. + +The function mipi_dbi_spi1_transfer() will transfer its payload as 9-bit +data, the 9th (MSB) bit being the data/command bit. In order to do that, +it unpacks the 8-bit values into 16-bit values, then sets the 9th bit if +the byte corresponds to data, clears it otherwise. The 7 MSB are +padding. The array of now 16-bit values is then passed to the SPI core +for transfer. + +This function was broken since its introduction, as the length of the +SPI transfer was set to the payload size before its conversion, but the +payload doubled in size due to the 8-bit -> 16-bit conversion. + +Fixes: 02dd95fe3169 ("drm/tinydrm: Add MIPI DBI support") +Cc: # 5.4+ +Signed-off-by: Paul Cercueil +Reviewed-by: Sam Ravnborg +Reviewed-by: Noralf Trønnes +Signed-off-by: Sam Ravnborg +Link: https://patchwork.freedesktop.org/patch/msgid/20200703141341.1266263-1-paul@crapouillou.net +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_mipi_dbi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_mipi_dbi.c ++++ b/drivers/gpu/drm/drm_mipi_dbi.c +@@ -937,7 +937,7 @@ static int mipi_dbi_spi1_transfer(struct + } + } + +- tr.len = chunk; ++ tr.len = chunk * 2; + len -= chunk; + + ret = spi_sync(spi, &m); diff --git a/queue-5.4/drm-hold-gem-reference-until-object-is-no-longer-accessed.patch b/queue-5.4/drm-hold-gem-reference-until-object-is-no-longer-accessed.patch new file mode 100644 index 00000000000..456b2c88180 --- /dev/null +++ b/queue-5.4/drm-hold-gem-reference-until-object-is-no-longer-accessed.patch @@ -0,0 +1,57 @@ +From 8490d6a7e0a0a6fab5c2d82d57a3937306660864 Mon Sep 17 00:00:00 2001 +From: Steve Cohen +Date: Mon, 20 Jul 2020 18:30:50 -0400 +Subject: drm: hold gem reference until object is no longer accessed + +From: Steve Cohen + +commit 8490d6a7e0a0a6fab5c2d82d57a3937306660864 upstream. + +A use-after-free in drm_gem_open_ioctl can happen if the +GEM object handle is closed between the idr lookup and +retrieving the size from said object since a local reference +is not being held at that point. Hold the local reference +while the object can still be accessed to fix this and +plug the potential security hole. + +Signed-off-by: Steve Cohen +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/1595284250-31580-1-git-send-email-cohens@codeaurora.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_gem.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -872,9 +872,6 @@ err: + * @file_priv: drm file-private structure + * + * Open an object using the global name, returning a handle and the size. +- * +- * This handle (of course) holds a reference to the object, so the object +- * will not go away until the handle is deleted. + */ + int + drm_gem_open_ioctl(struct drm_device *dev, void *data, +@@ -899,14 +896,15 @@ drm_gem_open_ioctl(struct drm_device *de + + /* drm_gem_handle_create_tail unlocks dev->object_name_lock. */ + ret = drm_gem_handle_create_tail(file_priv, obj, &handle); +- drm_gem_object_put_unlocked(obj); + if (ret) +- return ret; ++ goto err; + + args->handle = handle; + args->size = obj->size; + +- return 0; ++err: ++ drm_gem_object_put_unlocked(obj); ++ return ret; + } + + /** diff --git a/queue-5.4/revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch b/queue-5.4/revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch new file mode 100644 index 00000000000..e42fdf8924b --- /dev/null +++ b/queue-5.4/revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch @@ -0,0 +1,54 @@ +From 87004abfbc27261edd15716515d89ab42198b405 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 30 Jul 2020 11:02:30 -0400 +Subject: Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers" + +From: Alex Deucher + +commit 87004abfbc27261edd15716515d89ab42198b405 upstream. + +This regressed some working configurations so revert it. Will +fix this properly for 5.9 and backport then. + +This reverts commit 38e0c89a19fd13f28d2b4721035160a3e66e270b. + +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +@@ -691,7 +691,8 @@ static ssize_t amdgpu_set_pp_od_clk_volt + tmp_str++; + while (isspace(*++tmp_str)); + +- while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { ++ while (tmp_str[0]) { ++ sub_str = strsep(&tmp_str, delimiter); + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); + if (ret) + return -EINVAL; +@@ -882,7 +883,8 @@ static ssize_t amdgpu_read_mask(const ch + memcpy(buf_cpy, buf, bytes); + buf_cpy[bytes] = '\0'; + tmp = buf_cpy; +- while ((sub_str = strsep(&tmp, delimiter)) != NULL) { ++ while (tmp[0]) { ++ sub_str = strsep(&tmp, delimiter); + if (strlen(sub_str)) { + ret = kstrtol(sub_str, 0, &level); + if (ret) +@@ -1298,7 +1300,8 @@ static ssize_t amdgpu_set_pp_power_profi + i++; + memcpy(buf_cpy, buf, count-i); + tmp_str = buf_cpy; +- while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { ++ while (tmp_str[0]) { ++ sub_str = strsep(&tmp_str, delimiter); + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); + if (ret) { + count = -EINVAL; diff --git a/queue-5.4/series b/queue-5.4/series index bc7ff0f655b..de7ec6e6401 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -21,3 +21,8 @@ arm-dts-imx6qdl-icore-fix-otg_id-pin-and-sdcard-detect.patch virtio_balloon-fix-up-endian-ness-for-free-cmd-id.patch random32-update-the-net-random-state-on-interrupt-and-activity.patch arm-percpu.h-fix-build-error.patch +revert-drm-amdgpu-fix-null-dereference-in-dpm-sysfs-handlers.patch +drm-amd-display-clear-dm_state-for-fast-updates.patch +drm-amdgpu-prevent-kernel-infoleak-in-amdgpu_info_ioctl.patch +drm-dbi-fix-spi-type-1-9-bit-transfer.patch +drm-hold-gem-reference-until-object-is-no-longer-accessed.patch -- 2.47.3