Bug 141122

Summary: VUL-0: kernel: leak of kernel memory through /proc files
Product: [openSUSE] SUSE LINUX 10.0 Reporter: Marcus Meissner <meissner>
Component: KernelAssignee: Marcus Meissner <meissner>
Status: RESOLVED FIXED QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P5 - None CC: security-team
Version: RC 4   
Target Milestone: ---   
Hardware: All   
OS: Other   
Whiteboard: affected:9.2,9.3,10.0 applied:9.2,9.3,10.0 released: - CVE-2005-4605: CVSS v2 Base Score: 2.1 (AV:L/AC:L/Au:N/C:P/I:N/A:N )
Found By: Other Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Marcus Meissner 2005-12-30 09:04:26 UTC
Originally on full-disclosure, so it is public:

From: Karl Janmar <karl@utopiafoundation.org>
Subject: [Full-disclosure] linux procfs vulnerablity
Date: Fri, 23 Dec 2005 22:03:31 +0700

Hi,

I have found one flaw in Linux procfs code that make the kernel disclose
memory.

In the linux version 2.6.14.3,
fs/proc/proc_misc.c:74
snip:
...
if (len <= off+count) *eof = 1;
*start = page + off;
...
off is a off_t and count is a int.


This flaw is not limited to procfs but is spread to other places:
./arch/ia64/kernel/palinfo.c:   if (len <= off+count) *eof = 1;
./arch/ia64/kernel/salinfo.c:   if (len <= off+count) *eof = 1;
./arch/ppc64/kernel/rtc.c:        if (len <= off+count) *eof = 1;
./drivers/char/ds1286.c:        if (len <= off+count) *eof = 1;
./drivers/char/efirtc.c:        if (len <= off+count) *eof = 1;
./drivers/char/genrtc.c:        if (len <= off+count) *eof = 1;
./drivers/char/ip27-rtc.c:        if (len <= off+count) *eof = 1;
./drivers/input/misc/hp_sdc_rtc.c:        if (len <= off+count) *eof = 1;
./drivers/mca/mca-proc.c:       if (len <= off+count) *eof = 1;
./drivers/mca/mca-proc.c:       if (len <= off+count) *eof = 1;
./drivers/mca/mca-proc.c:       if (len <= off+count) *eof = 1;
./drivers/net/wireless/atmel.c:        if (len <= off+count) *eof = 1;
./drivers/telephony/ixj.c:        if (len <= off+count) *eof = 1;
./fs/proc/proc_misc.c:  if (len <= off+count) *eof = 1;

However I think the procfs is the most important.
Comment 1 Marcus Meissner 2005-12-30 09:06:42 UTC
linus confirmed it in a later mail:

From: Linus Torvalds <torvalds@osdl.org>
To: Solar Designer <solar@openwall.com>
Cc: Thomas Biege <thomas@suse.de>, vendor-sec@lst.de, davej@redhat.com,
        security@kernel.org
Subject: Re: [Security] Re: [vendor-sec] [tom@electric-sheep.org: Fwd:
 [Full-disclosure] linux procfs vulnerablity]

On Fri, 30 Dec 2005, Solar Designer wrote:
>
> I'm not sure the EOF check in proc_calc_metrics() is to blame, though.
> I did not investigate this for real, but I feel that it's primarily the
> code in proc_file_read() that can use some hardening on both 2.4 and
> 2.6.

Yeah. The correct thing would be to get rid of it entirely, and rely on
seqfiles. Of course, that has been the correct thing for a long time, so..

Oh, and proc_file_lseek() is a piece of crap too.

The only big /proc file is kcore, which has special read/write logic and
uses the default lseek. Everything else should check s_maxbytes or
something (which for /proc should always be MAX_NON_LFS, which is
essentially INT_MAX).

Does this stupid patch (which is partly just whitespace cleanups too, I
can't edit 4-space-tab code) look reasonable?

                        Linus
---
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index b638fb5..78ab861 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -54,11 +54,23 @@ proc_file_read(struct file *file, char _
        ssize_t n, count;
        char    *start;
        struct proc_dir_entry * dp;
+       unsigned long long pos;

        dp = PDE(inode);
        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
                return -ENOMEM;

+       /*
+        * Gaah, please just use "seq_file" instead. The legacy /proc

....

I will attach GIT urls / the final patches once they are available.
Comment 3 Olaf Kirch 2006-01-02 11:47:08 UTC
The patch looks reasonably contained. The first hunk is obviously correct.
The second hunk makes me a little nervous though as it removes use of the
BKL. It *probably* just did that because it checked "offset + file->f_pos"
first and then updated "file->f_pos += offset" which would have a race.

Can anyone confirm that?

Apart from the BKL change, the second hunk should be equivalent to the
original code.

Lars, can you please drive this bug and apply the patch to all affected trees
(once we're sure the BKL removal is harmless)?
Comment 4 Lars Marowsky-Bree 2006-01-04 15:34:44 UTC
All other llseek occurances in 2.6.14 are also protected by the BKL. I can see dropping the BKL for user-initiated llseeks though (coming in via vfs_llseek), because these are protected by fget/fput_light(), so that removal should be correct (though potentially unnecessary).

However, this seems to be addressed already (though differently) in SLES9: patches.fixes/proc-info-leak(-2). Both of which don't seem to have patch headers. This is related to bug #56074 / SUSE41074 which I'm not allowed to access for inspection. Could the security team please give me access to that bugzilla?

Casually, 9.2, 9.3, 10.0 seem affected, but I'd probably drop the chunk which removes the BKL. It may be unneeded, but it's obviously an optimisation and not a correctness issue.
Comment 5 Thomas Biege 2006-01-05 08:47:29 UTC
CVE-2005-4605
Comment 6 Marcus Meissner 2006-01-05 10:00:31 UTC
i opened the referenced bug. if this is sufficient info, please drop NEEDINFO state.
Comment 7 Marcus Meissner 2006-01-09 15:43:15 UTC
i guess it is sufficient.
Comment 8 Lars Marowsky-Bree 2006-01-10 15:44:09 UTC
Adjusting products so it does show up on the SLES radar.
Comment 9 Lars Marowsky-Bree 2006-01-10 15:54:31 UTC
Committed to SL10.0, SL9.3, SL9.2. The other releases seem unaffected.
Comment 10 Marcus Meissner 2006-01-25 14:09:22 UTC
reopen for tracking
Comment 11 Marcus Meissner 2006-02-27 15:48:40 UTC
updates + advisory released.
Comment 12 Thomas Biege 2009-10-13 20:46:21 UTC
CVE-2005-4605: CVSS v2 Base Score: 2.1 (AV:L/AC:L/Au:N/C:P/I:N/A:N)