Skip to content

Commit 8c16c1c

Browse files
charsyamnamjaejeon
authored andcommitted
ntfs: fix empty_buf and ra lifetime bugs in ntfs_empty_logfile()
ntfs_empty_logfile() has three related allocator bugs around the @empty_buf and @ra buffers it uses inside the per-cluster loop. When the loop encounters a runlist entry with LCN_RL_NOT_MAPPED, the function kvfrees @empty_buf and goes to map_vcn to remap. @empty_buf is not cleared. If ntfs_map_runlist_nolock() fails on re-entry, control jumps to the err label which kvfrees @empty_buf a second time. In the same branch, @ra is left allocated. When the remap succeeds the function falls through the @empty_buf re-allocation and the @ra re-allocation, overwriting the previous @ra pointer and leaking it. The success path frees @empty_buf with kfree() instead of kvfree(). kvzalloc() may fall back to vmalloc(), in which case kfree() does not correctly release the memory. A KASAN-enabled QEMU harness mirroring this control flow reports "BUG: KASAN: double-free" when the second ntfs_map_runlist_nolock() fails. Clear both @empty_buf and @ra after the in-loop releases so the err path is a no-op when the buffers have already been freed and so the remap-success path does not leak the previous @ra. Switch the success path to kvfree() to match the @empty_buf allocator. Fixes: 5218cd1 ("ntfs: update misc operations") Signed-off-by: DaeMyung Kang <charsyam@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
1 parent b64f0ae commit 8c16c1c

1 file changed

Lines changed: 4 additions & 1 deletion

File tree

fs/ntfs/logfile.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,9 @@ bool ntfs_empty_logfile(struct inode *log_vi)
710710
if (unlikely(lcn == LCN_RL_NOT_MAPPED)) {
711711
vcn = rl->vcn;
712712
kvfree(empty_buf);
713+
empty_buf = NULL;
714+
kfree(ra);
715+
ra = NULL;
713716
goto map_vcn;
714717
}
715718
/* If this run is not valid abort with an error. */
@@ -753,7 +756,7 @@ bool ntfs_empty_logfile(struct inode *log_vi)
753756
} while (start < end);
754757
} while ((++rl)->vcn < end_vcn);
755758
up_write(&log_ni->runlist.lock);
756-
kfree(empty_buf);
759+
kvfree(empty_buf);
757760
kfree(ra);
758761
truncate_inode_pages(log_vi->i_mapping, 0);
759762
/* Set the flag so we do not have to do it again on remount. */

0 commit comments

Comments
 (0)