Hi,
I was trying to reproduce the error of %eip corruption and I manage to
get a small test program (from my previous one).
----------
/*
* This program try to cause an exception raising a Xen failsafe callback
* The idea is:
* - one thread execute an infinite loop with some int3 instructions before
* and a CS segment allocated in LDT while handling a timer signal
* - another thread just make sure that first is in the infinite loop and
* set CS to cause an exception on the first one
* The first thread does not core just after the LDT change cause CS is cached
* to it crash when kernel try to return to it.
* Actually the first one running in the infinite loop can be stopped only by
* an hardware interrupt so you have a Xen callback which try to return and
* get an exception while doing IRET
*/
#undef NDEBUG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#include <sys/time.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <asm/ldt.h>
#include <pthread.h>
#define LDT_READ 0
#define LDT_WRITE 1
static void handler(int sig)
{
static unsigned count = 0;
if (++count == 60 * 1000)
exit(0);
}
static void segv_handler(int sig)
{
exit(0);
}
static int cs_ldt = -1;
static void
change_cs(void)
{
struct user_desc desc;
/* fills desc which represents the code segment */
desc.entry_number = 0;
desc.base_addr = 0;
desc.limit = 0xffffffffu >> 12;
desc.seg_32bit = 0x1;
desc.contents = 0x2;
desc.read_exec_only = 0x1;
desc.limit_in_pages = 0x1;
desc.seg_not_present = 0x0;
desc.useable = 0x1;
/* Writes a user_desc struct to the ldt */
int err = syscall(SYS_modify_ldt, LDT_WRITE,
&desc, sizeof(desc));
assert(!err);
/* set cs to our selector to be able to make it core */
asm(
" pushl %eax\n"
" movl $0x7, %eax\n" /* 0111: 0-Index 1-Using the LDT table 11-RPL of
3 */
" pushl %eax\n"
" pushl $1f\n"
" retf\n"
"1:\n"
" popl %eax\n"
);
cs_ldt = (desc.entry_number << 3) | 7;
}
static void *
corrupt_cs(void *arg)
{
/* this assure that we set the selector while in the loop */
sleep(2);
assert(cs_ldt >= 0);
struct user_desc desc;
/* fills desc which represents the code segment */
desc.entry_number = cs_ldt >> 3;
desc.base_addr = 0;
desc.limit = 1;
desc.seg_32bit = 0x1;
desc.contents = 0x2;
desc.read_exec_only = 0x1;
desc.limit_in_pages = 0x1;
desc.seg_not_present = 0x1;
desc.useable = 0x1;
/* Writes a user_desc struct to the ldt */
int err = syscall(SYS_modify_ldt, LDT_WRITE,
&desc, sizeof(desc));
assert(!err);
return NULL;
}
static void
faulty(void)
{
#if !defined(__x86_64__) && !defined(__i386__)
# error This code work only on Intel architecture!
#endif
// wait for a core !!
asm(
#ifdef __x86_64__
" mov $-513, %rax\n"
#else
" mov $-513, %eax\n"
#endif
" jmp 1f\n"
" int $3\n"
" int $3\n"
" int $3\n"
" int $3\n"
"1:\n"
" jmp 1b\n"
);
}
int main(void)
{
struct sigaction act;
// set signal
sigfillset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = handler;
int err = sigaction(SIGALRM, &act, NULL);
assert(!err);
act.sa_handler = segv_handler;
err = sigaction(SIGSEGV, &act, NULL);
assert(!err);
// set timer
struct itimerval ival = { { 0, 1000 }, { 0, 1000 } };
err = setitimer(ITIMER_REAL, &ival, NULL);
assert(!err);
pthread_t thread_id;
err = pthread_create(&thread_id, NULL, corrupt_cs, NULL);
assert(!err);
/* for some reasons pthread_create restre original cs */
change_cs();
/* faulting with SEGV is ok! */
faulty();
return 0;
}
----------
I run the program with this shell script
----------
#!/bin/bash
set -e
cd /
test -x xencore32
while true; do
echo running test
set +e
su nobody -s /xencore32 && echo ok
set -e
done
----------
The problems are now two:
- when program crash "normally" is cause an invalid instruction to be
executed while it should raise a SEGV
- sometimes it crashes very badly with an exception on the kernel and
after a couple of time you can be lucky and have your dom0 quite
useless.
When it crashes very badly I got this on screen (I couldn''t use dmesg)
[ 242.372564] Process xencore32 (pid: 6645, ti=e797e000 task=e98957f0
task.ti=e797e000)
[ 242.372615] Stack:
[ 242.372665] Call Trace:
[ 242.372691] <IRQ>
[ 242.373864] Process xencore32 (pid: 6645, ti=e797e000 task=e98957f0
task.ti=e797e000)
[ 242.373916] Stack:
[ 242.374243] Call Trace:
[ 242.374803] Code: 8b 4d 10 85 c9 74 13 3b 5d 10 73 32 8b 45 10 2d 00
20 00 00 39 c3 73 13 eb 24 3b 5d f0 76 1f 8b 45 f0 05 fc 1f 00 00 39 c3
[ 242.375302] EIP: [<c1013c04>] print_context_stack+0x94/0xc0 SS:ESP
0069:e797fe00
Anybody has some hint on how to resolve this problem?
Regards
Frediano