diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-01 16:36:40 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-01 16:36:40 +0900 |
commit | c70deae4efea09138e307d6915510c940d2063a5 (patch) | |
tree | df4d3cc04e2c61e390031d0104c228df0a788cbd | |
parent | 2dabec14ce5d7411cbefc07531ac833363de25a0 (diff) | |
download | stable-queue-c70deae4efea09138e307d6915510c940d2063a5.tar.gz |
.39 patches
-rw-r--r-- | queue-2.6.39/ext4-fix-possible-use-after-free-in.patch | 48 | ||||
-rw-r--r-- | queue-2.6.39/ext4-use-schedule_timeout_interruptible-for-waiting-in.patch | 147 | ||||
-rw-r--r-- | queue-2.6.39/series | 2 |
3 files changed, 197 insertions, 0 deletions
diff --git a/queue-2.6.39/ext4-fix-possible-use-after-free-in.patch b/queue-2.6.39/ext4-fix-possible-use-after-free-in.patch new file mode 100644 index 0000000000..ce01a8ba8e --- /dev/null +++ b/queue-2.6.39/ext4-fix-possible-use-after-free-in.patch @@ -0,0 +1,48 @@ +From 1bb933fb1fa8e4cb337a0d5dfd2ff4c0dc2073e8 Mon Sep 17 00:00:00 2001 +From: Lukas Czerner <lczerner@redhat.com> +Date: Fri, 20 May 2011 13:55:29 -0400 +Subject: ext4: fix possible use-after-free in + ext4_remove_li_request() + +From: Lukas Czerner <lczerner@redhat.com> + +commit 1bb933fb1fa8e4cb337a0d5dfd2ff4c0dc2073e8 upstream. + +We need to take reference to the s_li_request after we take a mutex, +because it might be freed since then, hence result in accessing old +already freed memory. Also we should protect the whole +ext4_remove_li_request() because ext4_li_info might be in the process of +being freed in ext4_lazyinit_thread(). + +Signed-off-by: Lukas Czerner <lczerner@redhat.com> +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Reviewed-by: Eric Sandeen <sandeen@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + fs/ext4/super.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2730,14 +2730,16 @@ static void ext4_remove_li_request(struc + + static void ext4_unregister_li_request(struct super_block *sb) + { +- struct ext4_li_request *elr = EXT4_SB(sb)->s_li_request; +- +- if (!ext4_li_info) ++ mutex_lock(&ext4_li_mtx); ++ if (!ext4_li_info) { ++ mutex_unlock(&ext4_li_mtx); + return; ++ } + + mutex_lock(&ext4_li_info->li_list_mtx); +- ext4_remove_li_request(elr); ++ ext4_remove_li_request(EXT4_SB(sb)->s_li_request); + mutex_unlock(&ext4_li_info->li_list_mtx); ++ mutex_unlock(&ext4_li_mtx); + } + + static struct task_struct *ext4_lazyinit_task; diff --git a/queue-2.6.39/ext4-use-schedule_timeout_interruptible-for-waiting-in.patch b/queue-2.6.39/ext4-use-schedule_timeout_interruptible-for-waiting-in.patch new file mode 100644 index 0000000000..bc7a1cc7c2 --- /dev/null +++ b/queue-2.6.39/ext4-use-schedule_timeout_interruptible-for-waiting-in.patch @@ -0,0 +1,147 @@ +From 4ed5c033c11b33149d993734a6a8de1016e8f03f Mon Sep 17 00:00:00 2001 +From: Lukas Czerner <lczerner@redhat.com> +Date: Fri, 20 May 2011 13:49:04 -0400 +Subject: ext4: Use schedule_timeout_interruptible() for waiting in + lazyinit thread + +From: Lukas Czerner <lczerner@redhat.com> + +commit 4ed5c033c11b33149d993734a6a8de1016e8f03f upstream. + +In order to make lazyinit eat approx. 10% of io bandwidth at max, we +are sleeping between zeroing each single inode table. For that purpose +we are using timer which wakes up thread when it expires. It is set +via add_timer() and this may cause troubles in the case that thread +has been woken up earlier and in next iteration we call add_timer() on +still running timer hence hitting BUG_ON in add_timer(). We could fix +that by using mod_timer() instead however we can use +schedule_timeout_interruptible() for waiting and hence simplifying +things a lot. + +This commit exchange the old "waiting mechanism" with simple +schedule_timeout_interruptible(), setting the time to sleep. Hence we +do not longer need li_wait_daemon waiting queue and others, so get rid +of it. + +Addresses-Red-Hat-Bugzilla: #699708 + +Signed-off-by: Lukas Czerner <lczerner@redhat.com> +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Reviewed-by: Eric Sandeen <sandeen@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + fs/ext4/ext4.h | 4 ---- + fs/ext4/super.c | 31 ++++++------------------------- + 2 files changed, 6 insertions(+), 29 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1590,12 +1590,8 @@ void ext4_get_group_no_and_offset(struct + */ + struct ext4_lazy_init { + unsigned long li_state; +- +- wait_queue_head_t li_wait_daemon; + wait_queue_head_t li_wait_task; +- struct timer_list li_timer; + struct task_struct *li_task; +- + struct list_head li_request_list; + struct mutex li_list_mtx; + }; +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2659,12 +2659,6 @@ static void print_daily_error_info(unsig + mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ + } + +-static void ext4_lazyinode_timeout(unsigned long data) +-{ +- struct task_struct *p = (struct task_struct *)data; +- wake_up_process(p); +-} +- + /* Find next suitable group and run ext4_init_inode_table */ + static int ext4_run_li_request(struct ext4_li_request *elr) + { +@@ -2712,7 +2706,7 @@ static int ext4_run_li_request(struct ex + + /* + * Remove lr_request from the list_request and free the +- * request tructure. Should be called with li_list_mtx held ++ * request structure. Should be called with li_list_mtx held + */ + static void ext4_remove_li_request(struct ext4_li_request *elr) + { +@@ -2758,14 +2752,10 @@ static int ext4_lazyinit_thread(void *ar + struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg; + struct list_head *pos, *n; + struct ext4_li_request *elr; +- unsigned long next_wakeup; +- DEFINE_WAIT(wait); ++ unsigned long next_wakeup, cur; + + BUG_ON(NULL == eli); + +- eli->li_timer.data = (unsigned long)current; +- eli->li_timer.function = ext4_lazyinode_timeout; +- + eli->li_task = current; + wake_up(&eli->li_wait_task); + +@@ -2799,19 +2789,15 @@ cont_thread: + if (freezing(current)) + refrigerator(); + +- if ((time_after_eq(jiffies, next_wakeup)) || ++ cur = jiffies; ++ if ((time_after_eq(cur, next_wakeup)) || + (MAX_JIFFY_OFFSET == next_wakeup)) { + cond_resched(); + continue; + } + +- eli->li_timer.expires = next_wakeup; +- add_timer(&eli->li_timer); +- prepare_to_wait(&eli->li_wait_daemon, &wait, +- TASK_INTERRUPTIBLE); +- if (time_before(jiffies, next_wakeup)) +- schedule(); +- finish_wait(&eli->li_wait_daemon, &wait); ++ schedule_timeout_interruptible(next_wakeup - cur); ++ + if (kthread_should_stop()) { + ext4_clear_request_list(); + goto exit_thread; +@@ -2835,12 +2821,10 @@ exit_thread: + goto cont_thread; + } + mutex_unlock(&eli->li_list_mtx); +- del_timer_sync(&ext4_li_info->li_timer); + eli->li_task = NULL; + wake_up(&eli->li_wait_task); + + kfree(ext4_li_info); +- ext4_lazyinit_task = NULL; + ext4_li_info = NULL; + mutex_unlock(&ext4_li_mtx); + +@@ -2868,7 +2852,6 @@ static int ext4_run_lazyinit_thread(void + if (IS_ERR(ext4_lazyinit_task)) { + int err = PTR_ERR(ext4_lazyinit_task); + ext4_clear_request_list(); +- del_timer_sync(&ext4_li_info->li_timer); + kfree(ext4_li_info); + ext4_li_info = NULL; + printk(KERN_CRIT "EXT4: error %d creating inode table " +@@ -2917,9 +2900,7 @@ static int ext4_li_info_new(void) + INIT_LIST_HEAD(&eli->li_request_list); + mutex_init(&eli->li_list_mtx); + +- init_waitqueue_head(&eli->li_wait_daemon); + init_waitqueue_head(&eli->li_wait_task); +- init_timer(&eli->li_timer); + eli->li_state |= EXT4_LAZYINIT_QUIT; + + ext4_li_info = eli; diff --git a/queue-2.6.39/series b/queue-2.6.39/series index 6a0c723bcb..9f21d6c849 100644 --- a/queue-2.6.39/series +++ b/queue-2.6.39/series @@ -160,3 +160,5 @@ xen-setup-fix-for-incorrect-xen_extra_mem_start.patch xen-setup-ignore-e820_unusable-when-setting-1-1-mappings.patch xen-mmu-fix-a-race-window-causing-leave_mm-bug.patch block-don-t-block-events-on-excl-write-for-non-optical.patch +ext4-fix-possible-use-after-free-in.patch +ext4-use-schedule_timeout_interruptible-for-waiting-in.patch |