• Sahitya Tummala's avatar
    jbd2: fix use after free in kjournald2() · dbfcef6b
    Sahitya Tummala authored
    Below is the synchronization issue between unmount and kjournald2
    contexts, which results into use after free issue in kjournald2().
    Fix this issue by using journal->j_state_lock to synchronize the
    wait_event() done in journal_kill_thread() and the wake_up() done
    in kjournald2().
    
    TASK 1:
    umount cmd:
       |--jbd2_journal_destroy() {
           |--journal_kill_thread() {
                write_lock(&journal->j_state_lock);
    	    journal->j_flags |= JBD2_UNMOUNT;
    	    ...
    	    write_unlock(&journal->j_state_lock);
    	    wake_up(&journal->j_wait_commit);	   TASK 2 wakes up here:
    	    					   kjournald2() {
    						     ...
    						     checks JBD2_UNMOUNT flag and calls goto end-loop;
    						     ...
    						     end_loop:
    						       write_unlock(&journal->j_state_lock);
    						       journal->j_task = NULL; --> If this thread gets
    						       pre-empted here, then TASK 1 wait_event will
    						       exit even before this thread is completely
    						       done.
    	    wait_event(journal->j_wait_done_commit, journal->j_task == NULL);
    	    ...
    	    write_lock(&journal->j_state_lock);
    	    write_unlock(&journal->j_state_lock);
    	  }
           |--kfree(journal);
         }
    }
    						       wake_up(&journal->j_wait_done_commit); --> this step
    						       now results into use after free issue.
    						   }
    Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
    Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
    dbfcef6b
journal.c 74.2 KB