linux/fs
Linus Torvalds b0d8d22921 vfs: fix subtle use-after-free of pipe_inode_info
The pipe code was trying (and failing) to be very careful about freeing
the pipe info only after the last access, with a pattern like:

        spin_lock(&inode->i_lock);
        if (!--pipe->files) {
                inode->i_pipe = NULL;
                kill = 1;
        }
        spin_unlock(&inode->i_lock);
        __pipe_unlock(pipe);
        if (kill)
                free_pipe_info(pipe);

where the final freeing is done last.

HOWEVER.  The above is actually broken, because while the freeing is
done at the end, if we have two racing processes releasing the pipe
inode info, the one that *doesn't* free it will decrement the ->files
count, and unlock the inode i_lock, but then still use the
"pipe_inode_info" afterwards when it does the "__pipe_unlock(pipe)".

This is *very* hard to trigger in practice, since the race window is
very small, and adding debug options seems to just hide it by slowing
things down.

Simon originally reported this way back in July as an Oops in
kmem_cache_allocate due to a single bit corruption (due to the final
"spin_unlock(pipe->mutex.wait_lock)" incrementing a field in a different
allocation that had re-used the free'd pipe-info), it's taken this long
to figure out.

Since the 'pipe->files' accesses aren't even protected by the pipe lock
(we very much use the inode lock for that), the simple solution is to
just drop the pipe lock early.  And since there were two users of this
pattern, create a helper function for it.

Introduced commit ba5bb14733 ("pipe: take allocation and freeing of
pipe_inode_info out of ->i_mutex").

Reported-by: Simon Kirby <sim@hostway.ca>
Reported-by: Ian Applegate <ia@cloudflare.com>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Cc: stable@kernel.org   # v3.10+
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-12-02 09:44:51 -08:00
..
9p consolidate simple ->d_delete() instances 2013-11-15 22:04:17 -05:00
adfs adfs: delayed freeing of sbi 2013-10-24 23:43:27 -04:00
affs remove obsolete references to powertweak 2013-11-27 20:34:32 -08:00
afs Merge branch 'fscache' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into linux-next 2013-10-28 19:36:46 -04:00
autofs4 autofs4: make freeing sbi rcu-delayed 2013-10-24 23:43:27 -04:00
befs befs: split symlink iops in two - for short and long symlinks resp. 2013-10-24 23:34:50 -04:00
bfs
btrfs Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs 2013-11-22 08:38:55 -08:00
cachefiles Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
ceph Merge branch 'for-linus-bugs' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client 2013-11-26 18:02:46 -08:00
cifs [CIFS] Do not use btrfs refcopy ioctl for SMB2 copy offload 2013-11-25 09:50:31 -06:00
coda coda_revalidate_inode(): switch to passing inode... 2013-11-09 00:16:21 -05:00
configfs configfs: fix race between dentry put and lookup 2013-11-21 16:42:27 -08:00
cramfs cramfs: mark as obsolete 2013-11-13 12:09:12 +09:00
debugfs debugfs: use list_next_entry() in debugfs_remove_recursive() 2013-11-13 12:09:24 +09:00
devpts devpts: plug the memory leak in kill_sb 2013-11-13 12:09:36 +09:00
dlm genetlink: only pass array to genl_register_family_with_ops() 2013-11-19 16:39:05 -05:00
ecryptfs Quiet static checkers by removing unneeded conditionals 2013-11-22 10:58:14 -08:00
efivarfs consolidate simple ->d_delete() instances 2013-11-15 22:04:17 -05:00
efs
exofs
exportfs exportfs: fix quadratic behavior in filehandle lookup 2013-11-09 00:16:38 -05:00
ext2 ext2: Fix fs corruption in ext2_get_xip_mem() 2013-11-05 11:26:47 +01:00
ext3 Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs 2013-11-13 15:25:47 +09:00
ext4 Ext4 updates for 3.13. Mostly bug fixes and cleanups. 2013-11-14 17:19:58 +09:00
f2fs f2fs: issue more large discard command 2013-11-11 09:36:32 +09:00
fat fat: rcu-delay unloading nls and freeing sbi 2013-10-24 23:43:28 -04:00
freevxfs
fscache Merge branch 'for-3.13/core' of git://git.kernel.dk/linux-block 2013-11-14 12:08:14 +09:00
fuse Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
gfs2 GFS2: Fix ref count bug relating to atomic_open 2013-11-21 18:47:57 +00:00
hfs fs/hfs/btree.h: remove duplicate defines 2013-11-13 12:09:32 +09:00
hfsplus hfsplus: Fix undefined __divdi3 in hfsplus_init_header_node() 2013-11-15 09:32:23 +09:00
hostfs consolidate simple ->d_delete() instances 2013-11-15 22:04:17 -05:00
hpfs locks: break delegations on any attribute modification 2013-11-09 00:16:44 -05:00
hppfs
hugetlbfs
isofs isofs: don't pass dentry to isofs_hash{i,}_common() 2013-10-24 23:34:59 -04:00
jbd jbd: Revert "jbd: remove dependency on __GFP_NOFAIL" 2013-10-31 20:37:15 +01:00
jbd2
jffs2 jffs2: do not support the MLC nand 2013-10-27 16:27:07 -07:00
jfs Just a patch to fix an oops in an error path. 2013-10-22 09:01:11 +01:00
lockd
logfs
minix
ncpfs ncpfs: rcu-delay unload_nls() and freeing ncp_server 2013-10-24 23:43:28 -04:00
nfs NFS client bugfixes: 2013-11-16 13:14:56 -08:00
nfs_common
nfsd nfsd4: fix xdr decoding of large non-write compounds 2013-11-19 18:06:54 -05:00
nilfs2
nls
notify
ntfs iget/iget5: don't bother with ->i_lock until we find a match 2013-11-09 00:16:31 -05:00
ocfs2 tree-wide: use reinit_completion instead of INIT_COMPLETION 2013-11-15 09:32:21 +09:00
omfs
openpromfs
proc Merge git://git.infradead.org/users/eparis/audit 2013-11-21 19:18:14 -08:00
pstore
qnx4 qnx4: i_sb is never NULL 2013-11-09 00:16:32 -05:00
qnx6
quota genetlink: make multicast groups const, prevent abuse 2013-11-19 16:39:06 -05:00
ramfs
reiserfs
romfs
squashfs Squashfs: Check stream is not NULL in decompressor_multi.c 2013-11-20 03:59:20 +00:00
sysfs Revert "sysfs: handle duplicate removal attempts in sysfs_remove_group()" 2013-11-27 09:44:55 -08:00
sysv
ubifs Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
udf
ufs
xfs xfs: update #2 for v3.13-rc1 2013-11-22 08:37:47 -08:00
aio.c Merge git://git.kvack.org/~bcrl/aio-next 2013-11-22 08:42:14 -08:00
anon_inodes.c ... and kill anon_inode_getfile_private() 2013-11-09 00:16:28 -05:00
attr.c locks: break delegations on any attribute modification 2013-11-09 00:16:44 -05:00
bad_inode.c
binfmt_aout.c dump_skip(): dump_seek() replacement taking coredump_params 2013-11-09 00:16:26 -05:00
binfmt_elf_fdpic.c elf{,_fdpic} coredump: get rid of pointless if (siginfo->si_signo) 2013-11-09 00:16:30 -05:00
binfmt_elf.c elf{,_fdpic} coredump: get rid of pointless if (siginfo->si_signo) 2013-11-09 00:16:30 -05:00
binfmt_em86.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
binfmt_flat.c
binfmt_misc.c
binfmt_script.c
binfmt_som.c
bio-integrity.c
bio.c bio: fix argument of __bio_add_page() for max_sectors > 0xffff 2013-11-18 12:31:27 -07:00
block_dev.c
buffer.c
char_dev.c Merge branch 'for-3.13/core' of git://git.kernel.dk/linux-block 2013-11-14 12:08:14 +09:00
compat_binfmt_elf.c
compat_ioctl.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
compat.c
coredump.c dump_emit(): use __kernel_write(), not vfs_write() 2013-11-15 22:04:09 -05:00
coredump.h
dcache.c fold try_to_ascend() into the sole remaining caller 2013-11-15 22:04:17 -05:00
dcookies.c
direct-io.c
drop_caches.c
eventfd.c
eventpoll.c Merge branch 'akpm' (patches from Andrew Morton) 2013-11-13 15:45:43 +09:00
exec.c Merge git://git.infradead.org/users/eparis/audit 2013-11-21 19:18:14 -08:00
fcntl.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
fhandle.c
file_table.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
file.c
filesystems.c
fs_struct.c seqcount: Add lockdep functionality to seqcount/seqlock structures 2013-11-06 12:40:26 +01:00
fs-writeback.c Merge branch 'akpm' (patches from Andrew Morton) 2013-11-13 15:45:43 +09:00
generic_acl.c
inode.c locks: break delegations on any attribute modification 2013-11-09 00:16:44 -05:00
internal.h get rid of s_files and files_lock 2013-11-09 00:16:20 -05:00
ioctl.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
ioprio.c
Kconfig
Kconfig.binfmt
libfs.c consolidate simple ->d_delete() instances 2013-11-15 22:04:17 -05:00
locks.c locks: missing unlock on error in generic_add_lease() 2013-11-13 07:30:53 -05:00
Makefile
mbcache.c
mount.h RCU'd vfsmounts 2013-11-09 00:16:19 -05:00
mpage.c
namei.c fix bogus path_put() of nd->root after some unlazy_walk() failures 2013-11-29 01:50:51 -05:00
namespace.c RCU'd vfsmounts 2013-11-09 00:16:19 -05:00
no-block.c
open.c locks: break delegations on any attribute modification 2013-11-09 00:16:44 -05:00
pipe.c vfs: fix subtle use-after-free of pipe_inode_info 2013-12-02 09:44:51 -08:00
pnode.c split __lookup_mnt() in two functions 2013-10-24 23:35:00 -04:00
pnode.h
posix_acl.c
proc_namespace.c don't bother with vfsmount_lock in mounts_poll() 2013-10-24 23:34:59 -04:00
read_write.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
readdir.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
select.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-11-13 15:34:18 +09:00
seq_file.c seq_file: always clear m->count when we free m->buf 2013-11-18 19:07:53 -08:00
signalfd.c
splice.c file->f_op is never NULL... 2013-10-24 23:34:54 -04:00
stack.c
stat.c vfs: split out vfs_getattr_nosec 2013-11-09 00:16:31 -05:00
statfs.c
super.c get rid of s_files and files_lock 2013-11-09 00:16:20 -05:00
sync.c Merge branch 'akpm' (patches from Andrew Morton) 2013-11-13 15:45:43 +09:00
timerfd.c
utimes.c locks: break delegations on any attribute modification 2013-11-09 00:16:44 -05:00
xattr_acl.c
xattr.c