summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorBryan Cantrill <bryan@joyent.com>2016-06-07 21:21:23 +0000
committerRobert Mustacchi <rm@joyent.com>2016-06-08 13:25:59 -0700
commit82d2d142300e27cbe46f9fd3731e9d280b2c66e8 (patch)
tree66d0292b6d2645f081ae04de6fa44a0f8994b5da /usr/src
parentf11ba53f80410731989b127bc0e36a178773e84a (diff)
downloadillumos-joyent-82d2d142300e27cbe46f9fd3731e9d280b2c66e8.tar.gz
7084 DTrace divide overflow can induce panic
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d38
-rw-r--r--usr/src/pkg/manifests/system-dtrace-tests.mf3
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c8
-rw-r--r--usr/src/uts/i86pc/ml/genassym.c1
-rw-r--r--usr/src/uts/i86pc/ml/locore.s33
5 files changed, 73 insertions, 10 deletions
diff --git a/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d b/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d
new file mode 100644
index 0000000000..a8fb302f3b
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d
@@ -0,0 +1,38 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2016, Joyent, Inc. All rights reserved.
+ */
+
+BEGIN
+{
+ v = 0x8000000000000000LL;
+ print((long)v % -1);
+}
+
+ERROR
+/arg4 == DTRACEFLT_DIVZERO/
+{
+ exit(0);
+}
+
+ERROR
+{
+ printf("unexpected error code %d", arg4);
+ exit(1);
+}
+
+BEGIN
+{
+ printf("did not get expected error");
+ exit(1);
+}
diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf
index 8afe5cccb6..85c8d273dd 100644
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf
@@ -39,6 +39,7 @@ dir path=opt/SUNWdtrt/lib/java
dir path=opt/SUNWdtrt/tst
dir path=opt/SUNWdtrt/tst/$(ARCH)
dir path=opt/SUNWdtrt/tst/$(ARCH)/arrays
+$(i386_ONLY)dir path=opt/SUNWdtrt/tst/$(ARCH)/error
$(i386_ONLY)dir path=opt/SUNWdtrt/tst/$(ARCH)/funcs
dir path=opt/SUNWdtrt/tst/$(ARCH)/pid
$(sparc_ONLY)dir path=opt/SUNWdtrt/tst/$(ARCH)/usdt
@@ -140,6 +141,8 @@ file path=opt/SUNWdtrt/bin/exception.lst mode=0444
file path=opt/SUNWdtrt/bin/jdtrace mode=0555
file path=opt/SUNWdtrt/lib/java/jdtrace.jar
file path=opt/SUNWdtrt/tst/$(ARCH)/arrays/tst.uregsarray.d mode=0444
+$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/error/tst.DTRACEFLT_DIVZERO.d \
+ mode=0444
$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/funcs/tst.badcopyin.d mode=0444
$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/funcs/tst.badcopyinstr.d \
mode=0444
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index c775224d86..3aeeef27f7 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -5759,8 +5759,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int64_t)regs[r1] /
(int64_t)regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5769,7 +5771,9 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = regs[r1] / regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5778,8 +5782,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int64_t)regs[r1] %
(int64_t)regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5788,7 +5794,9 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = regs[r1] % regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
diff --git a/usr/src/uts/i86pc/ml/genassym.c b/usr/src/uts/i86pc/ml/genassym.c
index 168a55cc84..088dd661a3 100644
--- a/usr/src/uts/i86pc/ml/genassym.c
+++ b/usr/src/uts/i86pc/ml/genassym.c
@@ -174,6 +174,7 @@ main(int argc, char *argv[])
printf("#define\tCPU_DTRACE_NOFAULT 0x%x\n", CPU_DTRACE_NOFAULT);
printf("#define\tCPU_DTRACE_BADADDR 0x%x\n", CPU_DTRACE_BADADDR);
+ printf("#define\tCPU_DTRACE_DIVZERO 0x%x\n", CPU_DTRACE_DIVZERO);
printf("#define\tCPU_DTRACE_ILLOP 0x%x\n", CPU_DTRACE_ILLOP);
printf("#define\tMODS_NOUNLOAD 0x%x\n", MODS_NOUNLOAD);
diff --git a/usr/src/uts/i86pc/ml/locore.s b/usr/src/uts/i86pc/ml/locore.s
index 91e38307ca..042818844d 100644
--- a/usr/src/uts/i86pc/ml/locore.s
+++ b/usr/src/uts/i86pc/ml/locore.s
@@ -23,7 +23,7 @@
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
@@ -1158,7 +1158,12 @@ cmntrap()
cmpl $T_ILLINST, REGOFF_TRAPNO(%rbp)
je 0f
- jne 4f /* if not PF, GP or UD, panic */
+ cmpl $T_ZERODIV, REGOFF_TRAPNO(%rbp)
+ jne 4f /* if not PF/GP/UD/DE, panic */
+
+ orw $CPU_DTRACE_DIVZERO, %cx
+ movw %cx, CPUC_DTRACE_FLAGS(%rax)
+ jmp 2f
/*
* If we've taken a GPF, we don't (unfortunately) have the address that
@@ -1249,14 +1254,22 @@ cmntrap()
.dtrace_induced:
cmpw $KCS_SEL, REGOFF_CS(%ebp) /* test CS for user-mode trap */
- jne 2f /* if from user, panic */
+ jne 3f /* if from user, panic */
cmpl $T_PGFLT, REGOFF_TRAPNO(%ebp)
- je 0f
+ je 1f
cmpl $T_GPFLT, REGOFF_TRAPNO(%ebp)
- jne 3f /* if not PF or GP, panic */
+ je 0f
+
+ cmpl $T_ZERODIV, REGOFF_TRAPNO(%ebp)
+ jne 4f /* if not PF/GP/UD/DE, panic */
+
+ orw $CPU_DTRACE_DIVZERO, %cx
+ movw %cx, CPUC_DTRACE_FLAGS(%eax)
+ jmp 2f
+0:
/*
* If we've taken a GPF, we don't (unfortunately) have the address that
* induced the fault. So instead of setting the fault to BADADDR,
@@ -1264,13 +1277,13 @@ cmntrap()
*/
orw $CPU_DTRACE_ILLOP, %cx
movw %cx, CPUC_DTRACE_FLAGS(%eax)
- jmp 1f
-0:
+ jmp 2f
+1:
orw $CPU_DTRACE_BADADDR, %cx
movw %cx, CPUC_DTRACE_FLAGS(%eax) /* set fault to bad addr */
movl %esi, CPUC_DTRACE_ILLVAL(%eax)
/* fault addr is illegal value */
-1:
+2:
pushl REGOFF_EIP(%ebp)
call dtrace_instr_size
addl $4, %esp
@@ -1280,10 +1293,10 @@ cmntrap()
INTR_POP_KERNEL
IRET
/*NOTREACHED*/
-2:
+3:
pushl $dtrace_badflags
call panic
-3:
+4:
pushl $dtrace_badtrap
call panic
SET_SIZE(cmntrap)