From: Namjae Jeon Date: Fri, 10 Jul 2026 05:22:57 +0000 (+0900) Subject: ntfs: harden runlist realloc size calculations X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8bed376124ab4505b70083a2b91f2c7ef6d51e24;p=thirdparty%2Flinux.git 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: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator") Co-developed-by: Alper Mudar Signed-off-by: Alper Mudar Tested-by: Alper Mudar Signed-off-by: Namjae Jeon --- diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index cbb6576cf725..8e0fd400e7f7 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -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); } /*