From: Greg Kroah-Hartman Date: Fri, 22 Nov 2013 19:54:01 +0000 (-0800) Subject: 3.4-stable patches X-Git-Tag: v3.11.10~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50e5be407268bce9bdc4f4e965bf6aae086685c9;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches added patches: nfs-don-t-allow-nfs_find_actor-to-match-inodes-of-the-wrong-type.patch vfs-proc-guarantee-unique-inodes-in-proc.patch --- diff --git a/queue-3.4/nfs-don-t-allow-nfs_find_actor-to-match-inodes-of-the-wrong-type.patch b/queue-3.4/nfs-don-t-allow-nfs_find_actor-to-match-inodes-of-the-wrong-type.patch new file mode 100644 index 00000000000..c44c6f1bfba --- /dev/null +++ b/queue-3.4/nfs-don-t-allow-nfs_find_actor-to-match-inodes-of-the-wrong-type.patch @@ -0,0 +1,106 @@ +From f6488c9ba51d65410e2dbc4345413c0d9120971e Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 27 Feb 2013 20:10:34 -0500 +Subject: nfs: don't allow nfs_find_actor to match inodes of the wrong type + +From: Jeff Layton + +commit f6488c9ba51d65410e2dbc4345413c0d9120971e upstream. + +Benny Halevy reported the following oops when testing RHEL6: + +<7>nfs_update_inode: inode 892950 mode changed, 0040755 to 0100644 +<1>BUG: unable to handle kernel NULL pointer dereference at (null) +<1>IP: [] nfs_closedir+0x15/0x30 [nfs] +<4>PGD 81448a067 PUD 831632067 PMD 0 +<4>Oops: 0000 [#1] SMP +<4>last sysfs file: /sys/kernel/mm/redhat_transparent_hugepage/enabled +<4>CPU 6 +<4>Modules linked in: fuse bonding 8021q garp ebtable_nat ebtables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi softdog bridge stp llc xt_physdev ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 xt_multiport iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 dm_round_robin dm_multipath objlayoutdriver2(U) nfs(U) lockd fscache auth_rpcgss nfs_acl sunrpc vhost_net macvtap macvlan tun kvm_intel kvm be2net igb dca ptp pps_core microcode serio_raw sg iTCO_wdt iTCO_vendor_support i7core_edac edac_core shpchp ext4 mbcache jbd2 sd_mod crc_t10dif ahci dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] +<4> +<4>Pid: 6332, comm: dd Not tainted 2.6.32-358.el6.x86_64 #1 HP ProLiant DL170e G6 /ProLiant DL170e G6 +<4>RIP: 0010:[] [] nfs_closedir+0x15/0x30 [nfs] +<4>RSP: 0018:ffff88081458bb98 EFLAGS: 00010292 +<4>RAX: ffffffffa02a52b0 RBX: 0000000000000000 RCX: 0000000000000003 +<4>RDX: ffffffffa02e45a0 RSI: ffff88081440b300 RDI: ffff88082d5f5760 +<4>RBP: ffff88081458bba8 R08: 0000000000000000 R09: 0000000000000000 +<4>R10: 0000000000000772 R11: 0000000000400004 R12: 0000000040000008 +<4>R13: ffff88082d5f5760 R14: ffff88082d6e8800 R15: ffff88082f12d780 +<4>FS: 00007f728f37e700(0000) GS:ffff8800456c0000(0000) knlGS:0000000000000000 +<4>CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +<4>CR2: 0000000000000000 CR3: 0000000831279000 CR4: 00000000000007e0 +<4>DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +<4>DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 +<4>Process dd (pid: 6332, threadinfo ffff88081458a000, task ffff88082fa0e040) +<4>Stack: +<4> 0000000040000008 ffff88081440b300 ffff88081458bbf8 ffffffff81182745 +<4> ffff88082d5f5760 ffff88082d6e8800 ffff88081458bbf8 ffffffffffffffea +<4> ffff88082f12d780 ffff88082d6e8800 ffffffffa02a50a0 ffff88082d5f5760 +<4>Call Trace: +<4> [] __fput+0xf5/0x210 +<4> [] ? do_open+0x0/0x20 [nfs] +<4> [] fput+0x25/0x30 +<4> [] __dentry_open+0x27e/0x360 +<4> [] ? inotify_d_instantiate+0x2a/0x60 +<4> [] lookup_instantiate_filp+0x69/0x90 +<4> [] nfs_intent_set_file+0x59/0x90 [nfs] +<4> [] nfs_atomic_lookup+0x1bb/0x310 [nfs] +<4> [] __lookup_hash+0x102/0x160 +<4> [] ? selinux_inode_permission+0x72/0xb0 +<4> [] lookup_hash+0x3a/0x50 +<4> [] do_filp_open+0x2eb/0xdd0 +<4> [] ? __do_page_fault+0x1ec/0x480 +<4> [] ? alloc_fd+0x92/0x160 +<4> [] do_sys_open+0x69/0x140 +<4> [] ? sys_lseek+0x66/0x80 +<4> [] sys_open+0x20/0x30 +<4> [] system_call_fastpath+0x16/0x1b +<4>Code: 65 48 8b 04 25 c8 cb 00 00 83 a8 44 e0 ff ff 01 5b 41 5c c9 c3 90 55 48 89 e5 53 48 83 ec 08 0f 1f 44 00 00 48 8b 9e a0 00 00 00 <48> 8b 3b e8 13 0c f7 ff 48 89 df e8 ab 3d ec e0 48 83 c4 08 31 +<1>RIP [] nfs_closedir+0x15/0x30 [nfs] +<4> RSP +<4>CR2: 0000000000000000 + +I think this is ultimately due to a bug on the server. The client had +previously found a directory dentry. It then later tried to do an atomic +open on a new (regular file) dentry. The attributes it got back had the +same filehandle as the previously found directory inode. It then tried +to put the filp because it failed the aops tests for O_DIRECT opens, and +oopsed here because the ctx was still NULL. + +Obviously the root cause here is a server issue, but we can take steps +to mitigate this on the client. When nfs_fhget is called, we always know +what type of inode it is. In the event that there's a broken or +malicious server on the other end of the wire, the client can end up +crashing because the wrong ops are set on it. + +Have nfs_find_actor check that the inode type is correct after checking +the fileid. The fileid check should rarely ever match, so it should only +rarely ever get to this check. In the case where we have a broken +server, we may see two different inodes with the same i_ino, but the +client should be able to cope with them without crashing. + +This should fix the oops reported here: + + https://bugzilla.redhat.com/show_bug.cgi?id=913660 + +Reported-by: Benny Halevy +Signed-off-by: Jeff Layton +Signed-off-by: Trond Myklebust +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/nfs/inode.c ++++ b/fs/nfs/inode.c +@@ -224,6 +224,8 @@ nfs_find_actor(struct inode *inode, void + + if (NFS_FILEID(inode) != fattr->fileid) + return 0; ++ if ((S_IFMT & inode->i_mode) != (S_IFMT & fattr->mode)) ++ return 0; + if (nfs_compare_fh(NFS_FH(inode), fh)) + return 0; + if (is_bad_inode(inode) || NFS_STALE(inode)) diff --git a/queue-3.4/series b/queue-3.4/series new file mode 100644 index 00000000000..9784283d288 --- /dev/null +++ b/queue-3.4/series @@ -0,0 +1,2 @@ +vfs-proc-guarantee-unique-inodes-in-proc.patch +nfs-don-t-allow-nfs_find_actor-to-match-inodes-of-the-wrong-type.patch diff --git a/queue-3.4/vfs-proc-guarantee-unique-inodes-in-proc.patch b/queue-3.4/vfs-proc-guarantee-unique-inodes-in-proc.patch new file mode 100644 index 00000000000..b7ebba35e71 --- /dev/null +++ b/queue-3.4/vfs-proc-guarantee-unique-inodes-in-proc.patch @@ -0,0 +1,77 @@ +From 4c239ba63bccc9d0f2829815a31f7972e925ab7f Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Fri, 22 Mar 2013 11:44:04 -0700 +Subject: vfs,proc: guarantee unique inodes in /proc + +From: Linus Torvalds + +commit 51f0885e5415b4cc6535e9cdcc5145bfbc134353 upstream. + +Dave Jones found another /proc issue with his Trinity tool: thanks to +the namespace model, we can have multiple /proc dentries that point to +the same inode, aliasing directories in /proc//net/ for example. + +This ends up being a total disaster, because it acts like hardlinked +directories, and causes locking problems. We rely on the topological +sort of the inodes pointed to by dentries, and if we have aliased +directories, that odering becomes unreliable. + +In short: don't do this. Multiple dentries with the same (directory) +inode is just a bad idea, and the namespace code should never have +exposed things this way. But we're kind of stuck with it. + +This solves things by just always allocating a new inode during /proc +dentry lookup, instead of using "iget_locked()" to look up existing +inodes by superblock and number. That actually simplies the code a bit, +at the cost of potentially doing more inode [de]allocations. + +That said, the inode lookup wasn't free either (and did a lot of locking +of inodes), so it is probably not that noticeable. We could easily keep +the old lookup model for non-directory entries, but rather than try to +be excessively clever this just implements the minimal and simplest +workaround for the problem. + +Reported-and-tested-by: Dave Jones +Analyzed-by: Al Viro +Signed-off-by: Linus Torvalds +[bwh: Backported to 3.2: + - Adjust context + - Never drop the pde reference in proc_get_inode(), as callers only + expect this when we return an existing inode, and we never do that now] +Signed-off-by: Ben Hutchings +Cc: Rui Xiang +Signed-off-by: Greg Kroah-Hartman + +--- + fs/proc/inode.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +--- a/fs/proc/inode.c ++++ b/fs/proc/inode.c +@@ -443,12 +443,10 @@ static const struct file_operations proc + + struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) + { +- struct inode * inode; ++ struct inode *inode = new_inode_pseudo(sb); + +- inode = iget_locked(sb, de->low_ino); +- if (!inode) +- return NULL; +- if (inode->i_state & I_NEW) { ++ if (inode) { ++ inode->i_ino = de->low_ino; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + PROC_I(inode)->fd = 0; + PROC_I(inode)->pde = de; +@@ -477,9 +475,7 @@ struct inode *proc_get_inode(struct supe + inode->i_fop = de->proc_fops; + } + } +- unlock_new_inode(inode); +- } else +- pde_put(de); ++ } + return inode; + } +