Commit cff3a5f2 authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Greg Kroah-Hartman

jbd2: fix use after free in kjournald2()

commit dbfcef6b upstream.

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>
Cc: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ff738afb
...@@ -276,11 +276,11 @@ static int kjournald2(void *arg) ...@@ -276,11 +276,11 @@ static int kjournald2(void *arg)
goto loop; goto loop;
end_loop: end_loop:
write_unlock(&journal->j_state_lock);
del_timer_sync(&journal->j_commit_timer); del_timer_sync(&journal->j_commit_timer);
journal->j_task = NULL; journal->j_task = NULL;
wake_up(&journal->j_wait_done_commit); wake_up(&journal->j_wait_done_commit);
jbd_debug(1, "Journal thread exiting.\n"); jbd_debug(1, "Journal thread exiting.\n");
write_unlock(&journal->j_state_lock);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment