]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 18:01:13 +0000 (10:01 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Nov 2012 18:01:13 +0000 (10:01 -0800)
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

queue-3.4/reiserfs-fix-lock-ordering-during-remount.patch [new file with mode: 0644]
queue-3.4/reiserfs-move-quota-calls-out-of-write-lock.patch [new file with mode: 0644]
queue-3.4/reiserfs-protect-reiserfs_quota_on-with-write-lock.patch [new file with mode: 0644]
queue-3.4/reiserfs-protect-reiserfs_quota_write-with-write-lock.patch [new file with mode: 0644]
queue-3.4/selinux-fix-sel_netnode_insert-suspicious-rcu-dereference.patch [new file with mode: 0644]
queue-3.4/series

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 (file)
index 0000000..af8c88b
--- /dev/null
@@ -0,0 +1,114 @@
+From 3bb3e1fc47aca554e7e2cc4deeddc24750987ac2 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 13 Nov 2012 14:55:52 +0100
+Subject: reiserfs: Fix lock ordering during remount
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..62dfda3
--- /dev/null
@@ -0,0 +1,176 @@
+From 7af11686933726e99af22901d622f9e161404e6b Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 13 Nov 2012 17:05:14 +0100
+Subject: reiserfs: Move quota calls out of write lock
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..794ffc1
--- /dev/null
@@ -0,0 +1,48 @@
+From b9e06ef2e8706fe669b51f4364e3aeed58639eb2 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 13 Nov 2012 16:34:17 +0100
+Subject: reiserfs: Protect reiserfs_quota_on() with write lock
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..625858d
--- /dev/null
@@ -0,0 +1,46 @@
+From 361d94a338a3fd0cee6a4ea32bbc427ba228e628 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 13 Nov 2012 18:25:38 +0100
+Subject: reiserfs: Protect reiserfs_quota_write() with write lock
+
+From: Jan Kara <jack@suse.cz>
+
+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 <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..4b66943
--- /dev/null
@@ -0,0 +1,64 @@
+From 88a693b5c1287be4da937699cb82068ce9db0135 Mon Sep 17 00:00:00 2001
+From: Dave Jones <davej@redhat.com>
+Date: Thu, 8 Nov 2012 16:09:27 -0800
+Subject: selinux: fix sel_netnode_insert() suspicious rcu dereference
+
+From: Dave Jones <davej@redhat.com>
+
+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: [<ffffffff812d8f8a>] sel_netnode_sid+0x16a/0x3e0
+
+stack backtrace:
+Pid: 8750, comm: trinity-child1 Not tainted 3.5.0-rc1+ #63
+Call Trace:
+ [<ffffffff810cec2d>] lockdep_rcu_suspicious+0xfd/0x130
+ [<ffffffff812d91d1>] sel_netnode_sid+0x3b1/0x3e0
+ [<ffffffff812d8e20>] ? sel_netnode_find+0x1a0/0x1a0
+ [<ffffffff812d24a6>] selinux_socket_bind+0xf6/0x2c0
+ [<ffffffff810cd1dd>] ? trace_hardirqs_off+0xd/0x10
+ [<ffffffff810cdb55>] ? lock_release_holdtime.part.9+0x15/0x1a0
+ [<ffffffff81093841>] ? lock_hrtimer_base+0x31/0x60
+ [<ffffffff812c9536>] security_socket_bind+0x16/0x20
+ [<ffffffff815550ca>] sys_bind+0x7a/0x100
+ [<ffffffff816c03d5>] ? sysret_check+0x22/0x5d
+ [<ffffffff810d392d>] ? trace_hardirqs_on_caller+0x10d/0x1a0
+ [<ffffffff8133b09e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
+ [<ffffffff816c03a9>] system_call_fastpath+0x16/0x1b
+
+This patch below does what Paul McKenney suggested in the previous thread.
+
+Signed-off-by: Dave Jones <davej@redhat.com>
+Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Acked-by: Paul Moore <paul@paul-moore.com>
+Cc: Eric Paris <eparis@parisplace.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);
index bd53597b19b6c8701beb82ab3d04308b99fec60d..cfe9f49cbf8f4f4880e6102c0c4ea89d1c41d0fc 100644 (file)
@@ -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