From: Greg Kroah-Hartman Date: Wed, 21 Nov 2012 18:01:13 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.0.53~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=657d673d17bbd8e77c185c04365710ad76c8b0a2;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: reiserfs-fix-lock-ordering-during-remount.patch reiserfs-move-quota-calls-out-of-write-lock.patch reiserfs-protect-reiserfs_quota_on-with-write-lock.patch reiserfs-protect-reiserfs_quota_write-with-write-lock.patch selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch --- diff --git a/queue-3.4/reiserfs-fix-lock-ordering-during-remount.patch b/queue-3.4/reiserfs-fix-lock-ordering-during-remount.patch new file mode 100644 index 00000000000..af8c88b250e --- /dev/null +++ b/queue-3.4/reiserfs-fix-lock-ordering-during-remount.patch @@ -0,0 +1,114 @@ +From 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 13 Nov 2012 14:55:52 +0100 +Subject: reiserfs: Fix lock ordering during remount + +From: Jan Kara + +commit 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 upstream. + +When remounting reiserfs dquot_suspend() or dquot_resume() can be called. +These functions take dqonoff_mutex which ranks above write lock so we have +to drop it before calling into quota code. + +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/reiserfs/super.c | 27 ++++++++++++++++++++------- + 1 file changed, 20 insertions(+), 7 deletions(-) + +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -1292,7 +1292,7 @@ static int reiserfs_remount(struct super + kfree(qf_names[i]); + #endif + err = -EINVAL; +- goto out_err; ++ goto out_unlock; + } + #ifdef CONFIG_QUOTA + handle_quota_files(s, qf_names, &qfmt); +@@ -1336,7 +1336,7 @@ static int reiserfs_remount(struct super + if (blocks) { + err = reiserfs_resize(s, blocks); + if (err != 0) +- goto out_err; ++ goto out_unlock; + } + + if (*mount_flags & MS_RDONLY) { +@@ -1346,9 +1346,15 @@ static int reiserfs_remount(struct super + /* it is read-only already */ + goto out_ok; + ++ /* ++ * Drop write lock. Quota will retake it when needed and lock ++ * ordering requires calling dquot_suspend() without it. ++ */ ++ reiserfs_write_unlock(s); + err = dquot_suspend(s, -1); + if (err < 0) + goto out_err; ++ reiserfs_write_lock(s); + + /* try to remount file system with read-only permissions */ + if (sb_umount_state(rs) == REISERFS_VALID_FS +@@ -1358,7 +1364,7 @@ static int reiserfs_remount(struct super + + err = journal_begin(&th, s, 10); + if (err) +- goto out_err; ++ goto out_unlock; + + /* Mounting a rw partition read-only. */ + reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); +@@ -1373,7 +1379,7 @@ static int reiserfs_remount(struct super + + if (reiserfs_is_journal_aborted(journal)) { + err = journal->j_errno; +- goto out_err; ++ goto out_unlock; + } + + handle_data_mode(s, mount_options); +@@ -1382,7 +1388,7 @@ static int reiserfs_remount(struct super + s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ + err = journal_begin(&th, s, 10); + if (err) +- goto out_err; ++ goto out_unlock; + + /* Mount a partition which is read-only, read-write */ + reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); +@@ -1399,11 +1405,17 @@ static int reiserfs_remount(struct super + SB_JOURNAL(s)->j_must_wait = 1; + err = journal_end(&th, s, 10); + if (err) +- goto out_err; ++ goto out_unlock; + s->s_dirt = 0; + + if (!(*mount_flags & MS_RDONLY)) { ++ /* ++ * Drop write lock. Quota will retake it when needed and lock ++ * ordering requires calling dquot_resume() without it. ++ */ ++ reiserfs_write_unlock(s); + dquot_resume(s, -1); ++ reiserfs_write_lock(s); + finish_unfinished(s); + reiserfs_xattr_init(s, *mount_flags); + } +@@ -1413,9 +1425,10 @@ out_ok: + reiserfs_write_unlock(s); + return 0; + ++out_unlock: ++ reiserfs_write_unlock(s); + out_err: + kfree(new_opts); +- reiserfs_write_unlock(s); + return err; + } + diff --git a/queue-3.4/reiserfs-move-quota-calls-out-of-write-lock.patch b/queue-3.4/reiserfs-move-quota-calls-out-of-write-lock.patch new file mode 100644 index 00000000000..62dfda3fc79 --- /dev/null +++ b/queue-3.4/reiserfs-move-quota-calls-out-of-write-lock.patch @@ -0,0 +1,176 @@ +From 7af11686933726e99af22901d622f9e161404e6b Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 13 Nov 2012 17:05:14 +0100 +Subject: reiserfs: Move quota calls out of write lock + +From: Jan Kara + +commit 7af11686933726e99af22901d622f9e161404e6b upstream. + +Calls into highlevel quota code cannot happen under the write lock. These +calls take dqio_mutex which ranks above write lock. So drop write lock +before calling back into quota code. + +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/reiserfs/inode.c | 10 +++++++--- + fs/reiserfs/stree.c | 4 ++++ + fs/reiserfs/super.c | 18 ++++++++++++++---- + 3 files changed, 25 insertions(+), 7 deletions(-) + +--- a/fs/reiserfs/inode.c ++++ b/fs/reiserfs/inode.c +@@ -1788,8 +1788,9 @@ int reiserfs_new_inode(struct reiserfs_t + + BUG_ON(!th->t_trans_id); + +- dquot_initialize(inode); ++ reiserfs_write_unlock(inode->i_sb); + err = dquot_alloc_inode(inode); ++ reiserfs_write_lock(inode->i_sb); + if (err) + goto out_end_trans; + if (!dir->i_nlink) { +@@ -1985,8 +1986,10 @@ int reiserfs_new_inode(struct reiserfs_t + + out_end_trans: + journal_end(th, th->t_super, th->t_blocks_allocated); ++ reiserfs_write_unlock(inode->i_sb); + /* Drop can be outside and it needs more credits so it's better to have it outside */ + dquot_drop(inode); ++ reiserfs_write_lock(inode->i_sb); + inode->i_flags |= S_NOQUOTA; + make_bad_inode(inode); + +@@ -3109,10 +3112,9 @@ int reiserfs_setattr(struct dentry *dent + /* must be turned off for recursive notify_change calls */ + ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); + +- depth = reiserfs_write_lock_once(inode->i_sb); + if (is_quota_modification(inode, attr)) + dquot_initialize(inode); +- ++ depth = reiserfs_write_lock_once(inode->i_sb); + if (attr->ia_valid & ATTR_SIZE) { + /* version 2 items will be caught by the s_maxbytes check + ** done for us in vmtruncate +@@ -3176,7 +3178,9 @@ int reiserfs_setattr(struct dentry *dent + error = journal_begin(&th, inode->i_sb, jbegin_count); + if (error) + goto out; ++ reiserfs_write_unlock_once(inode->i_sb, depth); + error = dquot_transfer(inode, attr); ++ depth = reiserfs_write_lock_once(inode->i_sb); + if (error) { + journal_end(&th, inode->i_sb, jbegin_count); + goto out; +--- a/fs/reiserfs/stree.c ++++ b/fs/reiserfs/stree.c +@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reis + key2type(&(key->on_disk_key))); + #endif + ++ reiserfs_write_unlock(inode->i_sb); + retval = dquot_alloc_space_nodirty(inode, pasted_size); ++ reiserfs_write_lock(inode->i_sb); + if (retval) { + pathrelse(search_path); + return retval; +@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs + "reiserquota insert_item(): allocating %u id=%u type=%c", + quota_bytes, inode->i_uid, head2type(ih)); + #endif ++ reiserfs_write_unlock(inode->i_sb); + /* We can't dirty inode here. It would be immediately written but + * appropriate stat item isn't inserted yet... */ + retval = dquot_alloc_space_nodirty(inode, quota_bytes); ++ reiserfs_write_lock(inode->i_sb); + if (retval) { + pathrelse(path); + return retval; +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -256,7 +256,9 @@ static int finish_unfinished(struct supe + retval = remove_save_link_only(s, &save_link_key, 0); + continue; + } ++ reiserfs_write_unlock(s); + dquot_initialize(inode); ++ reiserfs_write_lock(s); + + if (truncate && S_ISDIR(inode->i_mode)) { + /* We got a truncate request for a dir which is impossible. +@@ -2062,13 +2064,15 @@ static int reiserfs_write_dquot(struct d + REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); + if (ret) + goto out; ++ reiserfs_write_unlock(dquot->dq_sb); + ret = dquot_commit(dquot); ++ reiserfs_write_lock(dquot->dq_sb); + err = + journal_end(&th, dquot->dq_sb, + REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); + if (!ret && err) + ret = err; +- out: ++out: + reiserfs_write_unlock(dquot->dq_sb); + return ret; + } +@@ -2084,13 +2088,15 @@ static int reiserfs_acquire_dquot(struct + REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); + if (ret) + goto out; ++ reiserfs_write_unlock(dquot->dq_sb); + ret = dquot_acquire(dquot); ++ reiserfs_write_lock(dquot->dq_sb); + err = + journal_end(&th, dquot->dq_sb, + REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); + if (!ret && err) + ret = err; +- out: ++out: + reiserfs_write_unlock(dquot->dq_sb); + return ret; + } +@@ -2104,19 +2110,21 @@ static int reiserfs_release_dquot(struct + ret = + journal_begin(&th, dquot->dq_sb, + REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); ++ reiserfs_write_unlock(dquot->dq_sb); + if (ret) { + /* Release dquot anyway to avoid endless cycle in dqput() */ + dquot_release(dquot); + goto out; + } + ret = dquot_release(dquot); ++ reiserfs_write_lock(dquot->dq_sb); + err = + journal_end(&th, dquot->dq_sb, + REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + if (!ret && err) + ret = err; +- out: + reiserfs_write_unlock(dquot->dq_sb); ++out: + return ret; + } + +@@ -2141,11 +2149,13 @@ static int reiserfs_write_info(struct su + ret = journal_begin(&th, sb, 2); + if (ret) + goto out; ++ reiserfs_write_unlock(sb); + ret = dquot_commit_info(sb, type); ++ reiserfs_write_lock(sb); + err = journal_end(&th, sb, 2); + if (!ret && err) + ret = err; +- out: ++out: + reiserfs_write_unlock(sb); + return ret; + } diff --git a/queue-3.4/reiserfs-protect-reiserfs_quota_on-with-write-lock.patch b/queue-3.4/reiserfs-protect-reiserfs_quota_on-with-write-lock.patch new file mode 100644 index 00000000000..794ffc1cb95 --- /dev/null +++ b/queue-3.4/reiserfs-protect-reiserfs_quota_on-with-write-lock.patch @@ -0,0 +1,48 @@ +From b9e06ef2e8706fe669b51f4364e3aeed58639eb2 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 13 Nov 2012 16:34:17 +0100 +Subject: reiserfs: Protect reiserfs_quota_on() with write lock + +From: Jan Kara + +commit b9e06ef2e8706fe669b51f4364e3aeed58639eb2 upstream. + +In reiserfs_quota_on() we do quite some work - for example unpacking +tail of a quota file. Thus we have to hold write lock until a moment +we call back into the quota code. + +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/reiserfs/super.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -2170,8 +2170,11 @@ static int reiserfs_quota_on(struct supe + struct reiserfs_transaction_handle th; + int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; + +- if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) +- return -EINVAL; ++ reiserfs_write_lock(sb); ++ if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { ++ err = -EINVAL; ++ goto out; ++ } + + /* Quotafile not on the same filesystem? */ + if (path->dentry->d_sb != sb) { +@@ -2213,8 +2216,10 @@ static int reiserfs_quota_on(struct supe + if (err) + goto out; + } +- err = dquot_quota_on(sb, type, format_id, path); ++ reiserfs_write_unlock(sb); ++ return dquot_quota_on(sb, type, format_id, path); + out: ++ reiserfs_write_unlock(sb); + return err; + } + diff --git a/queue-3.4/reiserfs-protect-reiserfs_quota_write-with-write-lock.patch b/queue-3.4/reiserfs-protect-reiserfs_quota_write-with-write-lock.patch new file mode 100644 index 00000000000..625858dd20f --- /dev/null +++ b/queue-3.4/reiserfs-protect-reiserfs_quota_write-with-write-lock.patch @@ -0,0 +1,46 @@ +From 361d94a338a3fd0cee6a4ea32bbc427ba228e628 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 13 Nov 2012 18:25:38 +0100 +Subject: reiserfs: Protect reiserfs_quota_write() with write lock + +From: Jan Kara + +commit 361d94a338a3fd0cee6a4ea32bbc427ba228e628 upstream. + +Calls into reiserfs journalling code and reiserfs_get_block() need to +be protected with write lock. We remove write lock around calls to high +level quota code in the next patch so these paths would suddently become +unprotected. + +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/reiserfs/super.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/reiserfs/super.c ++++ b/fs/reiserfs/super.c +@@ -2303,7 +2303,9 @@ static ssize_t reiserfs_quota_write(stru + tocopy = sb->s_blocksize - offset < towrite ? + sb->s_blocksize - offset : towrite; + tmp_bh.b_state = 0; ++ reiserfs_write_lock(sb); + err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); ++ reiserfs_write_unlock(sb); + if (err) + goto out; + if (offset || tocopy != sb->s_blocksize) +@@ -2319,10 +2321,12 @@ static ssize_t reiserfs_quota_write(stru + flush_dcache_page(bh->b_page); + set_buffer_uptodate(bh); + unlock_buffer(bh); ++ reiserfs_write_lock(sb); + reiserfs_prepare_for_journal(sb, bh, 1); + journal_mark_dirty(current->journal_info, sb, bh); + if (!journal_quota) + reiserfs_add_ordered_list(inode, bh); ++ reiserfs_write_unlock(sb); + brelse(bh); + offset = 0; + towrite -= tocopy; diff --git a/queue-3.4/selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch b/queue-3.4/selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch new file mode 100644 index 00000000000..4b669439146 --- /dev/null +++ b/queue-3.4/selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch @@ -0,0 +1,64 @@ +From 88a693b5c1287be4da937699cb82068ce9db0135 Mon Sep 17 00:00:00 2001 +From: Dave Jones +Date: Thu, 8 Nov 2012 16:09:27 -0800 +Subject: selinux: fix sel_netnode_insert() suspicious rcu dereference + +From: Dave Jones + +commit 88a693b5c1287be4da937699cb82068ce9db0135 upstream. + +=============================== +[ INFO: suspicious RCU usage. ] +3.5.0-rc1+ #63 Not tainted +------------------------------- +security/selinux/netnode.c:178 suspicious rcu_dereference_check() usage! + +other info that might help us debug this: + +rcu_scheduler_active = 1, debug_locks = 0 +1 lock held by trinity-child1/8750: + #0: (sel_netnode_lock){+.....}, at: [] sel_netnode_sid+0x16a/0x3e0 + +stack backtrace: +Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63 +Call Trace: + [] lockdep_rcu_suspicious+0xfd/0x130 + [] sel_netnode_sid+0x3b1/0x3e0 + [] ? sel_netnode_find+0x1a0/0x1a0 + [] selinux_socket_bind+0xf6/0x2c0 + [] ? trace_hardirqs_off+0xd/0x10 + [] ? lock_release_holdtime.part.9+0x15/0x1a0 + [] ? lock_hrtimer_base+0x31/0x60 + [] security_socket_bind+0x16/0x20 + [] sys_bind+0x7a/0x100 + [] ? sysret_check+0x22/0x5d + [] ? trace_hardirqs_on_caller+0x10d/0x1a0 + [] ? trace_hardirqs_on_thunk+0x3a/0x3f + [] system_call_fastpath+0x16/0x1b + +This patch below does what Paul McKenney suggested in the previous thread. + +Signed-off-by: Dave Jones +Reviewed-by: Paul E. McKenney +Acked-by: Paul Moore +Cc: Eric Paris +Signed-off-by: Andrew Morton +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + security/selinux/netnode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/security/selinux/netnode.c ++++ b/security/selinux/netnode.c +@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct se + if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { + struct sel_netnode *tail; + tail = list_entry( +- rcu_dereference(sel_netnode_hash[idx].list.prev), ++ rcu_dereference_protected(sel_netnode_hash[idx].list.prev, ++ lockdep_is_held(&sel_netnode_lock)), + struct sel_netnode, list); + list_del_rcu(&tail->list); + kfree_rcu(tail, rcu); diff --git a/queue-3.4/series b/queue-3.4/series index bd53597b19b..cfe9f49cbf8 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -48,3 +48,8 @@ sky2-fix-for-interrupt-handler.patch s390-signal-set-correct-address-space-control.patch drm-i915-fix-overlay-on-i830m.patch nfs-wait-for-session-recovery-to-finish-before-returning.patch +reiserfs-fix-lock-ordering-during-remount.patch +reiserfs-protect-reiserfs_quota_on-with-write-lock.patch +reiserfs-move-quota-calls-out-of-write-lock.patch +reiserfs-protect-reiserfs_quota_write-with-write-lock.patch +selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch