Skip to content

Commit 48e1560

Browse files
Mirsad Goran Todorovacgregkh
authored andcommitted
test_firmware: fix the memory leak of the allocated firmware buffer
The following kernel memory leak was noticed after running tools/testing/selftests/firmware/fw_run_tests.sh: [root@pc-mtodorov firmware]# cat /sys/kernel/debug/kmemleak . . . unreferenced object 0xffff955389bc3400 (size 1024): comm "test_firmware-0", pid 5451, jiffies 4294944822 (age 65.652s) hex dump (first 32 bytes): 47 48 34 35 36 37 0a 00 00 00 00 00 00 00 00 00 GH4567.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff962f5dec>] slab_post_alloc_hook+0x8c/0x3c0 [<ffffffff962fcca4>] __kmem_cache_alloc_node+0x184/0x240 [<ffffffff962704de>] kmalloc_trace+0x2e/0xc0 [<ffffffff9665b42d>] test_fw_run_batch_request+0x9d/0x180 [<ffffffff95fd813b>] kthread+0x10b/0x140 [<ffffffff95e033e9>] ret_from_fork+0x29/0x50 unreferenced object 0xffff9553c334b400 (size 1024): comm "test_firmware-1", pid 5452, jiffies 4294944822 (age 65.652s) hex dump (first 32 bytes): 47 48 34 35 36 37 0a 00 00 00 00 00 00 00 00 00 GH4567.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff962f5dec>] slab_post_alloc_hook+0x8c/0x3c0 [<ffffffff962fcca4>] __kmem_cache_alloc_node+0x184/0x240 [<ffffffff962704de>] kmalloc_trace+0x2e/0xc0 [<ffffffff9665b42d>] test_fw_run_batch_request+0x9d/0x180 [<ffffffff95fd813b>] kthread+0x10b/0x140 [<ffffffff95e033e9>] ret_from_fork+0x29/0x50 unreferenced object 0xffff9553c334f000 (size 1024): comm "test_firmware-2", pid 5453, jiffies 4294944822 (age 65.652s) hex dump (first 32 bytes): 47 48 34 35 36 37 0a 00 00 00 00 00 00 00 00 00 GH4567.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff962f5dec>] slab_post_alloc_hook+0x8c/0x3c0 [<ffffffff962fcca4>] __kmem_cache_alloc_node+0x184/0x240 [<ffffffff962704de>] kmalloc_trace+0x2e/0xc0 [<ffffffff9665b42d>] test_fw_run_batch_request+0x9d/0x180 [<ffffffff95fd813b>] kthread+0x10b/0x140 [<ffffffff95e033e9>] ret_from_fork+0x29/0x50 unreferenced object 0xffff9553c3348400 (size 1024): comm "test_firmware-3", pid 5454, jiffies 4294944822 (age 65.652s) hex dump (first 32 bytes): 47 48 34 35 36 37 0a 00 00 00 00 00 00 00 00 00 GH4567.......... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<ffffffff962f5dec>] slab_post_alloc_hook+0x8c/0x3c0 [<ffffffff962fcca4>] __kmem_cache_alloc_node+0x184/0x240 [<ffffffff962704de>] kmalloc_trace+0x2e/0xc0 [<ffffffff9665b42d>] test_fw_run_batch_request+0x9d/0x180 [<ffffffff95fd813b>] kthread+0x10b/0x140 [<ffffffff95e033e9>] ret_from_fork+0x29/0x50 [root@pc-mtodorov firmware]# Note that the size 1024 corresponds to the size of the test firmware buffer. The actual number of the buffers leaked is around 70-110, depending on the test run. The cause of the leak is the following: request_partial_firmware_into_buf() and request_firmware_into_buf() provided firmware buffer isn't released on release_firmware(), we have allocated it and we are responsible for deallocating it manually. This is introduced in a number of context where previously only release_firmware() was called, which was insufficient. Reported-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr> Fixes: 7feebfa ("test_firmware: add support for request_firmware_into_buf") Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Dan Carpenter <error27@gmail.com> Cc: Takashi Iwai <tiwai@suse.de> Cc: Luis Chamberlain <mcgrof@kernel.org> Cc: Russ Weight <russell.h.weight@intel.com> Cc: Tianfei zhang <tianfei.zhang@intel.com> Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Cc: Zhengchao Shao <shaozhengchao@huawei.com> Cc: Colin Ian King <colin.i.king@gmail.com> Cc: linux-kernel@vger.kernel.org Cc: Kees Cook <keescook@chromium.org> Cc: Scott Branden <sbranden@broadcom.com> Cc: Luis R. Rodriguez <mcgrof@kernel.org> Cc: linux-kselftest@vger.kernel.org Cc: stable@vger.kernel.org # v5.4 Signed-off-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr> Link: https://lore.kernel.org/r/20230509084746.48259-3-mirsad.todorovac@alu.unizg.hr Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent be37bed commit 48e1560

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

lib/test_firmware.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct test_batched_req {
4545
bool sent;
4646
const struct firmware *fw;
4747
const char *name;
48+
const char *fw_buf;
4849
struct completion completion;
4950
struct task_struct *task;
5051
struct device *dev;
@@ -175,8 +176,14 @@ static void __test_release_all_firmware(void)
175176

176177
for (i = 0; i < test_fw_config->num_requests; i++) {
177178
req = &test_fw_config->reqs[i];
178-
if (req->fw)
179+
if (req->fw) {
180+
if (req->fw_buf) {
181+
kfree_const(req->fw_buf);
182+
req->fw_buf = NULL;
183+
}
179184
release_firmware(req->fw);
185+
req->fw = NULL;
186+
}
180187
}
181188

182189
vfree(test_fw_config->reqs);
@@ -670,6 +677,8 @@ static ssize_t trigger_request_store(struct device *dev,
670677

671678
mutex_lock(&test_fw_mutex);
672679
release_firmware(test_firmware);
680+
if (test_fw_config->reqs)
681+
__test_release_all_firmware();
673682
test_firmware = NULL;
674683
rc = request_firmware(&test_firmware, name, dev);
675684
if (rc) {
@@ -770,6 +779,8 @@ static ssize_t trigger_async_request_store(struct device *dev,
770779
mutex_lock(&test_fw_mutex);
771780
release_firmware(test_firmware);
772781
test_firmware = NULL;
782+
if (test_fw_config->reqs)
783+
__test_release_all_firmware();
773784
rc = request_firmware_nowait(THIS_MODULE, 1, name, dev, GFP_KERNEL,
774785
NULL, trigger_async_request_cb);
775786
if (rc) {
@@ -812,6 +823,8 @@ static ssize_t trigger_custom_fallback_store(struct device *dev,
812823

813824
mutex_lock(&test_fw_mutex);
814825
release_firmware(test_firmware);
826+
if (test_fw_config->reqs)
827+
__test_release_all_firmware();
815828
test_firmware = NULL;
816829
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOUEVENT, name,
817830
dev, GFP_KERNEL, NULL,
@@ -874,6 +887,8 @@ static int test_fw_run_batch_request(void *data)
874887
test_fw_config->buf_size);
875888
if (!req->fw)
876889
kfree(test_buf);
890+
else
891+
req->fw_buf = test_buf;
877892
} else {
878893
req->rc = test_fw_config->req_firmware(&req->fw,
879894
req->name,
@@ -934,6 +949,7 @@ static ssize_t trigger_batched_requests_store(struct device *dev,
934949
req->fw = NULL;
935950
req->idx = i;
936951
req->name = test_fw_config->name;
952+
req->fw_buf = NULL;
937953
req->dev = dev;
938954
init_completion(&req->completion);
939955
req->task = kthread_run(test_fw_run_batch_request, req,
@@ -1038,6 +1054,7 @@ ssize_t trigger_batched_requests_async_store(struct device *dev,
10381054
for (i = 0; i < test_fw_config->num_requests; i++) {
10391055
req = &test_fw_config->reqs[i];
10401056
req->name = test_fw_config->name;
1057+
req->fw_buf = NULL;
10411058
req->fw = NULL;
10421059
req->idx = i;
10431060
init_completion(&req->completion);

0 commit comments

Comments
 (0)