Commit e580abeb authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Stefan Bader

jbd2: fix use after free in kjournald2()

BugLink: http://bugs.launchpad.net/bugs/1768474

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>
Signed-off-by: default avatarJuerg Haefliger <juergh@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 2775df89
...@@ -275,11 +275,11 @@ static int kjournald2(void *arg) ...@@ -275,11 +275,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