- 学习目的:kernel stack overflow.
案例分析:查看commit,如下所示:
diff --git a/Makefile b/Makefile
index fa6c80d..550d425 100644
--- a/Makefile
+++ b/Makefile
@@ -190,6 +190,7 @@ UPROGS=\
_foo\
_nice\
_ps\
+ _wastestack\
fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS)
@@ -261,7 +262,7 @@ qemu-nox-gdb: fs.img xv6.img .gdbinit
EXTRA=\
mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\
ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c app.c zombie.c date.c\
- printf.c scanf.c umalloc.c alarmtest.c foo.c ps.c nice.c\
+ printf.c scanf.c umalloc.c alarmtest.c foo.c ps.c nice.c wastestack.c\
README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\
.gdbinit.tmpl gdbutil\
diff --git a/defs.h b/defs.h
index 9da63e9..cd99d39 100644
--- a/defs.h
+++ b/defs.h
@@ -119,6 +119,7 @@ void yield(void);
//albert
int cps (void);
int chpr(int,int);
+void wastestack(int);
// swtch.S
void swtch(struct context**, struct context*);
diff --git a/param.h b/param.h
index a7e90ef..c1663d2 100644
--- a/param.h
+++ b/param.h
@@ -1,5 +1,7 @@
#define NPROC 64 // maximum number of processes
-#define KSTACKSIZE 4096 // size of per-process kernel stack
+//#define KSTACKSIZE 4096 // size of per-process kernel stack
+//albert
+#define KSTACKSIZE 2048 // size of per-process kernel stack
#define NCPU 8 // maximum number of CPUs
#define NOFILE 16 // open files per process
#define NFILE 100 // open files per system
diff --git a/proc.c b/proc.c
index 7e91e16..696f449 100644
--- a/proc.c
+++ b/proc.c
@@ -703,6 +703,21 @@ cps(void)
return 22;
}
+//albert
+void
+wastestack(int recursive)
+{
+ struct proc *p = myproc();
+
+ cprintf("wastestack = %d\n",recursive);
+ while(recursive){
+ wastestack(recursive-1);
+ }
+
+ panic("wastestack: no kstack");
+}
+
struct proc *getptable_proc(void) {
return ptable.proc;
}
diff --git a/syscall.c b/syscall.c
index 826bced..387b293 100644
--- a/syscall.c
+++ b/syscall.c
@@ -110,6 +110,7 @@ extern int sys_alarm(void);
extern int sys_cps(void);
extern int sys_getptable(void);
extern int sys_chpr(void);
+extern int sys_wastestack(void);
static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
@@ -139,6 +140,7 @@ static int (*syscalls[])(void) = {
[SYS_cps] sys_cps,
[SYS_getptable] sys_getptable,
[SYS_chpr] sys_chpr,
+[SYS_wastestack] sys_wastestack,
};
//albert
diff --git a/syscall.h b/syscall.h
index 37c2614..a4fdd69 100644
--- a/syscall.h
+++ b/syscall.h
@@ -26,3 +26,4 @@
#define SYS_cps 24
#define SYS_getptable 25
#define SYS_chpr 26
+#define SYS_wastestack 27
diff --git a/sysproc.c b/sysproc.c
index 0b7e893..dc473be 100644
--- a/sysproc.c
+++ b/sysproc.c
@@ -181,3 +181,17 @@ int sys_chpr(void)
cprintf("albert:pid=%d,pr=%d\n",pid,pr);
return chpr(pid,pr);
}
+
+
+//albert
+int sys_wastestack(void)
+{
+ int recursive;
+
+ if(argint(0,&recursive) < 0)
+ return -1;
+ cprintf("albert:recursive=%d\n",recursive);
+
+ wastestack(recursive);
+ return 0;
+}
diff --git a/user.h b/user.h
index 0ef59b0..d83734e 100644
--- a/user.h
+++ b/user.h
@@ -29,6 +29,7 @@ int alarm(int ticks,void (*handler)());
int cps(void);
int getptable(int, void*);
int chpr(int, int);
+int wastestack(int);
// ulib.c
int stat(const char*, struct stat*);
diff --git a/usys.S b/usys.S
index eeafe1a..c2058ad 100644
--- a/usys.S
+++ b/usys.S
@@ -35,3 +35,4 @@ SYSCALL(alarm)
SYSCALL(cps)
SYSCALL(getptable)
SYSCALL(chpr)
+SYSCALL(wastestack)
调试步骤:
窗口1:
make qemu-nox-gdb
./wastestack //窗口2执行之后再执行该命令
窗口2:
The target architecture is assumed to be i8086
[f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file kernel
(gdb) file wastestack.o
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "wastestack.o"? (y or n) y
Reading symbols from wastestack.o...done.
(gdb) b main
Breakpoint 1 at 0x10: file wastestack.c, line 10.
(gdb) c
Continuing.
[New Thread 2]
[Switching to Thread 2]
[ 1b: 10] 0x1c0: add %al,(%bx,%si)
Breakpoint 1, main (argc=0, argv=0x0) at wastestack.c:10
10 {
(gdb) b *0x801040c1
Breakpoint 2 at 0x801040c1
(gdb) c
Continuing.
执行之后,出现stack overflow,log如下所示:
wastestack = 80119
wastestack = 80118
wastestack = 80117
wastestack = 80116
wastestack = 80115
EAX=ffffffee EBX=00000082 ECX=8dfbe800 EDX=00000000
ESI=80111b80 EDI=80111b84 EBP=80108008 ESP=80107ff0
EIP=80103638 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0028 80111b88 00000067 00408900 DPL=0 TSS32-avl
GDT= 80111bf0 0000002f
IDT= 801145a0 000007ff
CR0=80010011 CR2=80107fec CR3=0df22000 CR4=00000010
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
EFER=0000000000000000
Triple fault. Halting for inspection via QEMU monitor.
问题:What is Triple fault?
When a fault occurs, the CPU invokes an exception handler. If a fault occurs while trying to invoke the exception handler, that’s called a double fault, which the CPU tries to handle with yet another exception handler. If that invocation results in a fault too, the system reboots with a triple fault.
Note that a fault that occurs while a fault handler is already running does not of itself cause a double or triple fault. For example, if a Segment Not Present Fault occurs after a handler has already started, then the Segment Not Present handler will run as normal. However, if the code segment of the original handler is itself not Present, then the double (or triple) fault would occur since the original handler hadn’t started yet.
A triple fault is usually a sign that the exception handler called is faulty, or worse, that the whole exception handling in your system is screwed up. (LDT or GDT issues, bogus pointers or faulty memory mappings are frequent offenders.)
Another frequent cause of triple faults is a kernel stack overflow. If the stack reaches an invalid page (one with its present bit clear), a page fault is generated. However, the CPU faults while trying to push the exception information on to the stack, so a double fault is generated. The same problem still exists so a triple fault is generated.