Bug 962792 (CVE-2013-2094)

Summary: CVE-2013-2094 kernel: perf_swevent_enabled array out-of-bound access
Product: [Other] Security Response Reporter: Petr Matousek <pmatouse>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: adamw, afeldt, agajania, agordeev, ajb, alexa.gerancho, anton, arusso, bandrmail, b.de.boer, bhu, bmourelo, bugzilla-redhat, cameron.kerr, carnil, chensongzheng, coggy+redhat, cwawak, davej, ddm, dgherman, dhoward, dkovalsk, d-krstic, dslehman, esammons, fche, felipe, fhrbata, gansalmon, gbailey, gholms, greg.t, hans, hanzhin.stas, hayato.suzuki, herrold, iamdexpl, iboverma, itamar, james.hogarth, Jan.van.Eldik, jbrouer, jcpunk, jeder, jforbes, jjneely, jkacur, johan-fedora, john.mora, johnny, jonathan, jpazdziora, jsimonel, junk, jwboyer, karlamrhein, kcbnac, kernel-mgr, khorenko, kpatterson, leskomw, lgoncalv, lloyd.cobb, lmacken, logan, lwang, lwhatley, madhu.chinakonda, magnawave, masanari_iida, mattdm, matti, maxim, mchappel, mcoffey, mcressma, michele, mjc, mk, mkarg, mosorio, mricon, mstevens, npajkovs, nux, paulds, pep, philip.cheung, pkoro, plazonic, plougher, rbarlow, rcvalle, rebus, redhat, rg, rik.theys, ripleymj, rsteiger, rt-maint, rvrbovsk, shyam, simon.croome, srhode, stephan.wiesand, stephenf, sydelko, tema, t.h.amundsen, thomas.oulevey, timc, tis, tkramer, tobias.dussa, toracat, tristan.santore, tru, ville, williams, wolfy, xtian, yaplik, yersinia.spiros, ykawada, zdenek
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard: impact=important,public=20130514,reported=20130514,source=internet,cvss2=7.2/AV:L/AC:L/Au:N/C:C/I:C/A:C,rhel-5/kernel=notaffected,rhel-6/kernel=affected,rhel-6.3.z/kernel=affected,rhel-6.2.z/kernel=affected,rhel-6.1.z/kernel=affected,mrg-2/realtime-kernel=affected,fedora-all/kernel=affected,cwe=CWE-839->CWE-129->CWE-119
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-05-21 03:56:14 EDT Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Bug Depends On: 962793, 962794, 962795, 962796, 962797, 962798, 962799, 962812, 964225    
Bug Blocks: 962949, 963009, 963010, 963108, 963115    

Comment 3 Petr Matousek 2013-05-14 09:06:18 EDT
Created kernel tracking bugs for this issue

Affects: fedora-all [bug 962799]
Comment 6 Petr Matousek 2013-05-14 09:29:29 EDT
Statement:

This issue does not affect the kernel packages as shipped with Red Hat Enterprise Linux 5 because we did not backport upstream commit b0a873eb that introduced this issue.

This issue was addressed in Red Hat Enterprise Linux 6 via RHSA-2013:0830 (https://rhn.redhat.com/errata/RHSA-2013-0830.html), Red Hat Enterprise Linux 6.1 Extended update support via RHSA-2013:0841 (https://rhn.redhat.com/errata/RHSA-2013-0841.html), Red Hat Enterprise Linux 6.2 Extended update support via RHSA-2013:0840 (https://rhn.redhat.com/errata/RHSA-2013-0840.html), Red Hat Enterprise Linux 6.3 Extended Update Support via RHSA-2013:0832 (https://rhn.redhat.com/errata/RHSA-2013-0832.html), and Red Hat Enterprise MRG 2 via RHSA-2013:0829 (https://rhn.redhat.com/errata/RHSA-2013-0829.html).

Red Hat Enterprise Linux 6.0 was not affected by this flaw.

Refer to https://access.redhat.com/site/solutions/373743 for further information.
Comment 7 Thomas Oulevey 2013-05-14 09:31:03 EDT
Hi,

Can you confirm that :
sysctl kernel.perf_event_paranoid=2

is a good enough solution for our users in short term ?

cheers,
-- 
Thomas
Comment 10 Petr Matousek 2013-05-14 10:23:38 EDT
Hello, Thomas.

(In reply to comment #7)
> Can you confirm that :
> sysctl kernel.perf_event_paranoid=2
> 
> is a good enough solution for our users in short term ?

Our testing shows that this is not sufficient to avoid the issue in general, but it is currently sufficient mitigation against the publicly available (unmodified) exploits.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 13 Petr Matousek 2013-05-14 12:48:25 EDT
To mitigate the issue:

1) On the host, save the following in a file with the ".stp" extension:

%{

#include <linux/perf_event.h>

%}

function sanitize_config:long (event:long) %{
        struct perf_event *event;

#if STAP_COMPAT_VERSION >= STAP_VERSION(1,8)
        event = (struct perf_event *) (unsigned long) STAP_ARG_event;
#else
        event = (struct perf_event *) (unsigned long) THIS->event;
#endif

        event->attr.config &= INT_MAX;

%}

probe kernel.function("perf_swevent_init").call {
        sanitize_config($event);
}

2) Install the "systemtap" package and any required dependencies. Refer to
the "2. Using SystemTap" chapter in the Red Hat Enterprise Linux 6
"SystemTap Beginners Guide" document, available from docs.redhat.com, for
information on installing the required -debuginfo packages.

3) Run the "stap -g [filename-from-step-1].stp" command as root.

If the host is rebooted, the changes will be lost and the script must be
run again.


Alternatively, build the systemtap script on a development system with
"stap -g -p 4 [filename-from-step-1].stp", distribute the resulting kernel
module to all affected systems, and run "staprun -L <module>" on those.
When using this approach only systemtap-runtime package is required on the
affected systems. Please notice that the kernel version must be the same across all systems.
Comment 14 jcpunk 2013-05-14 13:59:57 EDT
What is the overall risk on this exploit for systems with selinux in Enforcing mode?
Comment 15 Petr Matousek 2013-05-14 14:40:34 EDT
(In reply to comment #14)
> What is the overall risk on this exploit for systems with selinux in
> Enforcing mode?

According to our testing, SELinux does not help to mitigate this issue.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 16 Petr Matousek 2013-05-14 19:36:43 EDT
How the public exploit in comment #0 (x86_64) works:

The problem is that event_id index in perf_swevent_init is signed and
checked only for it's upper bound. When assigning event->attr.config value
to event_id at the beginning of the function, any attr.config value
which has the 31st bit set will result in negative event_id.
Negative event_id will pass the >= PERF_COUNT_SW_MAX check later in the
code.

Later in the code, write in the form of

  atomic_inc(&perf_swevent_enabled[event_id]);

is present.

perf_swevent_enabled is defined as

atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];

so on RHEL (which does not have jump labels) it is basically array of ints.

When accessing the perf_swevent_enabled array with event_id being int,
event_id is sign extended to 64-bit. In the case of event_id being -1
(0xffffffff), it is sign extended to 0xffffffffffffffff. Because
perf_swevent_enabled is an array of ints (32-bit), the 64-bit value is
multiplied by 4 (32 / 8) and then added to the perf_swevent_enabled
address.

Let's assume

[cynique@intel-d3ce1-01 ~]$ cat /boot/System.map-2.6.32-358.el6.x86_64 | grep perf_swevent_enabled
ffffffff81f360c0 B perf_swevent_enabled

and event->attr.config == 0xffffffff -->

0xffffffffffffffff * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360BC

similarly when event->attr.config == 0xfffffffe -->

0xfffffffffffffffe * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360B8

So in the perf_swevent_init code path we will end up incrementing kernel
mode addresses.

The interesting thing happens in the destroy path, which gets called
when the file descriptor returned by the perf_event_open (invoking this
syscall with the correct parameters will trigger the perf_swevent_init
code path) is being closed:

static void sw_perf_event_destroy(struct perf_event *event)
{
        u64 event_id = event->attr.config;

        WARN_ON(event->parent);

        atomic_dec(&perf_swevent_enabled[event_id]);
        swevent_hlist_put(event);
}

Now event_id is u64, so it's taken from userspace as is.

Let's assume again event->attr.config == 0xffffffff -->

0xffffffff * 4 + 0xffffffff81f360c0 == 0x0000000381F360BC

similarly when event->attr.config == 0xfffffffe -->

0xfffffffe * 4 + 0xffffffff81f360c0 == 0x0000000381F360B8

So in the sw_perf_event_destroy path, we will end up decrementing
userspace addresses for the same values as in the perf_swevent_init code
path.

Now let's take this knowledge and see what the exploit does:

#define BASE  0x380000000
#define SIZE  0x010000000

  assert((map = mmap((void*)BASE, SIZE, 3, 0x32, 0,0)) == (void*)BASE);
  memset(map, 0, SIZE);
  sheep(-1); sheep(-2);    // sheep will just invoke perf_event_open
                           // syscall with attr.config set to the param
  for (i = 0; i < SIZE/4; i++) if (map[i]) {
    assert(map[i+1]);
    break;
  }

So we will map memory region starting at 0x380000000 (see how the 
addresses looked like when accessing perf_swevent_enabled in the
sw_perf_event_destroy code path above) and perform perf_even_open twice
with attr.config values of 0xffffffff and 0xfffffffe. This will result
in two increments on addresses 0xFFFFFFFF81F360BC and 0xFFFFFFFF81F360B8
and two decrements on addresses 0x0000000381F360BC and 0x0000000381F360B8.
The for loop then finds the addresses where the sw_perf_event_destroy
actually landed. That is important for us because this way we can find
out the address of perf_swevent_enabled as we know (from our testing)

0xfffffffe * 4 + 0xXXXXXXXXXXXXXXXX == 0x0000000381F360B8
0xfffffffe * 4 + 0xffffffffZZZZZZYY == 0x00000003ZZZZZZ(YY - 8)

ZZZZZZ   -> 81F360
(YY - 8) -> B8
YY       -> B8 + 8 (+ 8 because we're looking at -2 index to an array of 32bit
                    element size)
YY       -> C0

0xffffffffZZZZZZYY -> 0xffffffff81F360C0

On RHEL we can simply (even as unprivileged user) grep system map for the
address of perf_swevent_enabled, but there are hardened distros that it's
not possible this way.

Knowing the perf_swevent_enabled we move to the real exploitation part.
Because of the properties of the bug, that allows us to increment 32-bit
values, we can in one step change any kernel mode address to user space
one -- for example taking 0xffffffff81f360c0. If we increment the high
32-bits of this address by one, we end with 0x0000000081f360c0.

For this purposes, we choose interrupt descriptor table. An array of
16-byte descriptors:

Offset 	Size 	Description
0 	2 	Offset low bits (0..15)
2 	2 	Selector (Code segment selector)
4 	1 	Zero
5 	1 	Type and Attributes (same as before)
6 	2 	Offset middle bits (16..31)
8 	4 	Offset high bits (32..63)
12 	4 	Zero

The interesting value is at offset 8, on x86_64 it will be 0xffffffff.

The exploit author chose interrupt descriptor corresponding to interrupt
0x4, so the offset is 0x48 from the start of interrupt descriptor table.
We can actually see the offset in the code,

   *p = j?((g<<32)|u):(idt.addr + 0x48);

which setups the needed values for cleanup.

The interrupt descriptor table was chosen because it is very easy to get it's
address even on hardened builds -- using sidt instruction.

So what we do is setup the landing area with the code that just looks up
credentials of the current task, replaces uid/gids to 0, thus granting
full capabilities and also restores the value in idt + 0x48 to 0xffffffff
(*fixptr = -1;).

Once this is done, we are ready to increment the high bits of interrupt
descriptor offset of int 0x4, taking into account the address of
perf_swevent_enabled (distance from it):

  sheep(-i + (((idt.addr&0xffffffff)-0x80000000)/4) + 16);

In this case we do not care about the decrement, which will again land
in our previously prepared memory region, but in the increment.

Invoking asm("int $0x4"); will finally run our shellcode with ring0
privileges. Our "interrupt handler" will increase our task's privileges,
do the idt cleanup as presented above and return back to userspace.

And now we can run /bin/bash as root:

 return execl("/bin/bash", "-sh", NULL);
Comment 20 Elia Pinto 2013-05-15 06:30:53 EDT
Selinux  can block instead if the user is a confined user (user_u), and not unconfined_u

http://danwalsh.livejournal.com/16368.html


example

id
uid=504(pippo) gid=504(pippo) groups=504(pippo) context=user_u:user_r:user_t:s0
[pippo@esil780 ex]$ ./uu
2.6.37-3.x x86_64
sd@fucksheep.org 2010
-sh: /home/pippo/.profile: Permission denied
-sh-4.1# ^C
-sh-4.1# kill -9 19457
-sh: kill: (19457) - Operation not permitted
-sh-4.1# init 6
-sh: init: command not found
-sh-4.1# su
-sh: su: command not found
Comment 21 Petr Matousek 2013-05-15 06:45:43 EDT
(In reply to comment #20)

SELinux does not block the exploitation because the attacker's provided shellcode is still executed with ring0 permissions. The public exploit is not targeted against SELinux, but it would be rather easy to adapt it to disable SELinux completely from the ring0 shellcode.

Unfortunately, in this case SELinux blocks just the symptoms, not the real attack vector.

--
Petr Matousek / Red Hat Security Response Team
Comment 22 Elia Pinto 2013-05-15 08:42:41 EDT
(In reply to comment #21)
You are right naturally
> (In reply to comment #20)
> 
> SELinux does not block the exploitation because the attacker's provided
> shellcode is still executed with ring0 permissions. The public exploit is
> not targeted against SELinux, but it would be rather easy to adapt it to
> disable SELinux completely from the ring0 shellcode.
> 
> Unfortunately, in this case SELinux blocks just the symptoms, not the real
> attack vector.
> 
> --
> Petr Matousek / Red Hat Security Response Team
Comment 24 Petr Matousek 2013-05-15 09:26:03 EDT
To detect the original unmodified "semtex" CVE-2013-2094 public exploit on Red Hat Enterprise Linux 6@x86_64 systems:

1) On the host, save the following in a file with the ".stp" extension:

global PSE_ADDR=0

probe begin {

        printf("--------------------------------------------------------------------------\n");

        if ((kernel_int(PSE_ADDR-4) != 0) || (kernel_int(PSE_ADDR-8) != 0)) {
                printf("%lx -- %x, %lx -- %x\n", PSE_ADDR-4, kernel_int(PSE_ADDR-4), PSE_ADDR-8, kernel_int(PSE_ADDR-8));

                if (kernel_int(PSE_ADDR-4) == kernel_int(PSE_ADDR-8))
                        printf("CVE-2013-2094 semtex local privilege escalation exploit residue detected!\n");
                else
                        printf("CVE-2013-2094 relevant suspicious value combination detected.\n");

        } else
                printf("CVE-2013-2094 semtex local privilege escalation exploit residue NOT detected!\n");

        printf("--------------------------------------------------------------------------\n");

        exit();
}

2) Install the "systemtap" package and any required dependencies. Refer to
the "2. Using SystemTap" chapter in the Red Hat Enterprise Linux 6
"SystemTap Beginners Guide" document, available from docs.redhat.com, for
information on installing the required packages.

3) Run the "stap [filename-from-step-1].stp -G PSE_ADDR=0x`grep perf_swevent_enabled /proc/kallsyms | awk '{print $1}'`" command as root.

4) See the message printed

Please note that when the script does not detect the "semtex" exploit
residue it does not mean the server is/was not hacked. It just means that
the unmodified original public exploit was not run on this server (or
something went wrong). Considering that most of the exploits used in the
wild now will be either based on or are the same as the original public
"semtex" exploit, this script can be used to at least give a clue whether
the original unmodified "semtex" exploit was exercised on the system.

Also please note, that it is trivial to modify the exploit to cleanup
after the exploitation and as such, this detection script cannot be used
as a proof that the server was not hacked.
Comment 27 Lee Whatley 2013-05-15 11:30:05 EDT
Hi,

Has upstream commit b0a873eb been in every RHEL6 kernel, or was it introduced by a particular errata?  I guess my question really is, is there an older RHEL6 kernel that is not vulnerable?

Thanks!
-Lee
Comment 28 Tristan Santore 2013-05-15 12:02:04 EDT
We have been playing with this exploit for a while now. I would like to know if this exploit works for anyone running an i7/i5 range Intel CPU. For some reason this sploit doesn't seem to work on those, which is a good thing for me/us. However, I got somebody to try on an AMD system and it works there. Can somebody enlighten me if the new Intel CPU have some form of protection mechanism, AMD lacks ?

Thank you.

Tristan
Comment 29 Petr Matousek 2013-05-15 12:24:46 EDT
Hello, Lee.

(In reply to comment #27)
> Has upstream commit b0a873eb been in every RHEL6 kernel, or was it
> introduced by a particular errata?  I guess my question really is, is there
> an older RHEL6 kernel that is not vulnerable?

This issue was introduced by http://rhn.redhat.com/errata/RHSA-2011-0542.html, and is present in all Red Hat Enterprise Linux 6 kernels starting with Red Hat Enterprise Linux 6.1 (kernel-2.6.32-131.0.15.el6).

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 30 Petr Matousek 2013-05-15 12:39:31 EDT
Hello, Tristan.

(In reply to comment #28)
> We have been playing with this exploit for a while now. I would like to know
> if this exploit works for anyone running an i7/i5 range Intel CPU. For some
> reason this sploit doesn't seem to work on those, which is a good thing for
> me/us. However, I got somebody to try on an AMD system and it works there.
> Can somebody enlighten me if the new Intel CPU have some form of protection
> mechanism, AMD lacks ?

It might be SMEP (Supervisor Mode Execution Protection). SMEP is enabled in Red Hat Enterprise Linux since version 6.2. Can you please be more specific in what happens when you run the exploit on the i7/i5 range Intel CPU? Is there any output (even from dmesg)?

Does "grep smep /proc/cpuinfo" print any result?

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 31 Murray McAllister 2013-05-15 12:50:09 EDT
Knowledgebase article for this issue: https://access.redhat.com/site/solutions/373743
Comment 32 Tristan Santore 2013-05-15 13:46:02 EDT
Petr,

As per request:

uname -r
2.6.32-358.6.1.el6.x86_64
semtex: semtex.c:81: main: Assertion `p = memmem(code, 1024, &needle, 8)' failed.
Aborted

sestatus 
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
cpuinfo
excerpt:

flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm ida arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms

Regards,

Tristan
Comment 33 Tristan Santore 2013-05-15 13:47:03 EDT
Petr,

As per request:

uname -r
2.6.32-358.6.1.el6.x86_64
semtex: semtex.c:81: main: Assertion `p = memmem(code, 1024, &needle, 8)' failed.
Aborted

sestatus 
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
cpuinfo
excerpt:

flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm ida arat epb xsaveopt pln pts dts tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms

So it appears smep is there and enabled.
Regards,

Tristan
Comment 34 Joshua Baker-LePain 2013-05-15 13:49:38 EDT
Does this affect 32bit kernels as well as 64bit?  It's not specified anywhere, and the systemtap script from comment 13 fails to build on 32bit:

$ stap -g -p 4 -m fix_CVE_2013_2094 fix-CVE-2013-2094.stp 
cc1: warnings being treated as errors
/tmp/stapvT7siX/fix_CVE_2013_2094_src.c: In function ‘function_sanitize_config’:
/tmp/stapvT7siX/fix_CVE_2013_2094_src.c:140: error: cast to pointer from integer of different size
make[1]: *** [/tmp/stapvT7siX/fix_CVE_2013_2094_src.o] Error 1
make: *** [_module_/tmp/stapvT7siX] Error 2
WARNING: kbuild exited with status: 2
Pass 4: compilation failed.  Try again with another '--vp 0001' option.
Comment 35 Petr Matousek 2013-05-15 13:50:58 EDT
(In reply to comment #32)
> uname -r
> 2.6.32-358.6.1.el6.x86_64
> semtex: semtex.c:81: main: Assertion `p = memmem(code, 1024, &needle, 8)'
> failed.
> Aborted

Please try to build with -O2 -- gcc -O2 -o semtex semtex.c -- and rerun.

--
Petr Matousek / Red Hat Security Response Team
Comment 36 Tristan Santore 2013-05-15 13:54:03 EDT
I would rather not mate, I did that yesterday, and it crashed the machine.
;-p
Comment 37 manuel wolfshant 2013-05-15 15:18:37 EDT
(In reply to comment #34)
> Does this affect 32bit kernels as well as 64bit?  It's not specified
> anywhere, and the systemtap script from comment 13 fails to build on 32bit:
[...]

The unmodified exploit failed on all my 32bit instances. I have tested on real iron ( HS20, Athlon XP 2200+, Athlon II 455 X3 ) and VMware WS 7. OTOH it worked on all 64bit instances ( Athlon X2 250, VMware WS 7, Intel Xeon X3440)
Comment 38 Akemi Yagi 2013-05-15 15:40:18 EDT
(In reply to comment #34)
> Does this affect 32bit kernels as well as 64bit?  It's not specified
> anywhere, and the systemtap script from comment 13 fails to build on 32bit:

This KB article:

https://access.redhat.com/site/solutions/372873

refers to x86_64 only:

Environment

    Red Hat Enterprise Linux 6 up to kernel-2.6.32-358.6.1.el6, x86_64
    Red Hat MRG Realtime, up to kernel-rt-3.6.11-rt30.25.el6rt, x86_64
Comment 39 Akemi Yagi 2013-05-15 15:45:32 EDT
There is yet another way to mitigate the issue. That is to install kmod-tpe from ELRepo:

http://elrepo.org/tiki/kmod-tpe

"This package provides the tpe kernel module. Trusted Path Execution (TPE) is a security feature that denies users from executing programs that are not owned by root, or are writable. This closes the door on a whole category of exploits where a malicious user tries to execute his or her own code to hack the system. Since this kernel module does not use any kind of ACLs, it works out of the box with no configuration."

To the best of my knowledge, this actually blocks the known exploit.
Comment 40 Frank Ch. Eigler 2013-05-15 15:54:06 EDT
> "This package provides the tpe kernel module. Trusted Path Execution (TPE)
> is a security feature that denies users from executing programs that are not
> owned by root, or are writable. [...]

Would that do anything against exploits running via an interpreter like perl?
Comment 41 Akemi Yagi 2013-05-15 16:08:41 EDT
(In reply to comment #40)
> > "This package provides the tpe kernel module. Trusted Path Execution (TPE)
> > is a security feature that denies users from executing programs that are not
> > owned by root, or are writable. [...]
> 
> Would that do anything against exploits running via an interpreter like perl?

Questions/comments regarding the TPE kernel module are best directed to the author/source at:

https://github.com/cormander/tpe-lkm
Comment 42 Petr Matousek 2013-05-15 16:27:44 EDT
(In reply to comment #34)
> Does this affect 32bit kernels as well as 64bit?

Yes, both 32bit and 64bit kernels are affected but the publicly available exploit only targets x86_64 architecture.

> It's not specified
> anywhere

Unless explicitly specified, all architectures are affected.

> and the systemtap script from comment 13 fails to build on 32bit:
> 
> $ stap -g -p 4 -m fix_CVE_2013_2094 fix-CVE-2013-2094.stp 
> cc1: warnings being treated as errors
> /tmp/stapvT7siX/fix_CVE_2013_2094_src.c: In function
> ‘function_sanitize_config’:
> /tmp/stapvT7siX/fix_CVE_2013_2094_src.c:140: error: cast to pointer from
> integer of different size
> make[1]: *** [/tmp/stapvT7siX/fix_CVE_2013_2094_src.o] Error 1
> make: *** [_module_/tmp/stapvT7siX] Error 2
> WARNING: kbuild exited with status: 2
> Pass 4: compilation failed.  Try again with another '--vp 0001' option.

I am very sorry for the trouble. I've updated the system script in comment #13, it should now work on both 32-bit and 64-bit kernels.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 43 Petr Matousek 2013-05-15 16:30:01 EDT
(In reply to comment #38)
> (In reply to comment #34)
> > Does this affect 32bit kernels as well as 64bit?  It's not specified
> > anywhere, and the systemtap script from comment 13 fails to build on 32bit:
> 
> This KB article:
> 
> https://access.redhat.com/site/solutions/372873
> 
> refers to x86_64 only:
> 
> Environment
> 
>     Red Hat Enterprise Linux 6 up to kernel-2.6.32-358.6.1.el6, x86_64
>     Red Hat MRG Realtime, up to kernel-rt-3.6.11-rt30.25.el6rt, x86_64

Please see the referenced KB article from comment #31. The article you point to only lists some of the affected configurations, not all.
Comment 44 Petr Matousek 2013-05-15 16:31:28 EDT
(In reply to comment #37)
> (In reply to comment #34)
> > Does this affect 32bit kernels as well as 64bit?  It's not specified
> > anywhere, and the systemtap script from comment 13 fails to build on 32bit:
> [...]
> 
> The unmodified exploit failed on all my 32bit instances. I have tested on
> real iron ( HS20, Athlon XP 2200+, Athlon II 455 X3 ) and VMware WS 7. OTOH
> it worked on all 64bit instances ( Athlon X2 250, VMware WS 7, Intel Xeon
> X3440)

The original "semtex" exploit works only on x86_64 systems, but generally this issue does affect x86 as well.
Comment 45 Johnny Hughes 2013-05-15 16:43:52 EDT
The CentOS team has released an interim kernel that is the latest EL6 kernel plus only the patch in comment 0 and it is available here:

http://people.centos.org/hughesjr/c6kernel/2.6.32-358.6.1.el6.cve20132094/
Comment 46 Vadim Raskhozhev 2013-05-15 17:04:24 EDT
(In reply to comment #45)
> The CentOS team has released an interim kernel that is the latest EL6 kernel
> plus only the patch in comment 0 and it is available here:
> 
> http://people.centos.org/hughesjr/c6kernel/2.6.32-358.6.1.el6.cve20132094/

$ gcc -o semtex -O2 semtex.c && ./semtex ; cat /etc/redhat-release ; uname -r
semtex: semtex.c:51: sheep: Assertion `!close(fd)' failed.
Aborted
CentOS release 6.4 (Final)
2.6.32-358.6.1.el6.cve20132094.x86_64
Comment 47 Petr Matousek 2013-05-15 17:42:39 EDT
(In reply to comment #36)
> I would rather not mate, I did that yesterday, and it crashed the machine.
> ;-p

The only difference -O2 parameter brings is that the mov instructions with the 64-bit displacements and/or immediate operands are used instead of building the 64bit values on the stack when -O2 parameter is not used.

In the former case the values are consecutive in memory and can be searched in memory directly. In the latter case this is not possible and thus memmem fails.

The crash you are seeing when building with -O2 might very well be SMEP (because of the access right violation page fault) when transferring control to userspace via int 0x4.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 48 Nux 2013-05-15 18:51:26 EDT
(In reply to comment #40)
> > "This package provides the tpe kernel module. Trusted Path Execution (TPE)
> > is a security feature that denies users from executing programs that are not
> > owned by root, or are writable. [...]
> 
> Would that do anything against exploits running via an interpreter like perl?

AFAIK it will work against `./test.pl` if test.pl is in a 777 dir or not owned by root. It does not protect against `perl test.pl`, though.
It would have helped perfectly in this case.
Comment 49 masanari iida 2013-05-15 22:41:56 EDT
(In reply to comment #31)
> Knowledgebase article for this issue:
> https://access.redhat.com/site/solutions/373743

Reporting minor issue.

In case of RHEL6.1(2.6.32-131.0.15), perf_swevent_init() exist 
in kernel/perf_event.c.  So the sample systemtap script in KB
doesn't work.

RHEL6.2 or later, the perf_swevent_init() exist in kernel/events/core.c.

Why don't we just specify kernel.function("perf_swevent_init")
without code path?
Comment 50 Petr Matousek 2013-05-16 03:38:57 EDT
Masanari-san,

(In reply to comment #49)
> (In reply to comment #31)
> > Knowledgebase article for this issue:
> > https://access.redhat.com/site/solutions/373743
> 
> Reporting minor issue.
> 
> In case of RHEL6.1(2.6.32-131.0.15), perf_swevent_init() exist 
> in kernel/perf_event.c.  So the sample systemtap script in KB
> doesn't work.
> 
> RHEL6.2 or later, the perf_swevent_init() exist in kernel/events/core.c.
> 
> Why don't we just specify kernel.function("perf_swevent_init")
> without code path?

thank you very much for your report! The issue should be fixed now.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 53 Rados Gregoric 2013-05-16 06:15:22 EDT
How long does it take to complete script?

Tried script from #13 and also from: 
https://access.redhat.com/site/solutions/373743
(slightly different)

but stap command never ends

# stap -g sanitize1.stp

# ps aux | grep stap
root      9666  0.0  2.1 373452 84460 pts/0    S+   11:34   0:01 stap -g sanitize1.stp
root      9878  0.0  0.0 123588   792 pts/0    Sl+  11:34   0:00 /usr/libexec/systemtap/stapio -R stap_fa58fdb9be5354a95c81bd681b6795e3_9878

# uname -r
2.6.32-220.17.1.el6.x86_64

Thanks

(In reply to comment #13)
> To mitigate the issue:
> 
> 
> 3) Run the "stap -g [filename-from-step-1].stp" command as root.
>
Comment 54 Jesper Brouer 2013-05-16 07:01:11 EDT
(In reply to comment #50)
> thank you very much for your report! The issue should be fixed now.

Just to spell it out, the work-around systemtap script that disables the exploit runtime is available here:

  https://access.redhat.com/site/solutions/373743


And systemtap dependency install instructions here:
 https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/SystemTap_Beginners_Guide/using-systemtap.html
Comment 55 Petr Matousek 2013-05-16 07:12:30 EDT
Hello, Rados.

(In reply to comment #53)
> How long does it take to complete script?

> Tried script from #13 and also from: 
> https://access.redhat.com/site/solutions/373743
> (slightly different)

We try to keep all the sources that contain the script in sync.

> 
> but stap command never ends

What you see is correct behaviour. The script does not end without being forcibly stopped when ran the way presented.

If you want to detach from the running script, please use the -F option as follows:

stap -F -g sanitize1.stp

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 56 Tobias Dussa 2013-05-16 09:04:10 EDT
Hi,

(In reply to comment #52 https://bugzilla.redhat.com/show_bug.cgi?id=962792#c52)
> We are working on testing the updated packages to correct this issue in Red Hat > Enterprise Linux 6 and will release them ASAP.

Is there any estimate at all as to what "ASAP" might mean?  Are we talking hours, days, weeks?

THX & Cheers,
Toby.
Comment 57 Shawn Rhode 2013-05-16 09:33:30 EDT
I was testing the original, in the wild exploit on various systems and noticed that attempting to perform this on a RHEL6 x86_64 domU (Xen Hypervisor, full PV) caused that domU to panic.  The same binary worked on bare metal RHEL6 x86-64, so I know the binary works and this is specific to being a domU.

This is the flags on the CPUs in cpuinfo:
flags           : fpu de tsc msr pae cx8 cmov pat clflush mmx fxsr sse sse2 ss ht syscall nx lm rep_good aperfmperf unfair_spinlock pni ssse3 cx16 sse4_1 hypervisor lahf_lm dts 

Shawn
Comment 58 Petr Matousek 2013-05-16 09:39:44 EDT
Hello, Tobias.

(In reply to comment #56)
> (In reply to comment #52
> https://bugzilla.redhat.com/show_bug.cgi?id=962792#c52)
> > We are working on testing the updated packages to correct this issue in Red Hat > Enterprise Linux 6 and will release them ASAP.
> 
> Is there any estimate at all as to what "ASAP" might mean?  Are we talking
> hours, days, weeks?

Hour(s). We just started the process of releasing the kernel errata for Red Hat Enterprise Linux 6.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 59 Tobias Dussa 2013-05-16 09:43:26 EDT
Petr,

thanks a lot for the quick reply.

Cheers,
Toby.
Comment 60 errata-xmlrpc 2013-05-16 11:24:38 EDT
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6

Via RHSA-2013:0830 https://rhn.redhat.com/errata/RHSA-2013-0830.html
Comment 61 Petr Matousek 2013-05-16 12:47:06 EDT
Hello, Shawn.

(In reply to comment #57)
> I was testing the original, in the wild exploit on various systems and
> noticed that attempting to perform this on a RHEL6 x86_64 domU (Xen
> Hypervisor, full PV) caused that domU to panic.  The same binary worked on
> bare metal RHEL6 x86-64, so I know the binary works and this is specific to
> being a domU.

Yes, Xen PV DomUs don't have direct access to harware IDT (Interrupt descriptor table) and use hypercalls to register virtual IDT entries with the hypervisor.

The original "semtex" exploit expects IDT to be in (to point to) the DomU kernel memory region and not the Xen hypervisor memory region and that is not true for PV domains. The result is invalid memory access and DomU crash.

The exploit should work as is in HVM domain.

Please note that the security issue could still be exploited on PV domains, but not with the public exploit (except for the user triggered DomU crash).

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 62 Shawn Rhode 2013-05-16 15:12:32 EDT
Thank you for the response Petr.  That makes complete sense.  Will the fix that has been made available prevent the crash from occurring or does that issue still need to be addressed?  Even though it doesn't give a user root access, having the server crash causes a DOS effect to the end server.
Comment 63 Yves-Alexis Perez 2013-05-16 15:58:31 EDT
(In reply to comment #36)
> I would rather not mate, I did that yesterday, and it crashed the machine.
> ;-p

That's because SMEP only prevents the code execution by the kernel in userland address space.

The vulnerability is triggered by overwriting the interrupt handler for int 0x4 to the shellcode address, then calling int 0x4. With SMEP, the last step fails but the IDT overwrite is not prevented.

So you now have an interrupt handler address which will trigger SMEP each time it happens and indeed it's not pretty: it page faults, the exception is handled in the kernel, another overflow happens, page faults etc.
Comment 64 Petr Matousek 2013-05-17 02:52:12 EDT
Hello, Shawn.

(In reply to comment #62)
> Thank you for the response Petr.  That makes complete sense.  Will the fix
> that has been made available prevent the crash from occurring or does that
> issue still need to be addressed?  Even though it doesn't give a user root
> access, having the server crash causes a DOS effect to the end server.

The fix addresses the DoS effect you are seeing too.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 65 errata-xmlrpc 2013-05-17 11:17:44 EDT
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6.3 EUS - Server Only

Via RHSA-2013:0832 https://rhn.redhat.com/errata/RHSA-2013-0832.html
Comment 68 Peccary Chen 2013-05-18 23:41:57 EDT
Can kernel ASLR prevent this exploit?
Comment 69 Petr Matousek 2013-05-19 04:33:26 EDT
(In reply to comment #68)
> Can kernel ASLR prevent this exploit?

Kernel ASLR cannot prevent this bug from being exploited.

Best regards,
--
Petr Matousek / Red Hat Security Response Team
Comment 70 errata-xmlrpc 2013-05-20 12:26:38 EDT
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6.1 EUS - Server Only

Via RHSA-2013:0841 https://rhn.redhat.com/errata/RHSA-2013-0841.html
Comment 71 errata-xmlrpc 2013-05-20 12:28:38 EDT
This issue has been addressed in following products:

  Red Hat Enterprise Linux 6.2 EUS - Server Only

Via RHSA-2013:0840 https://rhn.redhat.com/errata/RHSA-2013-0840.html
Comment 72 errata-xmlrpc 2013-05-20 12:59:37 EDT
This issue has been addressed in following products:

  MRG for RHEL-6 v.2

Via RHSA-2013:0829 https://rhn.redhat.com/errata/RHSA-2013-0829.html
Comment 78 Alexa 2014-02-02 20:39:05 EST
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen live from the domain http://volichat.com/adult-chat-rooms
Marked for reference. Resolved as fixed @bugzilla.