| From e57d278b30eef0f8243fdc08d66e060067fdd3c4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 30 Aug 2023 17:58:20 +0200 |
| Subject: module/decompress: use vmalloc() for gzip decompression workspace |
| |
| From: Andrea Righi <andrea.righi@canonical.com> |
| |
| [ Upstream commit 3737df782c740b944912ed93420c57344b1cf864 ] |
| |
| Use a similar approach as commit a419beac4a07 ("module/decompress: use |
| vmalloc() for zstd decompression workspace") and replace kmalloc() with |
| vmalloc() also for the gzip module decompression workspace. |
| |
| In this case the workspace is represented by struct inflate_workspace |
| that can be fairly large for kmalloc() and it can potentially lead to |
| allocation errors on certain systems: |
| |
| $ pahole inflate_workspace |
| struct inflate_workspace { |
| struct inflate_state inflate_state; /* 0 9544 */ |
| /* --- cacheline 149 boundary (9536 bytes) was 8 bytes ago --- */ |
| unsigned char working_window[32768]; /* 9544 32768 */ |
| |
| /* size: 42312, cachelines: 662, members: 2 */ |
| /* last cacheline: 8 bytes */ |
| }; |
| |
| Considering that there is no need to use continuous physical memory, |
| simply switch to vmalloc() to provide a more reliable in-kernel module |
| decompression. |
| |
| Fixes: b1ae6dc41eaa ("module: add in-kernel support for decompressing") |
| Signed-off-by: Andrea Righi <andrea.righi@canonical.com> |
| Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/module/decompress.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| diff --git a/kernel/module/decompress.c b/kernel/module/decompress.c |
| index 720e719253cd1..e1e9f69c5dd16 100644 |
| --- a/kernel/module/decompress.c |
| +++ b/kernel/module/decompress.c |
| @@ -100,7 +100,7 @@ static ssize_t module_gzip_decompress(struct load_info *info, |
| s.next_in = buf + gzip_hdr_len; |
| s.avail_in = size - gzip_hdr_len; |
| |
| - s.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); |
| + s.workspace = vmalloc(zlib_inflate_workspacesize()); |
| if (!s.workspace) |
| return -ENOMEM; |
| |
| @@ -138,7 +138,7 @@ static ssize_t module_gzip_decompress(struct load_info *info, |
| out_inflate_end: |
| zlib_inflateEnd(&s); |
| out: |
| - kfree(s.workspace); |
| + vfree(s.workspace); |
| return retval; |
| } |
| #elif CONFIG_MODULE_COMPRESS_XZ |
| -- |
| 2.42.0 |
| |