Author: markj
Date: Mon Apr 13 01:42:24 2015
New Revision: 281482
URL: https://svnweb.freebsd.org/changeset/base/281482

Log:
  MFC r280834:
  Bound the number of frames traversed when executing the ustackdepth action.

Modified:
  stable/10/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
  stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
==============================================================================
--- stable/10/sys/cddl/dev/dtrace/amd64/dtrace_isa.c    Mon Apr 13 01:19:22 
2015        (r281481)
+++ stable/10/sys/cddl/dev/dtrace/amd64/dtrace_isa.c    Mon Apr 13 01:42:24 
2015        (r281482)
@@ -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 *pcstac
                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

Modified: stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c
==============================================================================
--- stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c     Mon Apr 13 01:19:22 
2015        (r281481)
+++ stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c     Mon Apr 13 01:42:24 
2015        (r281482)
@@ -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 *pcstac
        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 *pcstac
 #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 *pcstac
                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 *pcstac
                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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to