linux/fs/udf
Jan Kara 09ebb17ab4 udf: Fix data corruption on file type conversion
UDF has two types of files - files with data stored in inode (ICB in
UDF terminology) and files with data stored in external data blocks. We
convert file from in-inode format to external format in
udf_file_aio_write() when we find out data won't fit into inode any
longer. However the following race between two O_APPEND writes can happen:

CPU1					CPU2
udf_file_aio_write()			udf_file_aio_write()
  down_write(&iinfo->i_data_sem);
  checks that i_size + count1 fits within inode
    => no need to convert
  up_write(&iinfo->i_data_sem);
					  down_write(&iinfo->i_data_sem);
					  checks that i_size + count2 fits
					    within inode => no need to convert
					  up_write(&iinfo->i_data_sem);
  generic_file_aio_write()
    - extends file by count1 bytes
					  generic_file_aio_write()
					    - extends file by count2 bytes

Clearly if count1 + count2 doesn't fit into the inode, we overwrite
kernel buffers beyond inode, possibly corrupting the filesystem as well.

Fix the problem by acquiring i_mutex before checking whether write fits
into the inode and using __generic_file_aio_write() afterwards which
puts check and write into one critical section.

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Jan Kara <jack@suse.cz>
2014-02-20 21:56:00 +01:00
..
Kconfig Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6 2011-01-11 14:45:52 -08:00
Makefile switch udf to simple_fsync() 2009-06-11 21:36:13 -04:00
balloc.c udf: Fix handling of i_blocks 2012-02-29 21:53:47 +01:00
dir.c [readdir] convert udf 2013-06-29 12:46:50 +04:00
directory.c udf: Neaten udf_debug uses 2011-10-31 23:43:58 +01:00
ecma_167.h Remove struct typedefs from fs/udf/ecma_167.h et al. 2009-04-02 12:29:47 +02:00
file.c udf: Fix data corruption on file type conversion 2014-02-20 21:56:00 +01:00
ialloc.c udf: Fortify LVID loading 2013-09-24 11:23:33 +02:00
inode.c udf: Fix data corruption on file type conversion 2014-02-20 21:56:00 +01:00
lowlevel.c udf: Neaten udf_debug uses 2011-10-31 23:43:58 +01:00
misc.c udf: Rename udf_error to udf_err 2011-10-10 19:29:01 +02:00
namei.c udf: Fix lockdep warning from udf_symlink() 2013-12-23 22:02:16 +01:00
osta_udf.h Remove struct typedefs from fs/udf/ecma_167.h et al. 2009-04-02 12:29:47 +02:00
partition.c udf: Cleanup metadata flags handling 2011-10-31 23:49:48 +01:00
super.c udf: fix for pathetic mount times in case of invalid file system 2013-10-18 22:39:07 +02:00
symlink.c udf: Treat symlink component of type 2 as / 2012-01-09 13:52:08 +01:00
truncate.c udf: Do not decrement i_blocks when freeing indirect extent block 2012-07-09 13:24:21 +02:00
udf_i.h udf: add extent cache support in case of file reading 2013-01-22 10:48:31 +01:00
udf_sb.h udf: Fortify LVID loading 2013-09-24 11:23:33 +02:00
udfdecl.h udf: add extent cache support in case of file reading 2013-01-22 10:48:31 +01:00
udfend.h Remove struct typedefs from fs/udf/ecma_167.h et al. 2009-04-02 12:29:47 +02:00
udftime.c udf: Convert printks to pr_<level> 2011-10-31 23:43:52 +01:00
unicode.c udf: Convert printks to pr_<level> 2011-10-31 23:43:52 +01:00