mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
Import a missing piece of commit b8fac8e162eda7e98d from illumos-gate.
This adds an upper bound, dtrace_ustackdepth_max, to the number of frames traversed when computing the userland stack depth. Some programs - notably firefox - are otherwise able to trigger an infinite loop in dtrace_getustack_common(), causing a panic. MFC after: 1 week
This commit is contained in:
parent
53b2405ec0
commit
09a15aa38d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=280834
@ -49,6 +49,8 @@ uint16_t dtrace_fuword16_nocheck(void *);
|
||||
uint32_t dtrace_fuword32_nocheck(void *);
|
||||
uint64_t dtrace_fuword64_nocheck(void *);
|
||||
|
||||
int dtrace_ustackdepth_max = 2048;
|
||||
|
||||
void
|
||||
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
|
||||
uint32_t *intrpc)
|
||||
@ -102,14 +104,25 @@ static int
|
||||
dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
uintptr_t sp)
|
||||
{
|
||||
uintptr_t oldsp;
|
||||
volatile uint16_t *flags =
|
||||
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
||||
int ret = 0;
|
||||
|
||||
ASSERT(pcstack == NULL || pcstack_limit > 0);
|
||||
ASSERT(dtrace_ustackdepth_max > 0);
|
||||
|
||||
while (pc != 0) {
|
||||
ret++;
|
||||
/*
|
||||
* We limit the number of times we can go around this
|
||||
* loop to account for a circular stack.
|
||||
*/
|
||||
if (ret++ >= dtrace_ustackdepth_max) {
|
||||
*flags |= CPU_DTRACE_BADSTACK;
|
||||
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcstack != NULL) {
|
||||
*pcstack++ = (uint64_t)pc;
|
||||
pcstack_limit--;
|
||||
@ -120,10 +133,18 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
if (sp == 0)
|
||||
break;
|
||||
|
||||
oldsp = sp;
|
||||
|
||||
pc = dtrace_fuword64((void *)(sp +
|
||||
offsetof(struct amd64_frame, f_retaddr)));
|
||||
sp = dtrace_fuword64((void *)sp);
|
||||
|
||||
if (sp == oldsp) {
|
||||
*flags |= CPU_DTRACE_BADSTACK;
|
||||
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is totally bogus: if we faulted, we're going to clear
|
||||
* the fault and break. This is to deal with the apparently
|
||||
|
@ -55,6 +55,8 @@ uint16_t dtrace_fuword16_nocheck(void *);
|
||||
uint32_t dtrace_fuword32_nocheck(void *);
|
||||
uint64_t dtrace_fuword64_nocheck(void *);
|
||||
|
||||
int dtrace_ustackdepth_max = 2048;
|
||||
|
||||
void
|
||||
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
|
||||
uint32_t *intrpc)
|
||||
@ -113,11 +115,13 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
|
||||
size_t s1, s2;
|
||||
#endif
|
||||
uintptr_t oldsp;
|
||||
volatile uint16_t *flags =
|
||||
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
||||
int ret = 0;
|
||||
|
||||
ASSERT(pcstack == NULL || pcstack_limit > 0);
|
||||
ASSERT(dtrace_ustackdepth_max > 0);
|
||||
|
||||
#ifdef notyet /* XXX signal stack. */
|
||||
if (p->p_model == DATAMODEL_NATIVE) {
|
||||
@ -130,7 +134,16 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
#endif
|
||||
|
||||
while (pc != 0) {
|
||||
ret++;
|
||||
/*
|
||||
* We limit the number of times we can go around this
|
||||
* loop to account for a circular stack.
|
||||
*/
|
||||
if (ret++ >= dtrace_ustackdepth_max) {
|
||||
*flags |= CPU_DTRACE_BADSTACK;
|
||||
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcstack != NULL) {
|
||||
*pcstack++ = (uint64_t)pc;
|
||||
pcstack_limit--;
|
||||
@ -141,6 +154,8 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
if (sp == 0)
|
||||
break;
|
||||
|
||||
oldsp = sp;
|
||||
|
||||
#ifdef notyet /* XXX signal stack. */
|
||||
if (oldcontext == sp + s1 || oldcontext == sp + s2) {
|
||||
if (p->p_model == DATAMODEL_NATIVE) {
|
||||
@ -179,6 +194,12 @@ dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
||||
sp = dtrace_fuword32((void *)sp);
|
||||
#endif /* ! notyet */
|
||||
|
||||
if (sp == oldsp) {
|
||||
*flags |= CPU_DTRACE_BADSTACK;
|
||||
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is totally bogus: if we faulted, we're going to clear
|
||||
* the fault and break. This is to deal with the apparently
|
||||
|
Loading…
Reference in New Issue
Block a user