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);
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. */
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
*/
void VG_(scheduler_init) ( void )
{
- Int i;
+ Int i;
ThreadId tid_main;
for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) {
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);
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,
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
case VKI_RLIMIT_DATA:
*((vki_rlimit *)arg2) = VG_(client_rlimit_data);
break;
+
+ case VKI_RLIMIT_STACK:
+ *((vki_rlimit *)arg2) = VG_(client_rlimit_stack);
+ break;
}
}
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)