diff options
| author | Bryan Cantrill <bryan@joyent.com> | 2016-06-07 21:21:23 +0000 |
|---|---|---|
| committer | Robert Mustacchi <rm@joyent.com> | 2016-06-08 13:25:59 -0700 |
| commit | 82d2d142300e27cbe46f9fd3731e9d280b2c66e8 (patch) | |
| tree | 66d0292b6d2645f081ae04de6fa44a0f8994b5da /usr/src | |
| parent | f11ba53f80410731989b127bc0e36a178773e84a (diff) | |
| download | illumos-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.d | 38 | ||||
| -rw-r--r-- | usr/src/pkg/manifests/system-dtrace-tests.mf | 3 | ||||
| -rw-r--r-- | usr/src/uts/common/dtrace/dtrace.c | 8 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/ml/genassym.c | 1 | ||||
| -rw-r--r-- | usr/src/uts/i86pc/ml/locore.s | 33 |
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) |
