mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 02:21:39 -04:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user