Virtualise the stack rlimit for the main thread and make valgrind enforce
that limit when growing the stack. Also add a message when the stack in any
thread overflows.
CCMAIL: 73818-done@bugs.kde.org
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2689 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/core.h b/coregrind/core.h
index deff872..2a99c42 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -1243,6 +1243,7 @@
extern Addr VG_(valgrind_last); // Nb: last byte, rather than one past the end
extern vki_rlimit VG_(client_rlimit_data); /* client's original rlimit data */
+extern vki_rlimit VG_(client_rlimit_stack); /* client's original rlimit stack */
/* client executable file descriptor */
extern Int VG_(clexecfd);
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 183fa2e..a077d58 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -113,6 +113,7 @@
Addr VG_(valgrind_last);
vki_rlimit VG_(client_rlimit_data);
+vki_rlimit VG_(client_rlimit_stack);
/* This is set early to indicate whether this CPU has the
SSE/fxsave/fxrestor features. */
@@ -2496,7 +2497,10 @@
VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
zero.rlim_max = VG_(client_rlimit_data).rlim_max;
VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
-
+
+ // Get the current process stack rlimit.
+ VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
+
//--------------------------------------------------------------
// Check we were launched by stage1
// p: n/a
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index b181746..cf4050c 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -394,7 +394,7 @@
*/
void VG_(scheduler_init) ( void )
{
- Int i;
+ Int i;
ThreadId tid_main;
for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) {
@@ -428,7 +428,7 @@
VG_(threads)[tid_main].stack_highest_word
= VG_(clstk_end) - 4;
VG_(threads)[tid_main].stack_base = VG_(clstk_base);
- VG_(threads)[tid_main].stack_size = VG_(clstk_end) - VG_(clstk_base);
+ VG_(threads)[tid_main].stack_size = VG_(client_rlimit_stack).rlim_cur;
/* So now ... */
vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c
index 4f4061b..9a8ace7 100644
--- a/coregrind/vg_signals.c
+++ b/coregrind/vg_signals.c
@@ -2109,7 +2109,8 @@
then extend the stack segment.
*/
Addr base = PGROUNDDN(esp);
- if ((void*)-1 != VG_(mmap)((Char *)base, seg->addr - base,
+ if (seg->len + (seg->addr - base) <= VG_(threads)[tid].stack_size &&
+ (void*)-1 != VG_(mmap)((Char *)base, seg->addr - base,
VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
VKI_MAP_PRIVATE|VKI_MAP_FIXED|VKI_MAP_ANONYMOUS|VKI_MAP_CLIENT,
SF_STACK|SF_GROWDOWN,
@@ -2138,6 +2139,14 @@
recursion--;
}
}
+
+ if (info->si_code == 1 && /* SEGV_MAPERR */
+ seg != NULL &&
+ fault >= esp &&
+ fault < seg->addr &&
+ (seg->flags & SF_STACK)) {
+ VG_(message)(Vg_UserMsg, "Stack overflow in thread %d", tid);
+ }
}
/* Can't continue; must longjmp back to the scheduler and thus
diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c
index 2934f40..14ea259 100644
--- a/coregrind/vg_syscalls.c
+++ b/coregrind/vg_syscalls.c
@@ -2346,6 +2346,10 @@
case VKI_RLIMIT_DATA:
*((vki_rlimit *)arg2) = VG_(client_rlimit_data);
break;
+
+ case VKI_RLIMIT_STACK:
+ *((vki_rlimit *)arg2) = VG_(client_rlimit_stack);
+ break;
}
}
@@ -4692,6 +4696,17 @@
VG_(client_rlimit_data) = *(vki_rlimit *)arg2;
res = 0;
}
+ else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
+ if (((vki_rlimit *)arg2)->rlim_cur > ((vki_rlimit *)arg2)->rlim_max ||
+ ((vki_rlimit *)arg2)->rlim_max > ((vki_rlimit *)arg2)->rlim_max) {
+ res = -VKI_EPERM;
+ }
+ else {
+ VG_(threads)[tid].stack_size = ((vki_rlimit *)arg2)->rlim_cur;
+ VG_(client_rlimit_stack) = *(vki_rlimit *)arg2;
+ res = 0;
+ }
+ }
}
PRE(setuid)