summaryrefslogtreecommitdiffstats
path: root/sys/cddl/dev/dtrace/i386/dtrace_isa.c
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2015-04-13 01:42:24 +0000
committermarkj <markj@FreeBSD.org>2015-04-13 01:42:24 +0000
commitb4c145b73c8254b7a509a5fcaee8cb84ebd67930 (patch)
treebd9ceeb8561eef3954822860ce8c4110715f5ca7 /sys/cddl/dev/dtrace/i386/dtrace_isa.c
parent14c57b50a3a5a445d5b1800b9dd92a311d81f6e2 (diff)
downloadFreeBSD-src-b4c145b73c8254b7a509a5fcaee8cb84ebd67930.zip
FreeBSD-src-b4c145b73c8254b7a509a5fcaee8cb84ebd67930.tar.gz
MFC r280834:
Bound the number of frames traversed when executing the ustackdepth action.
Diffstat (limited to 'sys/cddl/dev/dtrace/i386/dtrace_isa.c')
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_isa.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_isa.c b/sys/cddl/dev/dtrace/i386/dtrace_isa.c
index 21a8154..6c261bf 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_isa.c
+++ b/sys/cddl/dev/dtrace/i386/dtrace_isa.c
@@ -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
OpenPOWER on IntegriCloud