Sophie

Sophie

distrib > CentOS > 5 > i386 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 1248

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

From: Phillip Lougher <plougher@redhat.com>
Date: Thu, 2 Jun 2011 20:55:37 -0400
Subject: [fs] xfs: prevent leaking uninit stack memory in FSGEOMETRY_V1 p2
Message-id: <20110602205537.C737444B5D@plougher.csb>
Patchwork-id: 4585
O-Subject: [kernel team] [RHEL5.7 PATCH 2/2] xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1
Bugzilla: 677266
CVE: CVE-2011-0711

BZ #677266

Upsteam status:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=af24ee9ea8d532e16883251a6684dfa1be8eec29

This is the second of two upstream patches which fix CVE-2011-0711
xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1

The xfs FSGEOMETRY_v1 ioctl calls xfs_fs_geometry() with an
xfs_fsop_geom_v1_t structure allocated on the stack.  On x86_64 this
structure is padded by 4 bytes (108 bytes rounded to 112 bytes), and these bytes
are not initialized by xfs_fs_geometry() and are thus returned uninitialized to
user-space.

This fix is split across two patches upstream due to mistakes in the first
patch, which described the problem as:

"The FSGEOMETRY_V1 ioctl (and its compat equivalent) calls out to
xfs_fs_geometry() with a version number of 3.  This code path does not
fill in the logsunit member of the passed xfs_fsop_geom_t, leading to
the leaking of four bytes of uninitialized stack data to potentially
unprivileged callers.  Since all other members are filled in all code
paths and there are no padding bytes in this structure, it's safe to
avoid an expensive memset() in favor of just clearing this one field."

This is  confused...

The existing FSGEOMETRY_V1 ioctl function (xfs_ioc_fsgeometry_v1) calls
xfs_fs_geometry() with an xfs_fsop_geom_v1_t structure on the stack cast to a
xfs_fsop_geom_t structure, i.e.

        xfs_fsop_geom_v1_t      fsgeo;

        error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);

An xfs_fsop_geom_v1_t structure is the same as the xfs_fsop_geom structure
except it lacks the logsunit field at the end (i.e. the underlying size of the
xfs_fsop_geom_v1 structure is 108 bytes, the xfs_fsop_geom structure is 112
bytes, and logsunit is at the byte offset of 108).  So the fact the version
number 3 code path doesn't fill in logsunit is correct (as it will over-write
the stack).  On 32 bit machines this is entirely correct, there is no leak.
However, on x86_64 the xfs_fsop_geom_v1_t structure is padded to 112 bytes (4
bytes of padding), and this padding is returned to user-space unintialized.

The first patch is thus broken in that it over-writes the stack on
32-bit machines.

This second patch does the right thing, by converting all callers to pass a
xfs_fsop_geom_t structure, and then memsets the entire structure in
xfs_fs_geometry, avoiding padding issues on 64 bit machines, and stack
over-runs on 32 bit machines.

The compat ioctl (xfs_compat_ioc_fsgeometry_v1) allocates a xfs_fsop_geom on
the stack and passes this to xfs_fs_geometry, but when it is returned to the
user it is truncated to the size of the compat_xfs_fsop_geom_v1 structure.
This structure is _packed_ and it is 108 bytes in size.  Therefore the
uninitialised 4 bytes of padding is not returned to user-space.

Testing: existing FSGEOMETRY_V1 ioctl leak confirmed with test program, no
leaks found on patched kernel.

Original commit info

 From 0eba576d17f04fd5fb77226f4a03a85eec1a2dea Mon Sep 17 00:00:00 2001
From: Alex Elder <aelder@sgi.com>
Date: Tue, 1 Mar 2011 17:50:00 +0000
Subject: [PATCH 2/2] xfs: zero proper structure size for geometry calls

Commit 493f3358cb289ccf716c5a14fa5bb52ab75943e5 added this call to
xfs_fs_geometry() in order to avoid passing kernel stack data back
to user space:

+       memset(geo, 0, sizeof(*geo));

Unfortunately, one of the callers of that function passes the
address of a smaller data type, cast to fit the type that
xfs_fs_geometry() requires.  As a result, this can happen:

Kernel panic - not syncing: stack-protector: Kernel stack is corrupted
in: f87aca93

Pid: 262, comm: xfs_fsr Not tainted 2.6.38-rc6-493f3358cb2+ #1
Call Trace:

[<c12991ac>] ? panic+0x50/0x150
[<c102ed71>] ? __stack_chk_fail+0x10/0x18
[<f87aca93>] ? xfs_ioc_fsgeometry_v1+0x56/0x5d [xfs]

Fix this by fixing that one caller to pass the right type and then
copy out the subset it is interested in.

Note: This patch is an alternative to one originally proposed by
Eric Sandeen.

Reported-by: Jeffrey Hundstad <jeffrey.hundstad@mnsu.edu>
Signed-off-by: Alex Elder <aelder@sgi.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Tested-by: Jeffrey Hundstad <jeffrey.hundstad@mnsu.edu>
Signed-off-by: Phillip Lougher <plougher@redhat.com>

diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index ff0cb3d..517b8db 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -762,14 +762,19 @@ xfs_ioc_fsgeometry_v1(
 	xfs_mount_t		*mp,
 	void			__user *arg)
 {
-	xfs_fsop_geom_v1_t	fsgeo;
+	xfs_fsop_geom_t         fsgeo;
 	int			error;
 
-	error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3);
+	error = xfs_fs_geometry(mp, &fsgeo, 3);
 	if (error)
 		return -error;
 
-	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
+	/*
+	 * Caller should have passed an argument of type
+	 * xfs_fsop_geom_v1_t.  This is a proper subset of the
+	 * xfs_fsop_geom_t that xfs_fs_geometry() fills in.
+	 */
+	if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }