Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: fix missing cleanup on rollforward recovery error

In an error injection test of a routine for mount-time recovery, KASAN
found a use-after-free bug.

It turned out that if data recovery was performed using partial logs
created by dsync writes, but an error occurred before starting the log
writer to create a recovered checkpoint, the inodes whose data had been
recovered were left in the ns_dirty_files list of the nilfs object and
were not freed.

Fix this issue by cleaning up inodes that have read the recovery data if
the recovery routine fails midway before the log writer starts.

Link: https://lkml.kernel.org/r/20240810065242.3701-1-konishi.ryusuke@gmail.com
Fixes: 0f3e1c7f23f8 ("nilfs2: recovery functions")
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
5787fcaa 68340825

+33 -2
+33 -2
fs/nilfs2/recovery.c
··· 716 716 } 717 717 718 718 /** 719 + * nilfs_abort_roll_forward - cleaning up after a failed rollforward recovery 720 + * @nilfs: nilfs object 721 + */ 722 + static void nilfs_abort_roll_forward(struct the_nilfs *nilfs) 723 + { 724 + struct nilfs_inode_info *ii, *n; 725 + LIST_HEAD(head); 726 + 727 + /* Abandon inodes that have read recovery data */ 728 + spin_lock(&nilfs->ns_inode_lock); 729 + list_splice_init(&nilfs->ns_dirty_files, &head); 730 + spin_unlock(&nilfs->ns_inode_lock); 731 + if (list_empty(&head)) 732 + return; 733 + 734 + set_nilfs_purging(nilfs); 735 + list_for_each_entry_safe(ii, n, &head, i_dirty) { 736 + spin_lock(&nilfs->ns_inode_lock); 737 + list_del_init(&ii->i_dirty); 738 + spin_unlock(&nilfs->ns_inode_lock); 739 + 740 + iput(&ii->vfs_inode); 741 + } 742 + clear_nilfs_purging(nilfs); 743 + } 744 + 745 + /** 719 746 * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint 720 747 * @nilfs: nilfs object 721 748 * @sb: super block instance ··· 800 773 if (unlikely(err)) { 801 774 nilfs_err(sb, "error %d writing segment for recovery", 802 775 err); 803 - goto failed; 776 + goto put_root; 804 777 } 805 778 806 779 nilfs_finish_roll_forward(nilfs, ri); 807 780 } 808 781 809 - failed: 782 + put_root: 810 783 nilfs_put_root(root); 811 784 return err; 785 + 786 + failed: 787 + nilfs_abort_roll_forward(nilfs); 788 + goto put_root; 812 789 } 813 790 814 791 /**