From e45ab0e6009452a9f149ae7c1379df03bcf816f7 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 15 Jun 2023 10:25:23 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...ull-pointer-dereference-error-in-amd.patch | 74 +++++ ...ut-of-bounds-read-in-smb2_handle_neg.patch | 63 +++++ queue-5.15/series | 5 + ...e-fix-a-memory-leak-with-reqs-buffer.patch | 72 +++++ ...event-race-conditions-by-a-correct-i.patch | 259 ++++++++++++++++++ ...-use-kstrtobool-instead-of-strtobool.patch | 51 ++++ 6 files changed, 524 insertions(+) create mode 100644 queue-5.15/drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch create mode 100644 queue-5.15/ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch create mode 100644 queue-5.15/series create mode 100644 queue-5.15/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch create mode 100644 queue-5.15/test_firmware-prevent-race-conditions-by-a-correct-i.patch create mode 100644 queue-5.15/test_firmware-use-kstrtobool-instead-of-strtobool.patch diff --git a/queue-5.15/drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch b/queue-5.15/drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch new file mode 100644 index 00000000000..2e808ef440e --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch @@ -0,0 +1,74 @@ +From ee1fdf315fd19f56c36d1f13bc983c841addce4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 May 2023 14:23:37 -0400 +Subject: drm/amdgpu: fix Null pointer dereference error in + amdgpu_device_recover_vram + +From: Horatio Zhang + +[ Upstream commit 2a1eb1a343208ce7d6839b73d62aece343e693ff ] + +Use the function of amdgpu_bo_vm_destroy to handle the resource release +of shadow bo. During the amdgpu_mes_self_test, shadow bo released, but +vmbo->shadow_list was not, which caused a null pointer reference error +in amdgpu_device_recover_vram when GPU reset. + +Fixes: 6c032c37ac3e ("drm/amdgpu: Fix vram recover doesn't work after whole GPU reset (v2)") +Signed-off-by: xinhui pan +Signed-off-by: Horatio Zhang +Acked-by: Feifei Xu +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 6 ++++-- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 - + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index a0b1bf17cb74b..d03a4519f945b 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -78,9 +78,10 @@ static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo) + static void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo) + { + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); +- struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); ++ struct amdgpu_bo *shadow_bo = ttm_to_amdgpu_bo(tbo), *bo; + struct amdgpu_bo_vm *vmbo; + ++ bo = shadow_bo->parent; + vmbo = to_amdgpu_bo_vm(bo); + /* in case amdgpu_device_recover_vram got NULL of bo->parent */ + if (!list_empty(&vmbo->shadow_list)) { +@@ -690,7 +691,6 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev, + return r; + + *vmbo_ptr = to_amdgpu_bo_vm(bo_ptr); +- INIT_LIST_HEAD(&(*vmbo_ptr)->shadow_list); + return r; + } + +@@ -741,6 +741,8 @@ void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo) + + mutex_lock(&adev->shadow_list_lock); + list_add_tail(&vmbo->shadow_list, &adev->shadow_list); ++ vmbo->shadow->parent = amdgpu_bo_ref(&vmbo->bo); ++ vmbo->shadow->tbo.destroy = &amdgpu_bo_vm_destroy; + mutex_unlock(&adev->shadow_list_lock); + } + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +index 01710cd0d9727..924c6d5f86203 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +@@ -983,7 +983,6 @@ static int amdgpu_vm_pt_create(struct amdgpu_device *adev, + return r; + } + +- (*vmbo)->shadow->parent = amdgpu_bo_ref(bo); + amdgpu_bo_add_to_shadow_list(*vmbo); + + return 0; +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch b/queue-5.15/ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch new file mode 100644 index 00000000000..4fc014a4adc --- /dev/null +++ b/queue-5.15/ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch @@ -0,0 +1,63 @@ +From 08f7fa3e8337a861872fc0b433ef6152bc8a6753 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 May 2023 22:59:28 +0900 +Subject: ksmbd: fix slab-out-of-bounds read in smb2_handle_negotiate + +From: Kuan-Ting Chen + +[ Upstream commit d738950f112c8f40f0515fe967db998e8235a175 ] + +Check request_buf length first to avoid out-of-bounds read by +req->DialectCount. + +[ 3350.990282] BUG: KASAN: slab-out-of-bounds in smb2_handle_negotiate+0x35d7/0x3e60 +[ 3350.990282] Read of size 2 at addr ffff88810ad61346 by task kworker/5:0/276 +[ 3351.000406] Workqueue: ksmbd-io handle_ksmbd_work +[ 3351.003499] Call Trace: +[ 3351.006473] +[ 3351.006473] dump_stack_lvl+0x8d/0xe0 +[ 3351.006473] print_report+0xcc/0x620 +[ 3351.006473] kasan_report+0x92/0xc0 +[ 3351.006473] smb2_handle_negotiate+0x35d7/0x3e60 +[ 3351.014760] ksmbd_smb_negotiate_common+0x7a7/0xf00 +[ 3351.014760] handle_ksmbd_work+0x3f7/0x12d0 +[ 3351.014760] process_one_work+0xa85/0x1780 + +Cc: stable@vger.kernel.org +Signed-off-by: Kuan-Ting Chen +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/smb2pdu.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index e24fd10d85d3b..266430a2a0e07 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1083,16 +1083,16 @@ int smb2_handle_negotiate(struct ksmbd_work *work) + return rc; + } + +- if (req->DialectCount == 0) { +- pr_err("malformed packet\n"); ++ smb2_buf_len = get_rfc1002_len(work->request_buf); ++ smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4; ++ if (smb2_neg_size > smb2_buf_len) { + rsp->hdr.Status = STATUS_INVALID_PARAMETER; + rc = -EINVAL; + goto err_out; + } + +- smb2_buf_len = get_rfc1002_len(work->request_buf); +- smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4; +- if (smb2_neg_size > smb2_buf_len) { ++ if (req->DialectCount == 0) { ++ pr_err("malformed packet\n"); + rsp->hdr.Status = STATUS_INVALID_PARAMETER; + rc = -EINVAL; + goto err_out; +-- +2.39.2 + diff --git a/queue-5.15/series b/queue-5.15/series new file mode 100644 index 00000000000..bfa7c055ae4 --- /dev/null +++ b/queue-5.15/series @@ -0,0 +1,5 @@ +test_firmware-use-kstrtobool-instead-of-strtobool.patch +test_firmware-prevent-race-conditions-by-a-correct-i.patch +test_firmware-fix-a-memory-leak-with-reqs-buffer.patch +ksmbd-fix-slab-out-of-bounds-read-in-smb2_handle_neg.patch +drm-amdgpu-fix-null-pointer-dereference-error-in-amd.patch diff --git a/queue-5.15/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch b/queue-5.15/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch new file mode 100644 index 00000000000..3efd7e0f7b0 --- /dev/null +++ b/queue-5.15/test_firmware-fix-a-memory-leak-with-reqs-buffer.patch @@ -0,0 +1,72 @@ +From 7c26929125a6642cb730fea67849620103369cf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 May 2023 10:47:47 +0200 +Subject: test_firmware: fix a memory leak with reqs buffer + +From: Mirsad Goran Todorovac + +[ Upstream commit be37bed754ed90b2655382f93f9724b3c1aae847 ] + +Dan Carpenter spotted that test_fw_config->reqs will be leaked if +trigger_batched_requests_store() is called two or more times. +The same appears with trigger_batched_requests_async_store(). + +This bug wasn't trigger by the tests, but observed by Dan's visual +inspection of the code. + +The recommended workaround was to return -EBUSY if test_fw_config->reqs +is already allocated. + +Fixes: 7feebfa487b92 ("test_firmware: add support for request_firmware_into_buf") +Cc: Luis Chamberlain +Cc: Greg Kroah-Hartman +Cc: Russ Weight +Cc: Tianfei Zhang +Cc: Shuah Khan +Cc: Colin Ian King +Cc: Randy Dunlap +Cc: linux-kselftest@vger.kernel.org +Cc: stable@vger.kernel.org # v5.4 +Suggested-by: Dan Carpenter +Suggested-by: Takashi Iwai +Signed-off-by: Mirsad Goran Todorovac +Reviewed-by: Dan Carpenter +Acked-by: Luis Chamberlain +Link: https://lore.kernel.org/r/20230509084746.48259-2-mirsad.todorovac@alu.unizg.hr +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/test_firmware.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index 4ad01dbe7e729..2a4078946a3fd 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -863,6 +863,11 @@ static ssize_t trigger_batched_requests_store(struct device *dev, + + mutex_lock(&test_fw_mutex); + ++ if (test_fw_config->reqs) { ++ rc = -EBUSY; ++ goto out_bail; ++ } ++ + test_fw_config->reqs = + vzalloc(array3_size(sizeof(struct test_batched_req), + test_fw_config->num_requests, 2)); +@@ -962,6 +967,11 @@ ssize_t trigger_batched_requests_async_store(struct device *dev, + + mutex_lock(&test_fw_mutex); + ++ if (test_fw_config->reqs) { ++ rc = -EBUSY; ++ goto out_bail; ++ } ++ + test_fw_config->reqs = + vzalloc(array3_size(sizeof(struct test_batched_req), + test_fw_config->num_requests, 2)); +-- +2.39.2 + diff --git a/queue-5.15/test_firmware-prevent-race-conditions-by-a-correct-i.patch b/queue-5.15/test_firmware-prevent-race-conditions-by-a-correct-i.patch new file mode 100644 index 00000000000..f2a6937dec4 --- /dev/null +++ b/queue-5.15/test_firmware-prevent-race-conditions-by-a-correct-i.patch @@ -0,0 +1,259 @@ +From 6c92c81b61569c8475d4ffef7d61fdb1a59a9e90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 May 2023 10:47:45 +0200 +Subject: test_firmware: prevent race conditions by a correct implementation of + locking + +From: Mirsad Goran Todorovac + +[ Upstream commit 4acfe3dfde685a5a9eaec5555351918e2d7266a1 ] + +Dan Carpenter spotted a race condition in a couple of situations like +these in the test_firmware driver: + +static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) +{ + u8 val; + int ret; + + ret = kstrtou8(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&test_fw_mutex); + *(u8 *)cfg = val; + mutex_unlock(&test_fw_mutex); + + /* Always return full write size even if we didn't consume all */ + return size; +} + +static ssize_t config_num_requests_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int rc; + + mutex_lock(&test_fw_mutex); + if (test_fw_config->reqs) { + pr_err("Must call release_all_firmware prior to changing config\n"); + rc = -EINVAL; + mutex_unlock(&test_fw_mutex); + goto out; + } + mutex_unlock(&test_fw_mutex); + + rc = test_dev_config_update_u8(buf, count, + &test_fw_config->num_requests); + +out: + return rc; +} + +static ssize_t config_read_fw_idx_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return test_dev_config_update_u8(buf, count, + &test_fw_config->read_fw_idx); +} + +The function test_dev_config_update_u8() is called from both the locked +and the unlocked context, function config_num_requests_store() and +config_read_fw_idx_store() which can both be called asynchronously as +they are driver's methods, while test_dev_config_update_u8() and siblings +change their argument pointed to by u8 *cfg or similar pointer. + +To avoid deadlock on test_fw_mutex, the lock is dropped before calling +test_dev_config_update_u8() and re-acquired within test_dev_config_update_u8() +itself, but alas this creates a race condition. + +Having two locks wouldn't assure a race-proof mutual exclusion. + +This situation is best avoided by the introduction of a new, unlocked +function __test_dev_config_update_u8() which can be called from the locked +context and reducing test_dev_config_update_u8() to: + +static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) +{ + int ret; + + mutex_lock(&test_fw_mutex); + ret = __test_dev_config_update_u8(buf, size, cfg); + mutex_unlock(&test_fw_mutex); + + return ret; +} + +doing the locking and calling the unlocked primitive, which enables both +locked and unlocked versions without duplication of code. + +The similar approach was applied to all functions called from the locked +and the unlocked context, which safely mitigates both deadlocks and race +conditions in the driver. + +__test_dev_config_update_bool(), __test_dev_config_update_u8() and +__test_dev_config_update_size_t() unlocked versions of the functions +were introduced to be called from the locked contexts as a workaround +without releasing the main driver's lock and thereof causing a race +condition. + +The test_dev_config_update_bool(), test_dev_config_update_u8() and +test_dev_config_update_size_t() locked versions of the functions +are being called from driver methods without the unnecessary multiplying +of the locking and unlocking code for each method, and complicating +the code with saving of the return value across lock. + +Fixes: 7feebfa487b92 ("test_firmware: add support for request_firmware_into_buf") +Cc: Luis Chamberlain +Cc: Greg Kroah-Hartman +Cc: Russ Weight +Cc: Takashi Iwai +Cc: Tianfei Zhang +Cc: Shuah Khan +Cc: Colin Ian King +Cc: Randy Dunlap +Cc: linux-kselftest@vger.kernel.org +Cc: stable@vger.kernel.org # v5.4 +Suggested-by: Dan Carpenter +Signed-off-by: Mirsad Goran Todorovac +Link: https://lore.kernel.org/r/20230509084746.48259-1-mirsad.todorovac@alu.unizg.hr +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/test_firmware.c | 52 ++++++++++++++++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 17 deletions(-) + +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index 0b4e3de3f1748..4ad01dbe7e729 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -321,16 +321,26 @@ static ssize_t config_test_show_str(char *dst, + return len; + } + +-static int test_dev_config_update_bool(const char *buf, size_t size, ++static inline int __test_dev_config_update_bool(const char *buf, size_t size, + bool *cfg) + { + int ret; + +- mutex_lock(&test_fw_mutex); + if (kstrtobool(buf, cfg) < 0) + ret = -EINVAL; + else + ret = size; ++ ++ return ret; ++} ++ ++static int test_dev_config_update_bool(const char *buf, size_t size, ++ bool *cfg) ++{ ++ int ret; ++ ++ mutex_lock(&test_fw_mutex); ++ ret = __test_dev_config_update_bool(buf, size, cfg); + mutex_unlock(&test_fw_mutex); + + return ret; +@@ -341,7 +351,8 @@ static ssize_t test_dev_config_show_bool(char *buf, bool val) + return snprintf(buf, PAGE_SIZE, "%d\n", val); + } + +-static int test_dev_config_update_size_t(const char *buf, ++static int __test_dev_config_update_size_t( ++ const char *buf, + size_t size, + size_t *cfg) + { +@@ -352,9 +363,7 @@ static int test_dev_config_update_size_t(const char *buf, + if (ret) + return ret; + +- mutex_lock(&test_fw_mutex); + *(size_t *)cfg = new; +- mutex_unlock(&test_fw_mutex); + + /* Always return full write size even if we didn't consume all */ + return size; +@@ -370,7 +379,7 @@ static ssize_t test_dev_config_show_int(char *buf, int val) + return snprintf(buf, PAGE_SIZE, "%d\n", val); + } + +-static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) ++static int __test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) + { + u8 val; + int ret; +@@ -379,14 +388,23 @@ static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) + if (ret) + return ret; + +- mutex_lock(&test_fw_mutex); + *(u8 *)cfg = val; +- mutex_unlock(&test_fw_mutex); + + /* Always return full write size even if we didn't consume all */ + return size; + } + ++static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg) ++{ ++ int ret; ++ ++ mutex_lock(&test_fw_mutex); ++ ret = __test_dev_config_update_u8(buf, size, cfg); ++ mutex_unlock(&test_fw_mutex); ++ ++ return ret; ++} ++ + static ssize_t test_dev_config_show_u8(char *buf, u8 val) + { + return snprintf(buf, PAGE_SIZE, "%u\n", val); +@@ -413,10 +431,10 @@ static ssize_t config_num_requests_store(struct device *dev, + mutex_unlock(&test_fw_mutex); + goto out; + } +- mutex_unlock(&test_fw_mutex); + +- rc = test_dev_config_update_u8(buf, count, +- &test_fw_config->num_requests); ++ rc = __test_dev_config_update_u8(buf, count, ++ &test_fw_config->num_requests); ++ mutex_unlock(&test_fw_mutex); + + out: + return rc; +@@ -460,10 +478,10 @@ static ssize_t config_buf_size_store(struct device *dev, + mutex_unlock(&test_fw_mutex); + goto out; + } +- mutex_unlock(&test_fw_mutex); + +- rc = test_dev_config_update_size_t(buf, count, +- &test_fw_config->buf_size); ++ rc = __test_dev_config_update_size_t(buf, count, ++ &test_fw_config->buf_size); ++ mutex_unlock(&test_fw_mutex); + + out: + return rc; +@@ -490,10 +508,10 @@ static ssize_t config_file_offset_store(struct device *dev, + mutex_unlock(&test_fw_mutex); + goto out; + } +- mutex_unlock(&test_fw_mutex); + +- rc = test_dev_config_update_size_t(buf, count, +- &test_fw_config->file_offset); ++ rc = __test_dev_config_update_size_t(buf, count, ++ &test_fw_config->file_offset); ++ mutex_unlock(&test_fw_mutex); + + out: + return rc; +-- +2.39.2 + diff --git a/queue-5.15/test_firmware-use-kstrtobool-instead-of-strtobool.patch b/queue-5.15/test_firmware-use-kstrtobool-instead-of-strtobool.patch new file mode 100644 index 00000000000..b72c9a218ad --- /dev/null +++ b/queue-5.15/test_firmware-use-kstrtobool-instead-of-strtobool.patch @@ -0,0 +1,51 @@ +From 43a777793a53fc41f0f1191eb2cb643046eadb8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 14 Jan 2023 10:22:03 +0100 +Subject: test_firmware: Use kstrtobool() instead of strtobool() + +From: Christophe JAILLET + +[ Upstream commit f7d85515bd21902b218370a1a6301f76e4e636ff ] + +strtobool() is the same as kstrtobool(). +However, the latter is more used within the kernel. + +In order to remove strtobool() and slightly simplify kstrtox.h, switch to +the other function name. + +While at it, include the corresponding header file () + +Signed-off-by: Christophe JAILLET +Acked-by: Luis Chamberlain +Link: https://lore.kernel.org/r/34f04735d20e0138695dd4070651bd860a36b81c.1673688120.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 4acfe3dfde68 ("test_firmware: prevent race conditions by a correct implementation of locking") +Signed-off-by: Sasha Levin +--- + lib/test_firmware.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index e337773585b9e..0b4e3de3f1748 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -326,7 +327,7 @@ static int test_dev_config_update_bool(const char *buf, size_t size, + int ret; + + mutex_lock(&test_fw_mutex); +- if (strtobool(buf, cfg) < 0) ++ if (kstrtobool(buf, cfg) < 0) + ret = -EINVAL; + else + ret = size; +-- +2.39.2 + -- 2.47.2