LWN.net Logo

The x86 denial of service bug

The current 2.5 and 2.4.20-rc releases both contain a patch for a newly-discovered vulnerability in the Linux kernel. Simply put, anybody who can run an arbitrary program on a Linux system can bring it down in flames. Your editor, who is not an expert on x86 assembly (but who can still describe the difference between CDC 6xxx A, B, and X registers), has made an effort to figure out just what is going on here, for those who are curious.

The x86 processor contains many flags which affect its operation. Two of these flags are abused in this exploit:

  • The trap flag (TF) causes a processor trap to happen after execution of every instruction. It is used primarily for debugging purposes.

  • The nested task (NT) flag indicates that the current task is executing via an interrupt (or other task-switching operation) that causes another task to be suspended. It is part of the hardware task switching mechanism, which Linux makes only limited use of. When the NT flag is set, the iret instruction performs a hardware task switch via the "backlink" field in the task state segment (TSS). Without NT, iret looks much like a normal return.

The DOS attack works, essentially, by setting both flags (TF and NT), then jumping into the kernel with an lcall instruction. The kernel code did not clear those flags when entered via that path. Thus, the setting of TF would cause an immediate processor trap within the kernel code. That, by itself, is relatively harmless, except that the trap handler returns via iret. That instruction, seeing that the NT flag is set, attempts to perform a task switch via the TSS - an operation the kernel was not expecting, and which had not been prepared for. So the kernel switches into a nonexistent task, and everything comes to a stop. It is at this point that one begins to appreciate the virtues of journaling filesystems.

The solution, as coded up by Linus, is simply to clear those flags when the kernel is entered via a call gate. End of problem - once you get the patch installed.

The call entry code has not changed in a long time, so even very old kernels are affected. The current 2.4.20 release candidate includes a fix, and the distributors are beginning (slowly) to release updates which fix the problem. 2.2 kernels are also vulnerable; if you have a 2.2-based system running with untrusted users, you may want to rebuild the kernel with this patch from Matthew Grant applied.


(Log in to post comments)

The x86 denial of service bug

Posted Nov 19, 2002 18:55 UTC (Tue) by rknop (guest, #66) [Link]

The current 2.5 and 2.4.20-rc releases both contain a bug for a newly-discovered vulnerability

Did you mean patch for the vulnerability?

-Rob

The x86 denial of service bug

Posted Nov 19, 2002 19:14 UTC (Tue) by corbet (editor, #1) [Link]

Yeah, I suppose I probably meant something like that...

The x86 denial of service bug

Posted Nov 19, 2002 19:15 UTC (Tue) by rknop (guest, #66) [Link]

...although, technically, a "bug" for the vulnerability might not be so bad. After all, the vulnerability doesn't work right in the newest kernels....

The x86 denial of service bug

Posted Nov 19, 2002 19:08 UTC (Tue) by einstein (subscriber, #2052) [Link]

As is often the case, Red Hat had a fix out for this within hours.

I guess it helps that they have a key kernel developer on staff -

Cheers,

einstein - happily running RH 7.3 and RH 8.0 with kernels updated.

2.2.x also vulnerable - WATCH OUT!!

Posted Nov 19, 2002 22:06 UTC (Tue) by grantma (subscriber, #5225) [Link]

I have been working on this one, and noone so far has produced any headlines about it, but 2.2.x is ALSO affected.

I have tested and found 2.2.x is vulnerable with Andrea Arcahneli's exploit. It also has exactly the same lcall7() function in the system
call interface as 2.4.x, and is definitely vulnerable. The patch below STOPS the crashes in 2.2.x

Result of bug isa as in 2.4.x, an absolute lockup of the machine. This
is an easy vulnerablity for a script kiidy to turn any network accessible
buffer overfolw into a DOS.

Here is the patch to fix 2.2:

--- linux/arch/i386/kernel/entry.S.orig Sat Nov 3 05:39:05 2001
+++ linux/arch/i386/kernel/entry.S Tue Nov 19 13:46:47 2002
@@ -63,7 +63,9 @@
OLDSS = 0x38

CF_MASK = 0x00000001
+TF_MASK = 0x00000100
IF_MASK = 0x00000200
+DF_MASK = 0x00000400
NT_MASK = 0x00004000
VM_MASK = 0x00020000

@@ -139,6 +141,9 @@
movl CS(%esp),%edx # this is eip..
movl EFLAGS(%esp),%ecx # and this is cs..
movl %eax,EFLAGS(%esp) #
+ andl $~(NT_MASK|TF_MASK|DF_MASK), %eax
+ pushl %eax
+ popfl
movl %edx,EIP(%esp) # Now we move them to their "normal" places
movl %ecx,CS(%esp) #
movl %esp,%ebx

The x86 denial of service bug

Posted Nov 22, 2002 14:26 UTC (Fri) by tsr2 (subscriber, #4293) [Link]

Does anybody here know what other OSes are vulnerable to this sort of attack?

Copyright © 2002, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds