Staging
v0.8.1
v0.8.1
https://github.com/torvalds/linux
Revision 5b41e74ad1b0bf7bc51765ae74e5dc564afc3e48 authored by Dmitri Monakhov on 28 March 2008, 21:15:52 UTC, committed by Linus Torvalds on 28 March 2008, 21:45:21 UTC
Current nobh_write_end() implementation ignore partial writes(copied < len) case if page was fully mapped and simply mark page as Uptodate, which is totally wrong because area [pos+copied, pos+len) wasn't updated explicitly in previous write_begin call. It simply contains garbage from pagecache and result in data leakage. #TEST_CASE_BEGIN: ~~~~~~~~~~~~~~~~ In fact issue triggered by classical testcase open("/mnt/test", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3 ftruncate(3, 409600) = 0 writev(3, [{"a", 1}, {NULL, 4095}], 2) = 1 ##TESTCASE_SOURCE: ~~~~~~~~~~~~~~~~~ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/uio.h> #include <sys/mman.h> #include <errno.h> int main(int argc, char **argv) { int fd, ret; void* p; struct iovec iov[2]; fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); ftruncate(fd, 409600); iov[0].iov_base="a"; iov[0].iov_len=1; iov[1].iov_base=NULL; iov[1].iov_len=4096; ret = writev(fd, iov, sizeof(iov)/sizeof(struct iovec)); printf("writev = %d, err = %d\n", ret, errno); return 0; } ##TESTCASE RESULT: ~~~~~~~~~~~~~~~~~~ [root@ts63 ~]# mount | grep mnt2 /dev/mapper/test on /mnt2 type ext2 (rw,nobh) [root@ts63 ~]# /tmp/writev /mnt2/test writev = 1, err = 0 [root@ts63 ~]# hexdump -C /mnt2/test 00000000 61 65 62 6f 6f 74 00 00 f0 b9 b4 59 3a 00 00 00 |aeboot.....Y:...| 00000010 20 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 | .......!.......| 00000020 df df df df df df df df df df df df df df df df |................| 00000030 3a 00 00 00 2a 00 00 00 21 00 00 00 00 00 00 00 |:...*...!.......| 00000040 60 c0 8c 00 00 00 00 00 40 4a 8d 00 00 00 00 00 |`.......@J......| 00000050 00 00 00 00 00 00 00 00 41 00 00 00 00 00 00 00 |........A.......| 00000060 74 69 6d 65 20 64 64 20 69 66 3d 2f 64 65 76 2f |time dd if=/dev/| 00000070 6c 6f 6f 70 30 20 20 6f 66 3d 2f 64 65 76 2f 6e |loop0 of=/dev/n| skip.. 00000f50 00 00 00 00 00 00 00 00 31 00 00 00 00 00 00 00 |........1.......| 00000f60 6d 6b 66 73 2e 65 78 74 33 20 2f 64 65 76 2f 76 |mkfs.ext3 /dev/v| 00000f70 7a 76 67 2f 74 65 73 74 20 2d 62 34 30 39 36 00 |zvg/test -b4096.| 00000f80 a0 fe 8c 00 00 00 00 00 21 00 00 00 00 00 00 00 |........!.......| 00000f90 23 31 32 30 35 39 35 30 34 30 34 00 3a 00 00 00 |#1205950404.:...| 00000fa0 20 00 8d 00 00 00 00 00 21 00 00 00 00 00 00 00 | .......!.......| 00000fb0 d0 cf 8c 00 00 00 00 00 10 d0 8c 00 00 00 00 00 |................| 00000fc0 00 00 00 00 00 00 00 00 41 00 00 00 00 00 00 00 |........A.......| 00000fd0 6d 6f 75 6e 74 20 2f 64 65 76 2f 76 7a 76 67 2f |mount /dev/vzvg/| 00000fe0 74 65 73 74 20 20 2f 76 7a 20 2d 6f 20 64 61 74 |test /vz -o dat| 00000ff0 61 3d 77 72 69 74 65 62 61 63 6b 00 00 00 00 00 |a=writeback.....| 00001000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| As you can see file's page contains garbage from pagecache instead of zeros. #TEST_CASE_END Attached patch: - Add sanity check BUG_ON in order to prevent incorrect usage by caller, This is function invariant because page can has buffers and in no zero *fadata pointer at the same time. - Always attach buffers to page is it is partial write case. - Always switch back to generic_write_end if page has buffers. This is reasonable because if page already has buffer then generic_write_begin was called previously. Signed-off-by: Dmitri Monakhov <dmonakhov@openvz.org> Reviewed-by: Nick Piggin <npiggin@suse.de> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 1d4a788
Tip revision: 5b41e74ad1b0bf7bc51765ae74e5dc564afc3e48 authored by Dmitri Monakhov on 28 March 2008, 21:15:52 UTC
vfs: fix data leak in nobh_write_end()
vfs: fix data leak in nobh_write_end()
Tip revision: 5b41e74
File | Mode | Size |
---|---|---|
basic | ||
genksyms | ||
kconfig | ||
ksymoops | ||
mod | ||
package | ||
rt-tester | ||
.gitignore | -rw-r--r-- | 77 bytes |
Kbuild.include | -rw-r--r-- | 9.1 KB |
Lindent | -rwxr-xr-x | 65 bytes |
Makefile | -rw-r--r-- | 893 bytes |
Makefile.build | -rw-r--r-- | 11.1 KB |
Makefile.clean | -rw-r--r-- | 3.2 KB |
Makefile.headersinst | -rw-r--r-- | 6.9 KB |
Makefile.host | -rw-r--r-- | 6.5 KB |
Makefile.lib | -rw-r--r-- | 6.7 KB |
Makefile.modinst | -rw-r--r-- | 1.0 KB |
Makefile.modpost | -rw-r--r-- | 4.9 KB |
bin2c.c | -rw-r--r-- | 702 bytes |
binoffset.c | -rw-r--r-- | 3.9 KB |
bloat-o-meter | -rwxr-xr-x | 1.7 KB |
checkincludes.pl | -rwxr-xr-x | 529 bytes |
checkkconfigsymbols.sh | -rwxr-xr-x | 1.8 KB |
checkpatch.pl | -rwxr-xr-x | 50.2 KB |
checkstack.pl | -rwxr-xr-x | 4.2 KB |
checksyscalls.sh | -rwxr-xr-x | 3.1 KB |
checkversion.pl | -rwxr-xr-x | 1.8 KB |
cleanfile | -rwxr-xr-x | 3.4 KB |
cleanpatch | -rwxr-xr-x | 5.0 KB |
conmakehash.c | -rw-r--r-- | 6.0 KB |
decodecode | -rw-r--r-- | 1.1 KB |
export_report.pl | -rw-r--r-- | 4.2 KB |
extract-ikconfig | -rwxr-xr-x | 1.7 KB |
gcc-version.sh | -rw-r--r-- | 818 bytes |
gcc-x86_64-has-stack-protector.sh | -rw-r--r-- | 187 bytes |
gen_initramfs_list.sh | -rw-r--r-- | 6.6 KB |
hdrcheck.sh | -rwxr-xr-x | 281 bytes |
kallsyms.c | -rw-r--r-- | 13.3 KB |
kernel-doc | -rwxr-xr-x | 55.3 KB |
makelst | -rwxr-xr-x | 773 bytes |
mkcompile_h | -rwxr-xr-x | 2.5 KB |
mkmakefile | -rw-r--r-- | 1.0 KB |
mksysmap | -rw-r--r-- | 1.3 KB |
mkuboot.sh | -rwxr-xr-x | 379 bytes |
mkversion | -rw-r--r-- | 74 bytes |
namespace.pl | -rwxr-xr-x | 13.1 KB |
patch-kernel | -rwxr-xr-x | 9.7 KB |
pnmtologo.c | -rw-r--r-- | 11.7 KB |
profile2linkerlist.pl | -rw-r--r-- | 378 bytes |
setlocalversion | -rwxr-xr-x | 1.5 KB |
show_delta | -rwxr-xr-x | 3.0 KB |
unifdef.c | -rw-r--r-- | 29.0 KB |
ver_linux | -rwxr-xr-x | 3.2 KB |
Computing file changes ...