mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] f2fs: fix panic in f2fs_put_super
@ 2024-05-16  8:55 sunshijie
  2024-05-16  9:32 ` Chao Yu
  0 siblings, 1 reply; 4+ messages in thread
From: sunshijie @ 2024-05-16  8:55 UTC (permalink / raw)
  To: jaegeuk, chao, linux-f2fs-devel, linux-kernel; +Cc: sunshijie

When thread A calls kill_f2fs_super, Thread A first executes the code sbi->node_inode = NULL;
Then thread A may submit a bio to the function iput(sbi->meta_inode);
Then thread A enters the process D state,
Now that the bio submitted by thread A is complete, it calls f2fs_write_end_io and may trigger null-ptr-deref in NODE_MAPPING.

Thread A                                          IRQ context
- f2fs_put_super
 - sbi->node_inode = NULL;
 - iput(sbi->meta_inode);
  - iput_final
   - write_inode_now
    - writeback_single_inode
     - __writeback_single_inode
      - filemap_fdatawait
       - filemap_fdatawait_range
        - __kcfi_typeid_free_transhuge_page
         - __filemap_fdatawait_range
          - wait_on_page_writeback
           - folio_wait_writeback
            - folio_wait_bit
             - folio_wait_bit_common
              - io_schedule

                                                  - __handle_irq_event_percpu
                                                   - ufs_qcom_mcq_esi_handler
                                                    - ufshcd_mcq_poll_cqe_nolock
                                                     - ufshcd_compl_one_cqe
                                                      - scsi_done
                                                       - scsi_done_internal
                                                        - blk_mq_complete_request
                                                         - scsi_complete
                                                          - scsi_finish_command
                                                           - scsi_io_completion
                                                            - scsi_end_request
                                                             - blk_update_request
                                                              - bio_endio
                                                               - f2fs_write_end_io
                                                                - NODE_MAPPING(sbi)

Signed-off-by: sunshijie <sunshijie@xiaomi.com>
---
 fs/f2fs/super.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index adffc9b80a9c..aeb085e11f9a 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1641,12 +1641,12 @@ static void f2fs_put_super(struct super_block *sb)
 
 	f2fs_destroy_compress_inode(sbi);
 
-	iput(sbi->node_inode);
-	sbi->node_inode = NULL;
-
 	iput(sbi->meta_inode);
 	sbi->meta_inode = NULL;
 
+	iput(sbi->node_inode);
+	sbi->node_inode = NULL;
+
 	mutex_unlock(&sbi->umount_mutex);
 
 	/*
-- 
2.34.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] f2fs: fix panic in f2fs_put_super
  2024-05-16  8:55 [PATCH] f2fs: fix panic in f2fs_put_super sunshijie
@ 2024-05-16  9:32 ` Chao Yu
  0 siblings, 0 replies; 4+ messages in thread
From: Chao Yu @ 2024-05-16  9:32 UTC (permalink / raw)
  To: sunshijie, jaegeuk, linux-f2fs-devel, linux-kernel; +Cc: sunshijie

On 2024/5/16 16:55, sunshijie wrote:
> When thread A calls kill_f2fs_super, Thread A first executes the code sbi->node_inode = NULL;
> Then thread A may submit a bio to the function iput(sbi->meta_inode);
> Then thread A enters the process D state,
> Now that the bio submitted by thread A is complete, it calls f2fs_write_end_io and may trigger null-ptr-deref in NODE_MAPPING.

I didn't get it, if there is no cp_err, f2fs_write_checkpoint() in
f2fs_put_super() will flush all dirty pages of node_inode, if there is
cp_err, below flow will keep all dirty pages being truncated, and
there is sanity check on all types of dirty pages.

	/* our cp_error case, we can wait for any writeback page */
	f2fs_flush_merged_writes(sbi);

	f2fs_wait_on_all_pages(sbi, F2FS_WB_CP_DATA);

	if (err || f2fs_cp_error(sbi)) {
		truncate_inode_pages_final(NODE_MAPPING(sbi));
		truncate_inode_pages_final(META_MAPPING(sbi));
	}

	for (i = 0; i < NR_COUNT_TYPE; i++) {
		if (!get_pages(sbi, i))
			continue;
		f2fs_err(sbi, "detect filesystem reference count leak during "
			"umount, type: %d, count: %lld", i, get_pages(sbi, i));
		f2fs_bug_on(sbi, 1);
	}

So, is there any missing case that dirty page of node_inode is missed by
f2fs_put_super()?

Thanks,

> 
> Thread A                                          IRQ context
> - f2fs_put_super
>   - sbi->node_inode = NULL;
>   - iput(sbi->meta_inode);
>    - iput_final
>     - write_inode_now
>      - writeback_single_inode
>       - __writeback_single_inode
>        - filemap_fdatawait
>         - filemap_fdatawait_range
>          - __kcfi_typeid_free_transhuge_page
>           - __filemap_fdatawait_range
>            - wait_on_page_writeback
>             - folio_wait_writeback
>              - folio_wait_bit
>               - folio_wait_bit_common
>                - io_schedule
> 
>                                                    - __handle_irq_event_percpu
>                                                     - ufs_qcom_mcq_esi_handler
>                                                      - ufshcd_mcq_poll_cqe_nolock
>                                                       - ufshcd_compl_one_cqe
>                                                        - scsi_done
>                                                         - scsi_done_internal
>                                                          - blk_mq_complete_request
>                                                           - scsi_complete
>                                                            - scsi_finish_command
>                                                             - scsi_io_completion
>                                                              - scsi_end_request
>                                                               - blk_update_request
>                                                                - bio_endio
>                                                                 - f2fs_write_end_io
>                                                                  - NODE_MAPPING(sbi)
> 
> Signed-off-by: sunshijie <sunshijie@xiaomi.com>
> ---
>   fs/f2fs/super.c | 6 +++---
>   1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index adffc9b80a9c..aeb085e11f9a 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1641,12 +1641,12 @@ static void f2fs_put_super(struct super_block *sb)
>   
>   	f2fs_destroy_compress_inode(sbi);
>   
> -	iput(sbi->node_inode);
> -	sbi->node_inode = NULL;
> -
>   	iput(sbi->meta_inode);
>   	sbi->meta_inode = NULL;
>   
> +	iput(sbi->node_inode);
> +	sbi->node_inode = NULL;
> +
>   	mutex_unlock(&sbi->umount_mutex);
>   
>   	/*

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] f2fs: fix panic in f2fs_put_super
@ 2024-05-16 10:13 sunshijie
  0 siblings, 0 replies; 4+ messages in thread
From: sunshijie @ 2024-05-16 10:13 UTC (permalink / raw)
  To: jaegeuk, chao, linux-f2fs-devel, linux-kernel; +Cc: sunshijie

When thread A calls kill_f2fs_super, Thread A first executes the code sbi->node_inode = NULL;
Then thread A may submit a bio to the function iput(sbi->meta_inode);
Then thread A enters the process D state,
Now that the bio submitted by thread A is complete, it calls f2fs_write_end_io and may trigger null-ptr-deref in NODE_MAPPING.

Thread A                                          IRQ context
- f2fs_put_super
 - sbi->node_inode = NULL;
 - iput(sbi->meta_inode);
  - iput_final
   - write_inode_now
    - writeback_single_inode
     - __writeback_single_inode
      - filemap_fdatawait
       - filemap_fdatawait_range
        - __kcfi_typeid_free_transhuge_page
         - __filemap_fdatawait_range
          - wait_on_page_writeback
           - folio_wait_writeback
            - folio_wait_bit
             - folio_wait_bit_common
              - io_schedule

                                                  - __handle_irq_event_percpu
                                                   - ufs_qcom_mcq_esi_handler
                                                    - ufshcd_mcq_poll_cqe_nolock
                                                     - ufshcd_compl_one_cqe
                                                      - scsi_done
                                                       - scsi_done_internal
                                                        - blk_mq_complete_request
                                                         - scsi_complete
                                                          - scsi_finish_command
                                                           - scsi_io_completion
                                                            - scsi_end_request
                                                             - blk_update_request
                                                              - bio_endio
                                                               - f2fs_write_end_io
                                                                - NODE_MAPPING(sbi)

Signed-off-by: sunshijie <sunshijie@xiaomi.com>
---
 fs/f2fs/super.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index adffc9b80a9c..62d4f229f601 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1642,9 +1642,9 @@ static void f2fs_put_super(struct super_block *sb)
 	f2fs_destroy_compress_inode(sbi);
 
 	iput(sbi->node_inode);
-	sbi->node_inode = NULL;
-
 	iput(sbi->meta_inode);
+
+	sbi->node_inode = NULL;
 	sbi->meta_inode = NULL;
 
 	mutex_unlock(&sbi->umount_mutex);
-- 
2.34.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] f2fs: fix panic in f2fs_put_super
@ 2024-05-16  8:40 sunshijie
  0 siblings, 0 replies; 4+ messages in thread
From: sunshijie @ 2024-05-16  8:40 UTC (permalink / raw)
  To: jaegeuk, chao, linux-f2fs-devel, linux-kernel; +Cc: sunshijie

When thread A calls kill_f2fs_super, thread A may submit a bio to the function iput(sbi->node_inode);
Then thread A enters the process D state, and thread B may also call kill_f2fs_super and execute the code sbi->node_inode = NULL;
Now that the bio submitted by thread A is complete, it calls f2fs_write_end_io and may trigger null-ptr-deref in NODE_MAPPING.

Thread A                                          Thread B                         IRQ context
- f2fs_put_super
 - iput(sbi->node_inode)
  - iput_final
   - write_inode_now
    - writeback_single_inode
     - __writeback_single_inode
      - filemap_fdatawait
       - filemap_fdatawait_range
        - __kcfi_typeid_free_transhuge_page
         - __filemap_fdatawait_range
          - wait_on_page_writeback
           - folio_wait_writeback
            - folio_wait_bit
             - folio_wait_bit_common
              - io_schedule
                                                  - f2fs_put_super
                                                   - sbi->node_inode = NULL
                                                                                   - __handle_irq_event_percpu
                                                                                    - ufs_qcom_mcq_esi_handler
                                                                                     - ufshcd_mcq_poll_cqe_nolock
                                                                                      - ufshcd_compl_one_cqe
                                                                                       - scsi_done
                                                                                        - scsi_done_internal
                                                                                         - blk_mq_complete_request
                                                                                          - scsi_complete
                                                                                           - scsi_finish_command
                                                                                            - scsi_io_completion
                                                                                             - scsi_end_request
                                                                                              - blk_update_request
                                                                                               - bio_endio
                                                                                                - f2fs_write_end_io
                                                                                                 - NODE_MAPPING(sbi)

Signed-off-by: sunshijie <sunshijie@xiaomi.com>
---
 fs/f2fs/super.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a4bc26dfdb1a..adffc9b80a9c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1618,7 +1618,6 @@ static void f2fs_put_super(struct super_block *sb)
 	f2fs_release_ino_entry(sbi, true);
 
 	f2fs_leave_shrinker(sbi);
-	mutex_unlock(&sbi->umount_mutex);
 
 	/* our cp_error case, we can wait for any writeback page */
 	f2fs_flush_merged_writes(sbi);
@@ -1648,6 +1647,8 @@ static void f2fs_put_super(struct super_block *sb)
 	iput(sbi->meta_inode);
 	sbi->meta_inode = NULL;
 
+	mutex_unlock(&sbi->umount_mutex);
+
 	/*
 	 * iput() can update stat information, if f2fs_write_checkpoint()
 	 * above failed with error.
-- 
2.34.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-05-16 10:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-16  8:55 [PATCH] f2fs: fix panic in f2fs_put_super sunshijie
2024-05-16  9:32 ` Chao Yu
  -- strict thread matches above, loose matches on Subject: below --
2024-05-16 10:13 sunshijie
2024-05-16  8:40 sunshijie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®