ntfs: harden runlist realloc size calculations

Add a shared helper to safely convert runlist element counts to byte sizes
using overflow checks, and use it in both ntfs_rl_realloc() and
ntfs_rl_realloc_nofail().

Fixes: 11ccc9107d ("ntfs: update runlist handling and cluster allocator")
Co-developed-by: Alper Mudar <kommandant_alper@proton.me>
Signed-off-by: Alper Mudar <kommandant_alper@proton.me>
Tested-by: Alper Mudar <kommandant_alper@proton.me>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon
2026-07-10 14:22:57 +09:00
parent 523307b851
commit 8bed376124

View File

@@ -71,29 +71,46 @@ static inline void ntfs_rl_mc(struct runlist_element *dstbase, int dst,
* On success, return a pointer to the newly allocated, or recycled, memory.
* On error, return -errno.
*/
struct runlist_element *ntfs_rl_realloc(struct runlist_element *rl,
int old_size, int new_size)
static inline struct runlist_element *ntfs_rl_realloc_gfp(struct runlist_element *rl,
int old_size, int new_size, gfp_t gfp)
{
struct runlist_element *new_rl;
size_t new_bytes;
if (old_size < 0 || new_size < 0)
return ERR_PTR(-EINVAL);
old_size = old_size * sizeof(*rl);
new_size = new_size * sizeof(*rl);
if (old_size == new_size)
return rl;
new_rl = kvzalloc(new_size, GFP_NOFS);
if (check_mul_overflow(new_size, sizeof(*rl), &new_bytes))
return ERR_PTR(-EINVAL);
new_rl = kvzalloc(new_bytes, gfp);
if (unlikely(!new_rl))
return ERR_PTR(-ENOMEM);
if (likely(rl != NULL)) {
if (unlikely(old_size > new_size))
old_size = new_size;
memcpy(new_rl, rl, old_size);
size_t old_bytes;
if (check_mul_overflow(old_size, sizeof(*rl), &old_bytes)) {
kvfree(new_rl);
return ERR_PTR(-EINVAL);
}
if (unlikely(old_bytes > new_bytes))
old_bytes = new_bytes;
memcpy(new_rl, rl, old_bytes);
kvfree(rl);
}
return new_rl;
}
struct runlist_element *ntfs_rl_realloc(struct runlist_element *rl,
int old_size, int new_size)
{
return ntfs_rl_realloc_gfp(rl, old_size, new_size, GFP_NOFS);
}
/*
* ntfs_rl_realloc_nofail - Reallocate memory for runlists
* @rl: original runlist
@@ -118,21 +135,8 @@ struct runlist_element *ntfs_rl_realloc(struct runlist_element *rl,
static inline struct runlist_element *ntfs_rl_realloc_nofail(struct runlist_element *rl,
int old_size, int new_size)
{
struct runlist_element *new_rl;
old_size = old_size * sizeof(*rl);
new_size = new_size * sizeof(*rl);
if (old_size == new_size)
return rl;
new_rl = kvmalloc(new_size, GFP_NOFS | __GFP_NOFAIL);
if (likely(rl != NULL)) {
if (unlikely(old_size > new_size))
old_size = new_size;
memcpy(new_rl, rl, old_size);
kvfree(rl);
}
return new_rl;
return ntfs_rl_realloc_gfp(rl, old_size, new_size,
GFP_NOFS | __GFP_NOFAIL);
}
/*