summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/exception.S36
-rw-r--r--sys/amd64/amd64/exception.s36
-rw-r--r--sys/amd64/amd64/locore.S11
-rw-r--r--sys/amd64/amd64/locore.s11
-rw-r--r--sys/amd64/amd64/machdep.c186
-rw-r--r--sys/amd64/amd64/trap.c72
-rw-r--r--sys/amd64/include/psl.h37
-rw-r--r--sys/amd64/include/trap.h21
-rw-r--r--sys/i386/i386/exception.s36
-rw-r--r--sys/i386/i386/locore.s11
-rw-r--r--sys/i386/i386/machdep.c186
-rw-r--r--sys/i386/i386/procfs_machdep.c59
-rw-r--r--sys/i386/i386/trap.c72
-rw-r--r--sys/i386/include/psl.h37
-rw-r--r--sys/i386/include/trap.h21
-rw-r--r--sys/kern/subr_trap.c72
-rw-r--r--sys/kern/sys_process.c8
17 files changed, 491 insertions, 421 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index e14934b..f6d6115 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.5 1994/09/28 03:37:49 bde Exp $
+ * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $
*/
#include "npx.h" /* NNPX */
@@ -158,43 +158,15 @@ IDTVEC(fpu)
#else /* NNPX > 0 */
pushl $0; TRAP(T_ARITHTRAP)
#endif /* NNPX > 0 */
- /* 17 - 31 reserved for future exp */
-IDTVEC(rsvd0)
- pushl $0; TRAP(17)
-IDTVEC(rsvd1)
- pushl $0; TRAP(18)
-IDTVEC(rsvd2)
- pushl $0; TRAP(19)
-IDTVEC(rsvd3)
- pushl $0; TRAP(20)
-IDTVEC(rsvd4)
- pushl $0; TRAP(21)
-IDTVEC(rsvd5)
- pushl $0; TRAP(22)
-IDTVEC(rsvd6)
- pushl $0; TRAP(23)
-IDTVEC(rsvd7)
- pushl $0; TRAP(24)
-IDTVEC(rsvd8)
- pushl $0; TRAP(25)
-IDTVEC(rsvd9)
- pushl $0; TRAP(26)
-IDTVEC(rsvd10)
- pushl $0; TRAP(27)
-IDTVEC(rsvd11)
- pushl $0; TRAP(28)
-IDTVEC(rsvd12)
- pushl $0; TRAP(29)
-IDTVEC(rsvd13)
- pushl $0; TRAP(30)
-IDTVEC(rsvd14)
- pushl $0; TRAP(31)
+IDTVEC(align)
+ TRAP(T_ALIGNFLT)
SUPERALIGN_TEXT
_alltraps:
pushal
pushl %ds
pushl %es
+alltraps_with_regs_pushed:
movl $KDSEL,%eax
movl %ax,%ds
movl %ax,%es
diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s
index e14934b..f6d6115 100644
--- a/sys/amd64/amd64/exception.s
+++ b/sys/amd64/amd64/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.5 1994/09/28 03:37:49 bde Exp $
+ * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $
*/
#include "npx.h" /* NNPX */
@@ -158,43 +158,15 @@ IDTVEC(fpu)
#else /* NNPX > 0 */
pushl $0; TRAP(T_ARITHTRAP)
#endif /* NNPX > 0 */
- /* 17 - 31 reserved for future exp */
-IDTVEC(rsvd0)
- pushl $0; TRAP(17)
-IDTVEC(rsvd1)
- pushl $0; TRAP(18)
-IDTVEC(rsvd2)
- pushl $0; TRAP(19)
-IDTVEC(rsvd3)
- pushl $0; TRAP(20)
-IDTVEC(rsvd4)
- pushl $0; TRAP(21)
-IDTVEC(rsvd5)
- pushl $0; TRAP(22)
-IDTVEC(rsvd6)
- pushl $0; TRAP(23)
-IDTVEC(rsvd7)
- pushl $0; TRAP(24)
-IDTVEC(rsvd8)
- pushl $0; TRAP(25)
-IDTVEC(rsvd9)
- pushl $0; TRAP(26)
-IDTVEC(rsvd10)
- pushl $0; TRAP(27)
-IDTVEC(rsvd11)
- pushl $0; TRAP(28)
-IDTVEC(rsvd12)
- pushl $0; TRAP(29)
-IDTVEC(rsvd13)
- pushl $0; TRAP(30)
-IDTVEC(rsvd14)
- pushl $0; TRAP(31)
+IDTVEC(align)
+ TRAP(T_ALIGNFLT)
SUPERALIGN_TEXT
_alltraps:
pushal
pushl %ds
pushl %es
+alltraps_with_regs_pushed:
movl $KDSEL,%eax
movl %ax,%ds
movl %ax,%es
diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S
index 7f32a04..e28f065 100644
--- a/sys/amd64/amd64/locore.S
+++ b/sys/amd64/amd64/locore.S
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.44 1994/11/06 22:18:45 phk Exp $
+ * $Id: locore.s,v 1.45 1994/11/18 05:27:34 phk Exp $
*/
/*
@@ -176,7 +176,7 @@ NON_GPROF_ENTRY(btext)
movl %esp, %ebp
/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_MBO
+ pushl $PSL_KERNEL
popfl
/* Don't trust what the BIOS gives for %fs and %gs. */
@@ -764,7 +764,7 @@ reloc_gdt:
pushl $0 /* unused */
pushl __udatasel /* ss */
pushl $0 /* esp - filled in by execve() */
- pushl $PSL_USERSET /* eflags (ring 0, int enab) */
+ pushl $PSL_USER /* eflags (IOPL 0, int enab) */
pushl __ucodesel /* cs */
pushl $0 /* eip - filled in by execve() */
subl $(12*4),%esp /* space for rest of registers */
@@ -776,13 +776,14 @@ reloc_gdt:
/*
* now we've run main() and determined what cpu-type we are, we can
- * enable WP mode on i486 cpus and above.
+ * enable write protection and alignment checking on i486 cpus and
+ * above.
*/
#if defined(I486_CPU) || defined(I586_CPU)
cmpl $CPUCLASS_386,_cpu_class
je 1f
movl %cr0,%eax /* get control word */
- orl $CR0_WP,%eax /* enable write protect for all modes */
+ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
movl %eax,%cr0 /* and do it */
#endif
/*
diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s
index 7f32a04..e28f065 100644
--- a/sys/amd64/amd64/locore.s
+++ b/sys/amd64/amd64/locore.s
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.44 1994/11/06 22:18:45 phk Exp $
+ * $Id: locore.s,v 1.45 1994/11/18 05:27:34 phk Exp $
*/
/*
@@ -176,7 +176,7 @@ NON_GPROF_ENTRY(btext)
movl %esp, %ebp
/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_MBO
+ pushl $PSL_KERNEL
popfl
/* Don't trust what the BIOS gives for %fs and %gs. */
@@ -764,7 +764,7 @@ reloc_gdt:
pushl $0 /* unused */
pushl __udatasel /* ss */
pushl $0 /* esp - filled in by execve() */
- pushl $PSL_USERSET /* eflags (ring 0, int enab) */
+ pushl $PSL_USER /* eflags (IOPL 0, int enab) */
pushl __ucodesel /* cs */
pushl $0 /* eip - filled in by execve() */
subl $(12*4),%esp /* space for rest of registers */
@@ -776,13 +776,14 @@ reloc_gdt:
/*
* now we've run main() and determined what cpu-type we are, we can
- * enable WP mode on i486 cpus and above.
+ * enable write protection and alignment checking on i486 cpus and
+ * above.
*/
#if defined(I486_CPU) || defined(I586_CPU)
cmpl $CPUCLASS_386,_cpu_class
je 1f
movl %cr0,%eax /* get control word */
- orl $CR0_WP,%eax /* enable write protect for all modes */
+ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
movl %eax,%cr0 /* and do it */
#endif
/*
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index eeba17b..7b59d96 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.99 1995/01/05 19:51:14 se Exp $
+ * $Id: machdep.c,v 1.100 1995/01/09 16:04:37 davidg Exp $
*/
#include "npx.h"
@@ -459,7 +459,7 @@ vmtime(otime, olbolt, oicr)
}
#endif
-extern int kstack[];
+extern char kstack[];
/*
* Send an interrupt to process.
@@ -607,48 +607,34 @@ sigreturn(p, uap, retval)
if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
return(EINVAL);
+ /*
+ * Don't allow users to change privileged or reserved flags. Let
+ * the hardware check for changing to excess I/O privilege.
+ */
+#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+
eflags = scp->sc_ps;
- if ((eflags & PSL_USERCLR) != 0 ||
- (eflags & PSL_USERSET) != PSL_USERSET ||
- (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) {
+ if (!EFLAGS_SECURE(eflags, regs[tEFLAGS])) {
#ifdef DEBUG
- printf("sigreturn: eflags=0x%x\n", eflags);
+ printf("sigreturn: eflags = 0x%x\n", eflags);
#endif
return(EINVAL);
}
/*
- * Sanity check the user's selectors and error if they
- * are suspect.
+ * Don't allow users to load a valid privileged %cs. Let the
+ * hardware check for invalid selectors, excess privilege in
+ * other selectors, invalid %eip's and invalid %esp's.
*/
-#define max_ldt_sel(pcb) \
- ((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
-
-#define valid_ldt_sel(sel) \
- (ISLDT(sel) && ISPL(sel) == SEL_UPL && \
- IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
-
-#define null_sel(sel) \
- (!ISLDT(sel) && IDXSEL(sel) == 0)
-
- if (((scp->sc_cs&0xffff) != _ucodesel && !valid_ldt_sel(scp->sc_cs)) ||
- ((scp->sc_ss&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ss)) ||
- ((scp->sc_ds&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ds) &&
- !null_sel(scp->sc_ds)) ||
- ((scp->sc_es&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_es) &&
- !null_sel(scp->sc_es))) {
+#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
+ if (!CS_SECURE(scp->sc_cs)) {
#ifdef DEBUG
- printf("sigreturn: cs=0x%x ss=0x%x ds=0x%x es=0x%x\n",
- scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es);
+ printf("sigreturn: cs = 0x%x\n", scp->sc_cs);
#endif
trapsignal(p, SIGBUS, T_PROTFLT);
return(EINVAL);
}
-#undef max_ldt_sel
-#undef valid_ldt_sel
-#undef null_sel
-
/* restore scratch registers */
regs[tEAX] = scp->sc_eax;
regs[tEBX] = scp->sc_ebx;
@@ -863,7 +849,7 @@ setregs(p, entry, stack)
bzero(regs, sizeof(struct trapframe));
regs[tEIP] = entry;
regs[tESP] = stack;
- regs[tEFLAGS] = PSL_USERSET | (regs[tEFLAGS] & PSL_T);
+ regs[tEFLAGS] = PSL_USER | (regs[tEFLAGS] & PSL_T);
regs[tSS] = _udatasel;
regs[tDS] = _udatasel;
regs[tES] = _udatasel;
@@ -1106,11 +1092,8 @@ extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
- IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
- IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
- IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
- IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
- IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
+ IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
+ IDTVEC(syscall);
void
sdtossd(sd, ssd)
@@ -1191,6 +1174,8 @@ init386(first)
ssdtosd(&ldt_segs[x], &ldt[x].sd);
/* exceptions */
+ for (x = 0; x < NIDT; x++)
+ setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
@@ -1208,21 +1193,7 @@ init386(first)
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
- setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL);
- setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
- setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
- setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
- setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
- setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
- setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
- setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
- setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
- setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
- setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
- setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
- setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
- setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
- setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
+ setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
#include "isa.h"
#if NISA >0
@@ -1445,60 +1416,95 @@ test_page(address, pattern)
* index into the user block. Don't you just *love* virtual memory?
* (I'm starting to think seymour is right...)
*/
+#define TF_REGP(p) ((struct trapframe *) \
+ ((char *)(p)->p_addr \
+ + ((char *)(p)->p_md.md_regs - kstack)))
int
-ptrace_set_pc (struct proc *p, unsigned int addr) {
- void *regs = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
-
- ((struct trapframe *)regs)->tf_eip = addr;
- return 0;
+ptrace_set_pc(p, addr)
+ struct proc *p;
+ unsigned int addr;
+{
+ TF_REGP(p)->tf_eip = addr;
+ return (0);
}
int
-ptrace_single_step (struct proc *p) {
- void *regs = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
-
- ((struct trapframe *)regs)->tf_eflags |= PSL_T;
- return 0;
+ptrace_single_step(p)
+ struct proc *p;
+{
+ TF_REGP(p)->tf_eflags |= PSL_T;
+ return (0);
}
-/*
- * Copy the registers to user-space.
- */
-
int
-ptrace_getregs (struct proc *p, unsigned int *addr) {
+ptrace_getregs(p, addr)
+ struct proc *p;
+ unsigned int *addr;
+{
int error;
- struct reg regs = {0};
+ struct reg regs;
- error = fill_regs (p, &regs);
+ error = fill_regs(p, &regs);
if (error)
- return error;
-
- return copyout (&regs, addr, sizeof (regs));
+ return (error);
+ return (copyout(&regs, addr, sizeof regs));
}
int
-ptrace_setregs (struct proc *p, unsigned int *addr) {
+ptrace_setregs(p, addr)
+ struct proc *p;
+ unsigned int *addr;
+{
int error;
- struct reg regs = {0};
+ struct reg regs;
- error = copyin (addr, &regs, sizeof(regs));
+ error = copyin(addr, &regs, sizeof regs);
if (error)
- return error;
+ return (error);
+ return (set_regs(p, &regs));
+}
+
+int ptrace_write_u(p, off, data)
+ struct proc *p;
+ vm_offset_t off;
+ int data;
+{
+ struct trapframe frame_copy;
+ vm_offset_t min;
+ struct trapframe *tp;
- return set_regs (p, &regs);
+ /*
+ * Privileged kernel state is scattered all over the user area.
+ * Only allow write access to parts of regs and to fpregs.
+ */
+ min = (char *)p->p_md.md_regs - kstack;
+ if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) {
+ tp = TF_REGP(p);
+ frame_copy = *tp;
+ *(int *)((char *)&frame_copy + (off - min)) = data;
+ if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
+ !CS_SECURE(frame_copy.tf_cs))
+ return (EINVAL);
+ *(int*)((char *)p->p_addr + off) = data;
+ return (0);
+ }
+ min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu);
+ if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) {
+ *(int*)((char *)p->p_addr + off) = data;
+ return (0);
+ }
+ return (EFAULT);
}
int
-fill_regs(struct proc *p, struct reg *regs) {
+fill_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
struct trapframe *tp;
- void *ptr = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
- tp = ptr;
+ tp = TF_REGP(p);
regs->r_es = tp->tf_es;
regs->r_ds = tp->tf_ds;
regs->r_edi = tp->tf_edi;
@@ -1513,16 +1519,20 @@ fill_regs(struct proc *p, struct reg *regs) {
regs->r_eflags = tp->tf_eflags;
regs->r_esp = tp->tf_esp;
regs->r_ss = tp->tf_ss;
- return 0;
+ return (0);
}
int
-set_regs (struct proc *p, struct reg *regs) {
+set_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
struct trapframe *tp;
- void *ptr = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
- tp = ptr;
+ tp = TF_REGP(p);
+ if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) ||
+ !CS_SECURE(regs->r_cs))
+ return (EINVAL);
tp->tf_es = regs->r_es;
tp->tf_ds = regs->r_ds;
tp->tf_edi = regs->r_edi;
@@ -1537,7 +1547,7 @@ set_regs (struct proc *p, struct reg *regs) {
tp->tf_eflags = regs->r_eflags;
tp->tf_esp = regs->r_esp;
tp->tf_ss = regs->r_ss;
- return 0;
+ return (0);
}
#ifndef DDB
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 0b4946f..57d586a 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.42 1994/12/24 07:22:58 bde Exp $
+ * $Id: trap.c,v 1.43 1995/01/09 16:04:39 davidg Exp $
*/
/*
@@ -73,24 +73,24 @@ void trap_fatal __P((struct trapframe *));
#define MAX_TRAP_MSG 27
char *trap_msg[] = {
- "reserved addressing fault", /* 0 T_RESADFLT */
+ "", /* 0 unused */
"privileged instruction fault", /* 1 T_PRIVINFLT */
- "reserved operand fault", /* 2 T_RESOPFLT */
+ "", /* 2 unused */
"breakpoint instruction fault", /* 3 T_BPTFLT */
"", /* 4 unused */
- "system call trap", /* 5 T_SYSCALL */
+ "", /* 5 unused */
"arithmetic trap", /* 6 T_ARITHTRAP */
"system forced exception", /* 7 T_ASTFLT */
- "segmentation (limit) fault", /* 8 T_SEGFLT */
+ "", /* 8 unused */
"general protection fault", /* 9 T_PROTFLT */
"trace trap", /* 10 T_TRCTRAP */
"", /* 11 unused */
"page fault", /* 12 T_PAGEFLT */
- "page table fault", /* 13 T_TABLEFLT */
+ "", /* 13 unused */
"alignment fault", /* 14 T_ALIGNFLT */
- "kernel stack pointer not valid", /* 15 T_KSPNOTVAL */
- "bus error", /* 16 T_BUSERR */
- "kernel debugger fault", /* 17 T_KDBTRAP */
+ "", /* 15 unused */
+ "", /* 16 unused */
+ "", /* 17 unused */
"integer divide fault", /* 18 T_DIVIDE */
"non-maskable interrupt trap", /* 19 T_NMI */
"overflow trap", /* 20 T_OFLOW */
@@ -167,7 +167,6 @@ trap(frame)
u_long eva;
#endif
- frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
type = frame.tf_trapno;
code = frame.tf_err;
@@ -178,9 +177,7 @@ trap(frame)
p->p_md.md_regs = (int *)&frame;
switch (type) {
- case T_RESADFLT: /* reserved addressing fault */
case T_PRIVINFLT: /* privileged instruction fault */
- case T_RESOPFLT: /* reserved operand fault */
ucode = type;
i = SIGILL;
break;
@@ -208,6 +205,9 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
case T_STKFLT: /* stack fault */
+ case T_TSSFLT: /* invalid TSS fault */
+ case T_DOUBLEFLT: /* double fault */
+ default:
ucode = code + BUS_SEGM_FAULT ;
i = SIGBUS;
break;
@@ -276,10 +276,6 @@ trap(frame)
ucode = T_FPOPFLT;
i = SIGILL;
break;
-
- default:
- trap_fatal(&frame);
- return;
}
} else {
/* kernel trap */
@@ -291,12 +287,56 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
+ /*
+ * Invalid segment selectors and out of bounds
+ * %eip's and %esp's can be set up in user mode.
+ * This causes a fault in kernel mode when the
+ * kernel tries to return to user mode. We want
+ * to get this fault so that we can fix the
+ * problem here and not have to check all the
+ * selectors and pointers when the user changes
+ * them.
+ */
+#define MAYBE_DORETI_FAULT(where, whereto) \
+ do { \
+ extern void where(void) __asm(__STRING(where)); \
+ extern void whereto(void) __asm(__STRING(whereto)); \
+ if (frame.tf_eip == (int)where) { \
+ frame.tf_eip = (int)whereto; \
+ return; \
+ } \
+ } while (0)
+
+ if (intr_nesting_level == 0) {
+ MAYBE_DORETI_FAULT(doreti_iret,
+ doreti_iret_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_ds,
+ doreti_popl_ds_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_es,
+ doreti_popl_es_fault);
+ }
if (curpcb && curpcb->pcb_onfault) {
frame.tf_eip = (int)curpcb->pcb_onfault;
return;
}
break;
+ case T_TSSFLT:
+ /*
+ * PSL_NT can be set in user mode and isn't cleared
+ * automatically when the kernel is entered. This
+ * causes a TSS fault when the kernel attempts to
+ * `iret' because the TSS link is uninitialized. We
+ * want to get this fault so that we can fix the
+ * problem here and not every time the kernel is
+ * entered.
+ */
+ if (frame.tf_eflags & PSL_NT) {
+ frame.tf_eflags &= ~PSL_NT;
+ return;
+ }
+ break;
+
#ifdef DDB
case T_BPTFLT:
case T_TRCTRAP:
diff --git a/sys/amd64/include/psl.h b/sys/amd64/include/psl.h
index 906acd4..3d96dbc 100644
--- a/sys/amd64/include/psl.h
+++ b/sys/amd64/include/psl.h
@@ -34,11 +34,11 @@
* SUCH DAMAGE.
*
* from: @(#)psl.h 5.2 (Berkeley) 1/18/91
- * $Id: psl.h,v 1.4 1994/02/24 00:21:12 hsu Exp $
+ * $Id: psl.h,v 1.5 1994/08/10 03:51:18 wollman Exp $
*/
#ifndef _MACHINE_PSL_H_
-#define _MACHINE_PSL_H_ 1
+#define _MACHINE_PSL_H_
/*
* 386 processor status longword.
@@ -52,18 +52,37 @@
#define PSL_I 0x00000200 /* interrupt enable bit */
#define PSL_D 0x00000400 /* string instruction direction bit */
#define PSL_V 0x00000800 /* overflow bit */
-#define PSL_IOPL 0x00003000 /* i/o priviledge level enable */
+#define PSL_IOPL 0x00003000 /* i/o privilege level */
#define PSL_NT 0x00004000 /* nested task bit */
-#define PSL_RF 0x00010000 /* restart flag bit */
+#define PSL_RF 0x00010000 /* resume flag bit */
#define PSL_VM 0x00020000 /* virtual 8086 mode bit */
#define PSL_AC 0x00040000 /* alignment checking */
#define PSL_VIF 0x00080000 /* virtual interrupt enable */
#define PSL_VIP 0x00100000 /* virtual interrupt pending */
#define PSL_ID 0x00200000 /* identification bit */
-#define PSL_MBZ 0xffc08028 /* must be zero bits */
-#define PSL_MBO 0x00000002 /* must be one bits */
+/*
+ * The i486 manual says that we are not supposed to change reserved flags,
+ * but this is too much trouble since the reserved flags depend on the cpu
+ * and setting them to their historical values works in practice.
+ */
+#define PSL_RESERVED_DEFAULT 0x00000002
+
+/*
+ * Initial flags for kernel and user mode. The kernel later inherits
+ * PSL_I and some other flags from user mode.
+ */
+#define PSL_KERNEL PSL_RESERVED_DEFAULT
+#define PSL_USER (PSL_RESERVED_DEFAULT | PSL_I)
+
+/*
+ * Bits that can be changed in user mode on 486's. We allow these bits
+ * to be changed using ptrace(), sigreturn() and procfs. Setting PS_NT
+ * is undesireable but it may as well be allowed since users can inflict
+ * it on the kernel directly. Changes to PSL_AC are silently ignored on
+ * 386's.
+ */
+#define PSL_USERCHANGE (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_T \
+ | PSL_D | PSL_V | PSL_NT | PSL_AC)
-#define PSL_USERSET (PSL_MBO | PSL_I)
-#define PSL_USERCLR (PSL_MBZ | PSL_NT)
-#endif /* _MACHINE_PSL_H_ */
+#endif /* !_MACHINE_PSL_H_ */
diff --git a/sys/amd64/include/trap.h b/sys/amd64/include/trap.h
index aa832ff..e1ead77 100644
--- a/sys/amd64/include/trap.h
+++ b/sys/amd64/include/trap.h
@@ -34,33 +34,25 @@
* SUCH DAMAGE.
*
* from: @(#)trap.h 5.4 (Berkeley) 5/9/91
- * $Id: trap.h,v 1.2 1993/10/16 14:39:37 rgrimes Exp $
+ * $Id: trap.h,v 1.3 1993/11/07 17:43:15 wollman Exp $
*/
#ifndef _MACHINE_TRAP_H_
-#define _MACHINE_TRAP_H_ 1
+#define _MACHINE_TRAP_H_
/*
* Trap type values
* also known in trap.c for name strings
*/
-#define T_RESADFLT 0 /* reserved addressing */
#define T_PRIVINFLT 1 /* privileged instruction */
-#define T_RESOPFLT 2 /* reserved operand */
#define T_BPTFLT 3 /* breakpoint instruction */
-#define T_SYSCALL 5 /* system call (kcall) */
#define T_ARITHTRAP 6 /* arithmetic trap */
#define T_ASTFLT 7 /* system forced exception */
-#define T_SEGFLT 8 /* segmentation (limit) fault */
#define T_PROTFLT 9 /* protection fault */
-#define T_TRCTRAP 10 /* trace trap */
+#define T_TRCTRAP 10 /* debug exception (sic) */
#define T_PAGEFLT 12 /* page fault */
-#define T_TABLEFLT 13 /* page table fault */
#define T_ALIGNFLT 14 /* alignment fault */
-#define T_KSPNOTVAL 15 /* kernel stack pointer not valid */
-#define T_BUSERR 16 /* bus error */
-#define T_KDBTRAP 17 /* kernel debugger trap */
#define T_DIVIDE 18 /* integer divide fault */
#define T_NMI 19 /* non-maskable trap */
@@ -72,7 +64,9 @@
#define T_TSSFLT 25 /* invalid tss fault */
#define T_SEGNPFLT 26 /* segment not present fault */
#define T_STKFLT 27 /* stack fault */
-#define T_RESERVED 28 /* reserved fault base */
+#define T_RESERVED 28 /* reserved (unknown) */
+
+/* XXX most of the following codes aren't used, but could be. */
/* definitions for <sys/signal.h> */
#define ILL_RESAD_FAULT T_RESADFLT
@@ -98,4 +92,5 @@
/* Trap's coming from user mode */
#define T_USER 0x100
-#endif /* _MACHINE_TRAP_H_ */
+
+#endif /* !_MACHINE_TRAP_H_ */
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index e14934b..f6d6115 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exception.s,v 1.5 1994/09/28 03:37:49 bde Exp $
+ * $Id: exception.s,v 1.6 1994/12/03 10:02:19 bde Exp $
*/
#include "npx.h" /* NNPX */
@@ -158,43 +158,15 @@ IDTVEC(fpu)
#else /* NNPX > 0 */
pushl $0; TRAP(T_ARITHTRAP)
#endif /* NNPX > 0 */
- /* 17 - 31 reserved for future exp */
-IDTVEC(rsvd0)
- pushl $0; TRAP(17)
-IDTVEC(rsvd1)
- pushl $0; TRAP(18)
-IDTVEC(rsvd2)
- pushl $0; TRAP(19)
-IDTVEC(rsvd3)
- pushl $0; TRAP(20)
-IDTVEC(rsvd4)
- pushl $0; TRAP(21)
-IDTVEC(rsvd5)
- pushl $0; TRAP(22)
-IDTVEC(rsvd6)
- pushl $0; TRAP(23)
-IDTVEC(rsvd7)
- pushl $0; TRAP(24)
-IDTVEC(rsvd8)
- pushl $0; TRAP(25)
-IDTVEC(rsvd9)
- pushl $0; TRAP(26)
-IDTVEC(rsvd10)
- pushl $0; TRAP(27)
-IDTVEC(rsvd11)
- pushl $0; TRAP(28)
-IDTVEC(rsvd12)
- pushl $0; TRAP(29)
-IDTVEC(rsvd13)
- pushl $0; TRAP(30)
-IDTVEC(rsvd14)
- pushl $0; TRAP(31)
+IDTVEC(align)
+ TRAP(T_ALIGNFLT)
SUPERALIGN_TEXT
_alltraps:
pushal
pushl %ds
pushl %es
+alltraps_with_regs_pushed:
movl $KDSEL,%eax
movl %ax,%ds
movl %ax,%es
diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
index 7f32a04..e28f065 100644
--- a/sys/i386/i386/locore.s
+++ b/sys/i386/i386/locore.s
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.44 1994/11/06 22:18:45 phk Exp $
+ * $Id: locore.s,v 1.45 1994/11/18 05:27:34 phk Exp $
*/
/*
@@ -176,7 +176,7 @@ NON_GPROF_ENTRY(btext)
movl %esp, %ebp
/* Don't trust what the BIOS gives for eflags. */
- pushl $PSL_MBO
+ pushl $PSL_KERNEL
popfl
/* Don't trust what the BIOS gives for %fs and %gs. */
@@ -764,7 +764,7 @@ reloc_gdt:
pushl $0 /* unused */
pushl __udatasel /* ss */
pushl $0 /* esp - filled in by execve() */
- pushl $PSL_USERSET /* eflags (ring 0, int enab) */
+ pushl $PSL_USER /* eflags (IOPL 0, int enab) */
pushl __ucodesel /* cs */
pushl $0 /* eip - filled in by execve() */
subl $(12*4),%esp /* space for rest of registers */
@@ -776,13 +776,14 @@ reloc_gdt:
/*
* now we've run main() and determined what cpu-type we are, we can
- * enable WP mode on i486 cpus and above.
+ * enable write protection and alignment checking on i486 cpus and
+ * above.
*/
#if defined(I486_CPU) || defined(I586_CPU)
cmpl $CPUCLASS_386,_cpu_class
je 1f
movl %cr0,%eax /* get control word */
- orl $CR0_WP,%eax /* enable write protect for all modes */
+ orl $CR0_WP|CR0_AM,%eax /* enable i486 features */
movl %eax,%cr0 /* and do it */
#endif
/*
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index eeba17b..7b59d96 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.99 1995/01/05 19:51:14 se Exp $
+ * $Id: machdep.c,v 1.100 1995/01/09 16:04:37 davidg Exp $
*/
#include "npx.h"
@@ -459,7 +459,7 @@ vmtime(otime, olbolt, oicr)
}
#endif
-extern int kstack[];
+extern char kstack[];
/*
* Send an interrupt to process.
@@ -607,48 +607,34 @@ sigreturn(p, uap, retval)
if (useracc((caddr_t)fp, sizeof (*fp), 0) == 0)
return(EINVAL);
+ /*
+ * Don't allow users to change privileged or reserved flags. Let
+ * the hardware check for changing to excess I/O privilege.
+ */
+#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+
eflags = scp->sc_ps;
- if ((eflags & PSL_USERCLR) != 0 ||
- (eflags & PSL_USERSET) != PSL_USERSET ||
- (eflags & PSL_IOPL) < (regs[tEFLAGS] & PSL_IOPL)) {
+ if (!EFLAGS_SECURE(eflags, regs[tEFLAGS])) {
#ifdef DEBUG
- printf("sigreturn: eflags=0x%x\n", eflags);
+ printf("sigreturn: eflags = 0x%x\n", eflags);
#endif
return(EINVAL);
}
/*
- * Sanity check the user's selectors and error if they
- * are suspect.
+ * Don't allow users to load a valid privileged %cs. Let the
+ * hardware check for invalid selectors, excess privilege in
+ * other selectors, invalid %eip's and invalid %esp's.
*/
-#define max_ldt_sel(pcb) \
- ((pcb)->pcb_ldt ? (pcb)->pcb_ldt_len : (sizeof(ldt) / sizeof(ldt[0])))
-
-#define valid_ldt_sel(sel) \
- (ISLDT(sel) && ISPL(sel) == SEL_UPL && \
- IDXSEL(sel) < max_ldt_sel(&p->p_addr->u_pcb))
-
-#define null_sel(sel) \
- (!ISLDT(sel) && IDXSEL(sel) == 0)
-
- if (((scp->sc_cs&0xffff) != _ucodesel && !valid_ldt_sel(scp->sc_cs)) ||
- ((scp->sc_ss&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ss)) ||
- ((scp->sc_ds&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_ds) &&
- !null_sel(scp->sc_ds)) ||
- ((scp->sc_es&0xffff) != _udatasel && !valid_ldt_sel(scp->sc_es) &&
- !null_sel(scp->sc_es))) {
+#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
+ if (!CS_SECURE(scp->sc_cs)) {
#ifdef DEBUG
- printf("sigreturn: cs=0x%x ss=0x%x ds=0x%x es=0x%x\n",
- scp->sc_cs, scp->sc_ss, scp->sc_ds, scp->sc_es);
+ printf("sigreturn: cs = 0x%x\n", scp->sc_cs);
#endif
trapsignal(p, SIGBUS, T_PROTFLT);
return(EINVAL);
}
-#undef max_ldt_sel
-#undef valid_ldt_sel
-#undef null_sel
-
/* restore scratch registers */
regs[tEAX] = scp->sc_eax;
regs[tEBX] = scp->sc_ebx;
@@ -863,7 +849,7 @@ setregs(p, entry, stack)
bzero(regs, sizeof(struct trapframe));
regs[tEIP] = entry;
regs[tESP] = stack;
- regs[tEFLAGS] = PSL_USERSET | (regs[tEFLAGS] & PSL_T);
+ regs[tEFLAGS] = PSL_USER | (regs[tEFLAGS] & PSL_T);
regs[tSS] = _udatasel;
regs[tDS] = _udatasel;
regs[tES] = _udatasel;
@@ -1106,11 +1092,8 @@ extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(dble), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
- IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(rsvd0),
- IDTVEC(rsvd1), IDTVEC(rsvd2), IDTVEC(rsvd3), IDTVEC(rsvd4),
- IDTVEC(rsvd5), IDTVEC(rsvd6), IDTVEC(rsvd7), IDTVEC(rsvd8),
- IDTVEC(rsvd9), IDTVEC(rsvd10), IDTVEC(rsvd11), IDTVEC(rsvd12),
- IDTVEC(rsvd13), IDTVEC(rsvd14), IDTVEC(syscall);
+ IDTVEC(page), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
+ IDTVEC(syscall);
void
sdtossd(sd, ssd)
@@ -1191,6 +1174,8 @@ init386(first)
ssdtosd(&ldt_segs[x], &ldt[x].sd);
/* exceptions */
+ for (x = 0; x < NIDT; x++)
+ setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL);
setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL);
setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL);
@@ -1208,21 +1193,7 @@ init386(first)
setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL);
setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL);
setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL);
- setidt(17, &IDTVEC(rsvd0), SDT_SYS386TGT, SEL_KPL);
- setidt(18, &IDTVEC(rsvd1), SDT_SYS386TGT, SEL_KPL);
- setidt(19, &IDTVEC(rsvd2), SDT_SYS386TGT, SEL_KPL);
- setidt(20, &IDTVEC(rsvd3), SDT_SYS386TGT, SEL_KPL);
- setidt(21, &IDTVEC(rsvd4), SDT_SYS386TGT, SEL_KPL);
- setidt(22, &IDTVEC(rsvd5), SDT_SYS386TGT, SEL_KPL);
- setidt(23, &IDTVEC(rsvd6), SDT_SYS386TGT, SEL_KPL);
- setidt(24, &IDTVEC(rsvd7), SDT_SYS386TGT, SEL_KPL);
- setidt(25, &IDTVEC(rsvd8), SDT_SYS386TGT, SEL_KPL);
- setidt(26, &IDTVEC(rsvd9), SDT_SYS386TGT, SEL_KPL);
- setidt(27, &IDTVEC(rsvd10), SDT_SYS386TGT, SEL_KPL);
- setidt(28, &IDTVEC(rsvd11), SDT_SYS386TGT, SEL_KPL);
- setidt(29, &IDTVEC(rsvd12), SDT_SYS386TGT, SEL_KPL);
- setidt(30, &IDTVEC(rsvd13), SDT_SYS386TGT, SEL_KPL);
- setidt(31, &IDTVEC(rsvd14), SDT_SYS386TGT, SEL_KPL);
+ setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL);
#include "isa.h"
#if NISA >0
@@ -1445,60 +1416,95 @@ test_page(address, pattern)
* index into the user block. Don't you just *love* virtual memory?
* (I'm starting to think seymour is right...)
*/
+#define TF_REGP(p) ((struct trapframe *) \
+ ((char *)(p)->p_addr \
+ + ((char *)(p)->p_md.md_regs - kstack)))
int
-ptrace_set_pc (struct proc *p, unsigned int addr) {
- void *regs = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
-
- ((struct trapframe *)regs)->tf_eip = addr;
- return 0;
+ptrace_set_pc(p, addr)
+ struct proc *p;
+ unsigned int addr;
+{
+ TF_REGP(p)->tf_eip = addr;
+ return (0);
}
int
-ptrace_single_step (struct proc *p) {
- void *regs = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
-
- ((struct trapframe *)regs)->tf_eflags |= PSL_T;
- return 0;
+ptrace_single_step(p)
+ struct proc *p;
+{
+ TF_REGP(p)->tf_eflags |= PSL_T;
+ return (0);
}
-/*
- * Copy the registers to user-space.
- */
-
int
-ptrace_getregs (struct proc *p, unsigned int *addr) {
+ptrace_getregs(p, addr)
+ struct proc *p;
+ unsigned int *addr;
+{
int error;
- struct reg regs = {0};
+ struct reg regs;
- error = fill_regs (p, &regs);
+ error = fill_regs(p, &regs);
if (error)
- return error;
-
- return copyout (&regs, addr, sizeof (regs));
+ return (error);
+ return (copyout(&regs, addr, sizeof regs));
}
int
-ptrace_setregs (struct proc *p, unsigned int *addr) {
+ptrace_setregs(p, addr)
+ struct proc *p;
+ unsigned int *addr;
+{
int error;
- struct reg regs = {0};
+ struct reg regs;
- error = copyin (addr, &regs, sizeof(regs));
+ error = copyin(addr, &regs, sizeof regs);
if (error)
- return error;
+ return (error);
+ return (set_regs(p, &regs));
+}
+
+int ptrace_write_u(p, off, data)
+ struct proc *p;
+ vm_offset_t off;
+ int data;
+{
+ struct trapframe frame_copy;
+ vm_offset_t min;
+ struct trapframe *tp;
- return set_regs (p, &regs);
+ /*
+ * Privileged kernel state is scattered all over the user area.
+ * Only allow write access to parts of regs and to fpregs.
+ */
+ min = (char *)p->p_md.md_regs - kstack;
+ if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) {
+ tp = TF_REGP(p);
+ frame_copy = *tp;
+ *(int *)((char *)&frame_copy + (off - min)) = data;
+ if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) ||
+ !CS_SECURE(frame_copy.tf_cs))
+ return (EINVAL);
+ *(int*)((char *)p->p_addr + off) = data;
+ return (0);
+ }
+ min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu);
+ if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) {
+ *(int*)((char *)p->p_addr + off) = data;
+ return (0);
+ }
+ return (EFAULT);
}
int
-fill_regs(struct proc *p, struct reg *regs) {
+fill_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
struct trapframe *tp;
- void *ptr = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
- tp = ptr;
+ tp = TF_REGP(p);
regs->r_es = tp->tf_es;
regs->r_ds = tp->tf_ds;
regs->r_edi = tp->tf_edi;
@@ -1513,16 +1519,20 @@ fill_regs(struct proc *p, struct reg *regs) {
regs->r_eflags = tp->tf_eflags;
regs->r_esp = tp->tf_esp;
regs->r_ss = tp->tf_ss;
- return 0;
+ return (0);
}
int
-set_regs (struct proc *p, struct reg *regs) {
+set_regs(p, regs)
+ struct proc *p;
+ struct reg *regs;
+{
struct trapframe *tp;
- void *ptr = (char*)p->p_addr +
- ((char*) p->p_md.md_regs - (char*) kstack);
- tp = ptr;
+ tp = TF_REGP(p);
+ if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) ||
+ !CS_SECURE(regs->r_cs))
+ return (EINVAL);
tp->tf_es = regs->r_es;
tp->tf_ds = regs->r_ds;
tp->tf_edi = regs->r_edi;
@@ -1537,7 +1547,7 @@ set_regs (struct proc *p, struct reg *regs) {
tp->tf_eflags = regs->r_eflags;
tp->tf_esp = regs->r_esp;
tp->tf_ss = regs->r_ss;
- return 0;
+ return (0);
}
#ifndef DDB
diff --git a/sys/i386/i386/procfs_machdep.c b/sys/i386/i386/procfs_machdep.c
index d122fc6..b22eef5 100644
--- a/sys/i386/i386/procfs_machdep.c
+++ b/sys/i386/i386/procfs_machdep.c
@@ -37,7 +37,7 @@
* @(#)procfs_machdep.c 8.3 (Berkeley) 1/27/94
*
* From:
- * $Id: procfs_i386.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
+ * $Id: procfs_machdep.c,v 1.2 1994/05/25 08:54:48 rgrimes Exp $
*/
/*
@@ -52,6 +52,8 @@
* Update the current register set from the passed in regs
* structure. Take care to avoid clobbering special CPU
* registers or privileged bits in the PSL.
+ * Depending on the architecture this may have fix-up work to do,
+ * especially if the IAR or PCW are modified.
* The process is stopped at the time write_regs is called.
*
* procfs_read_fpregs, procfs_write_fpregs
@@ -76,51 +78,42 @@
#include <machine/frame.h>
#include <miscfs/procfs/procfs.h>
+extern char kstack[]; /* XXX */
+
int
procfs_read_regs(p, regs)
struct proc *p;
struct reg *regs;
{
- struct trapframe *f;
-
if ((p->p_flag & P_INMEM) == 0)
return (EIO);
-
- f = (struct trapframe *) p->p_md.md_regs;
- bcopy((void *) f, (void *) regs, sizeof(*regs));
-
- return (0);
+ return (fill_regs(p, regs));
}
-/*
- * Update the process's current register
- * set. Depending on the architecture this
- * may have fix-up work to do, especially
- * if the IAR or PCW are modified.
- */
int
procfs_write_regs(p, regs)
struct proc *p;
struct reg *regs;
{
- struct trapframe *f;
-
if ((p->p_flag & P_INMEM) == 0)
return (EIO);
-
- f = (struct trapframe *) p->p_md.md_regs;
- bcopy((void *) regs, (void *) f, sizeof(*regs));
-
- return (0);
+ return (set_regs(p, regs));
}
+/*
+ * Ptrace doesn't support fpregs at all, and there are no security holes
+ * or translations for fpregs, so we can just copy them.
+ */
+
int
procfs_read_fpregs(p, fpregs)
struct proc *p;
struct fpreg *fpregs;
{
-
- return (EOPNOTSUPP);
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+ bcopy(&p->p_addr->u_pcb.pcb_savefpu, fpregs, sizeof *fpregs);
+ return (0);
}
int
@@ -128,25 +121,19 @@ procfs_write_fpregs(p, fpregs)
struct proc *p;
struct fpreg *fpregs;
{
-
- return (EOPNOTSUPP);
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+ bcopy(fpregs, &p->p_addr->u_pcb.pcb_savefpu, sizeof *fpregs);
+ return (0);
}
-
int
procfs_sstep(p)
struct proc *p;
{
- int error;
- struct reg r;
-
- error = procfs_read_regs(p, &r);
- if (error == 0) {
- r.r_eflags |= PSL_T;
- error = procfs_write_regs(p, &r);
- }
-
- return (error);
+ if ((p->p_flag & P_INMEM) == 0)
+ return (EIO);
+ return (ptrace_single_step(p));
}
void
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 0b4946f..57d586a 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.42 1994/12/24 07:22:58 bde Exp $
+ * $Id: trap.c,v 1.43 1995/01/09 16:04:39 davidg Exp $
*/
/*
@@ -73,24 +73,24 @@ void trap_fatal __P((struct trapframe *));
#define MAX_TRAP_MSG 27
char *trap_msg[] = {
- "reserved addressing fault", /* 0 T_RESADFLT */
+ "", /* 0 unused */
"privileged instruction fault", /* 1 T_PRIVINFLT */
- "reserved operand fault", /* 2 T_RESOPFLT */
+ "", /* 2 unused */
"breakpoint instruction fault", /* 3 T_BPTFLT */
"", /* 4 unused */
- "system call trap", /* 5 T_SYSCALL */
+ "", /* 5 unused */
"arithmetic trap", /* 6 T_ARITHTRAP */
"system forced exception", /* 7 T_ASTFLT */
- "segmentation (limit) fault", /* 8 T_SEGFLT */
+ "", /* 8 unused */
"general protection fault", /* 9 T_PROTFLT */
"trace trap", /* 10 T_TRCTRAP */
"", /* 11 unused */
"page fault", /* 12 T_PAGEFLT */
- "page table fault", /* 13 T_TABLEFLT */
+ "", /* 13 unused */
"alignment fault", /* 14 T_ALIGNFLT */
- "kernel stack pointer not valid", /* 15 T_KSPNOTVAL */
- "bus error", /* 16 T_BUSERR */
- "kernel debugger fault", /* 17 T_KDBTRAP */
+ "", /* 15 unused */
+ "", /* 16 unused */
+ "", /* 17 unused */
"integer divide fault", /* 18 T_DIVIDE */
"non-maskable interrupt trap", /* 19 T_NMI */
"overflow trap", /* 20 T_OFLOW */
@@ -167,7 +167,6 @@ trap(frame)
u_long eva;
#endif
- frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
type = frame.tf_trapno;
code = frame.tf_err;
@@ -178,9 +177,7 @@ trap(frame)
p->p_md.md_regs = (int *)&frame;
switch (type) {
- case T_RESADFLT: /* reserved addressing fault */
case T_PRIVINFLT: /* privileged instruction fault */
- case T_RESOPFLT: /* reserved operand fault */
ucode = type;
i = SIGILL;
break;
@@ -208,6 +205,9 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
case T_STKFLT: /* stack fault */
+ case T_TSSFLT: /* invalid TSS fault */
+ case T_DOUBLEFLT: /* double fault */
+ default:
ucode = code + BUS_SEGM_FAULT ;
i = SIGBUS;
break;
@@ -276,10 +276,6 @@ trap(frame)
ucode = T_FPOPFLT;
i = SIGILL;
break;
-
- default:
- trap_fatal(&frame);
- return;
}
} else {
/* kernel trap */
@@ -291,12 +287,56 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
+ /*
+ * Invalid segment selectors and out of bounds
+ * %eip's and %esp's can be set up in user mode.
+ * This causes a fault in kernel mode when the
+ * kernel tries to return to user mode. We want
+ * to get this fault so that we can fix the
+ * problem here and not have to check all the
+ * selectors and pointers when the user changes
+ * them.
+ */
+#define MAYBE_DORETI_FAULT(where, whereto) \
+ do { \
+ extern void where(void) __asm(__STRING(where)); \
+ extern void whereto(void) __asm(__STRING(whereto)); \
+ if (frame.tf_eip == (int)where) { \
+ frame.tf_eip = (int)whereto; \
+ return; \
+ } \
+ } while (0)
+
+ if (intr_nesting_level == 0) {
+ MAYBE_DORETI_FAULT(doreti_iret,
+ doreti_iret_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_ds,
+ doreti_popl_ds_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_es,
+ doreti_popl_es_fault);
+ }
if (curpcb && curpcb->pcb_onfault) {
frame.tf_eip = (int)curpcb->pcb_onfault;
return;
}
break;
+ case T_TSSFLT:
+ /*
+ * PSL_NT can be set in user mode and isn't cleared
+ * automatically when the kernel is entered. This
+ * causes a TSS fault when the kernel attempts to
+ * `iret' because the TSS link is uninitialized. We
+ * want to get this fault so that we can fix the
+ * problem here and not every time the kernel is
+ * entered.
+ */
+ if (frame.tf_eflags & PSL_NT) {
+ frame.tf_eflags &= ~PSL_NT;
+ return;
+ }
+ break;
+
#ifdef DDB
case T_BPTFLT:
case T_TRCTRAP:
diff --git a/sys/i386/include/psl.h b/sys/i386/include/psl.h
index 906acd4..3d96dbc 100644
--- a/sys/i386/include/psl.h
+++ b/sys/i386/include/psl.h
@@ -34,11 +34,11 @@
* SUCH DAMAGE.
*
* from: @(#)psl.h 5.2 (Berkeley) 1/18/91
- * $Id: psl.h,v 1.4 1994/02/24 00:21:12 hsu Exp $
+ * $Id: psl.h,v 1.5 1994/08/10 03:51:18 wollman Exp $
*/
#ifndef _MACHINE_PSL_H_
-#define _MACHINE_PSL_H_ 1
+#define _MACHINE_PSL_H_
/*
* 386 processor status longword.
@@ -52,18 +52,37 @@
#define PSL_I 0x00000200 /* interrupt enable bit */
#define PSL_D 0x00000400 /* string instruction direction bit */
#define PSL_V 0x00000800 /* overflow bit */
-#define PSL_IOPL 0x00003000 /* i/o priviledge level enable */
+#define PSL_IOPL 0x00003000 /* i/o privilege level */
#define PSL_NT 0x00004000 /* nested task bit */
-#define PSL_RF 0x00010000 /* restart flag bit */
+#define PSL_RF 0x00010000 /* resume flag bit */
#define PSL_VM 0x00020000 /* virtual 8086 mode bit */
#define PSL_AC 0x00040000 /* alignment checking */
#define PSL_VIF 0x00080000 /* virtual interrupt enable */
#define PSL_VIP 0x00100000 /* virtual interrupt pending */
#define PSL_ID 0x00200000 /* identification bit */
-#define PSL_MBZ 0xffc08028 /* must be zero bits */
-#define PSL_MBO 0x00000002 /* must be one bits */
+/*
+ * The i486 manual says that we are not supposed to change reserved flags,
+ * but this is too much trouble since the reserved flags depend on the cpu
+ * and setting them to their historical values works in practice.
+ */
+#define PSL_RESERVED_DEFAULT 0x00000002
+
+/*
+ * Initial flags for kernel and user mode. The kernel later inherits
+ * PSL_I and some other flags from user mode.
+ */
+#define PSL_KERNEL PSL_RESERVED_DEFAULT
+#define PSL_USER (PSL_RESERVED_DEFAULT | PSL_I)
+
+/*
+ * Bits that can be changed in user mode on 486's. We allow these bits
+ * to be changed using ptrace(), sigreturn() and procfs. Setting PS_NT
+ * is undesireable but it may as well be allowed since users can inflict
+ * it on the kernel directly. Changes to PSL_AC are silently ignored on
+ * 386's.
+ */
+#define PSL_USERCHANGE (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_T \
+ | PSL_D | PSL_V | PSL_NT | PSL_AC)
-#define PSL_USERSET (PSL_MBO | PSL_I)
-#define PSL_USERCLR (PSL_MBZ | PSL_NT)
-#endif /* _MACHINE_PSL_H_ */
+#endif /* !_MACHINE_PSL_H_ */
diff --git a/sys/i386/include/trap.h b/sys/i386/include/trap.h
index aa832ff..e1ead77 100644
--- a/sys/i386/include/trap.h
+++ b/sys/i386/include/trap.h
@@ -34,33 +34,25 @@
* SUCH DAMAGE.
*
* from: @(#)trap.h 5.4 (Berkeley) 5/9/91
- * $Id: trap.h,v 1.2 1993/10/16 14:39:37 rgrimes Exp $
+ * $Id: trap.h,v 1.3 1993/11/07 17:43:15 wollman Exp $
*/
#ifndef _MACHINE_TRAP_H_
-#define _MACHINE_TRAP_H_ 1
+#define _MACHINE_TRAP_H_
/*
* Trap type values
* also known in trap.c for name strings
*/
-#define T_RESADFLT 0 /* reserved addressing */
#define T_PRIVINFLT 1 /* privileged instruction */
-#define T_RESOPFLT 2 /* reserved operand */
#define T_BPTFLT 3 /* breakpoint instruction */
-#define T_SYSCALL 5 /* system call (kcall) */
#define T_ARITHTRAP 6 /* arithmetic trap */
#define T_ASTFLT 7 /* system forced exception */
-#define T_SEGFLT 8 /* segmentation (limit) fault */
#define T_PROTFLT 9 /* protection fault */
-#define T_TRCTRAP 10 /* trace trap */
+#define T_TRCTRAP 10 /* debug exception (sic) */
#define T_PAGEFLT 12 /* page fault */
-#define T_TABLEFLT 13 /* page table fault */
#define T_ALIGNFLT 14 /* alignment fault */
-#define T_KSPNOTVAL 15 /* kernel stack pointer not valid */
-#define T_BUSERR 16 /* bus error */
-#define T_KDBTRAP 17 /* kernel debugger trap */
#define T_DIVIDE 18 /* integer divide fault */
#define T_NMI 19 /* non-maskable trap */
@@ -72,7 +64,9 @@
#define T_TSSFLT 25 /* invalid tss fault */
#define T_SEGNPFLT 26 /* segment not present fault */
#define T_STKFLT 27 /* stack fault */
-#define T_RESERVED 28 /* reserved fault base */
+#define T_RESERVED 28 /* reserved (unknown) */
+
+/* XXX most of the following codes aren't used, but could be. */
/* definitions for <sys/signal.h> */
#define ILL_RESAD_FAULT T_RESADFLT
@@ -98,4 +92,5 @@
/* Trap's coming from user mode */
#define T_USER 0x100
-#endif /* _MACHINE_TRAP_H_ */
+
+#endif /* !_MACHINE_TRAP_H_ */
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 0b4946f..57d586a 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.42 1994/12/24 07:22:58 bde Exp $
+ * $Id: trap.c,v 1.43 1995/01/09 16:04:39 davidg Exp $
*/
/*
@@ -73,24 +73,24 @@ void trap_fatal __P((struct trapframe *));
#define MAX_TRAP_MSG 27
char *trap_msg[] = {
- "reserved addressing fault", /* 0 T_RESADFLT */
+ "", /* 0 unused */
"privileged instruction fault", /* 1 T_PRIVINFLT */
- "reserved operand fault", /* 2 T_RESOPFLT */
+ "", /* 2 unused */
"breakpoint instruction fault", /* 3 T_BPTFLT */
"", /* 4 unused */
- "system call trap", /* 5 T_SYSCALL */
+ "", /* 5 unused */
"arithmetic trap", /* 6 T_ARITHTRAP */
"system forced exception", /* 7 T_ASTFLT */
- "segmentation (limit) fault", /* 8 T_SEGFLT */
+ "", /* 8 unused */
"general protection fault", /* 9 T_PROTFLT */
"trace trap", /* 10 T_TRCTRAP */
"", /* 11 unused */
"page fault", /* 12 T_PAGEFLT */
- "page table fault", /* 13 T_TABLEFLT */
+ "", /* 13 unused */
"alignment fault", /* 14 T_ALIGNFLT */
- "kernel stack pointer not valid", /* 15 T_KSPNOTVAL */
- "bus error", /* 16 T_BUSERR */
- "kernel debugger fault", /* 17 T_KDBTRAP */
+ "", /* 15 unused */
+ "", /* 16 unused */
+ "", /* 17 unused */
"integer divide fault", /* 18 T_DIVIDE */
"non-maskable interrupt trap", /* 19 T_NMI */
"overflow trap", /* 20 T_OFLOW */
@@ -167,7 +167,6 @@ trap(frame)
u_long eva;
#endif
- frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
type = frame.tf_trapno;
code = frame.tf_err;
@@ -178,9 +177,7 @@ trap(frame)
p->p_md.md_regs = (int *)&frame;
switch (type) {
- case T_RESADFLT: /* reserved addressing fault */
case T_PRIVINFLT: /* privileged instruction fault */
- case T_RESOPFLT: /* reserved operand fault */
ucode = type;
i = SIGILL;
break;
@@ -208,6 +205,9 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
case T_STKFLT: /* stack fault */
+ case T_TSSFLT: /* invalid TSS fault */
+ case T_DOUBLEFLT: /* double fault */
+ default:
ucode = code + BUS_SEGM_FAULT ;
i = SIGBUS;
break;
@@ -276,10 +276,6 @@ trap(frame)
ucode = T_FPOPFLT;
i = SIGILL;
break;
-
- default:
- trap_fatal(&frame);
- return;
}
} else {
/* kernel trap */
@@ -291,12 +287,56 @@ trap(frame)
case T_PROTFLT: /* general protection fault */
case T_SEGNPFLT: /* segment not present fault */
+ /*
+ * Invalid segment selectors and out of bounds
+ * %eip's and %esp's can be set up in user mode.
+ * This causes a fault in kernel mode when the
+ * kernel tries to return to user mode. We want
+ * to get this fault so that we can fix the
+ * problem here and not have to check all the
+ * selectors and pointers when the user changes
+ * them.
+ */
+#define MAYBE_DORETI_FAULT(where, whereto) \
+ do { \
+ extern void where(void) __asm(__STRING(where)); \
+ extern void whereto(void) __asm(__STRING(whereto)); \
+ if (frame.tf_eip == (int)where) { \
+ frame.tf_eip = (int)whereto; \
+ return; \
+ } \
+ } while (0)
+
+ if (intr_nesting_level == 0) {
+ MAYBE_DORETI_FAULT(doreti_iret,
+ doreti_iret_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_ds,
+ doreti_popl_ds_fault);
+ MAYBE_DORETI_FAULT(doreti_popl_es,
+ doreti_popl_es_fault);
+ }
if (curpcb && curpcb->pcb_onfault) {
frame.tf_eip = (int)curpcb->pcb_onfault;
return;
}
break;
+ case T_TSSFLT:
+ /*
+ * PSL_NT can be set in user mode and isn't cleared
+ * automatically when the kernel is entered. This
+ * causes a TSS fault when the kernel attempts to
+ * `iret' because the TSS link is uninitialized. We
+ * want to get this fault so that we can fix the
+ * problem here and not every time the kernel is
+ * entered.
+ */
+ if (frame.tf_eflags & PSL_NT) {
+ frame.tf_eflags &= ~PSL_NT;
+ return;
+ }
+ break;
+
#ifdef DDB
case T_BPTFLT:
case T_TRCTRAP:
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 63537bd..692f2c5 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: sys_process.c,v 1.6 1994/08/18 22:35:05 wollman Exp $
+ * $Id: sys_process.c,v 1.7 1994/09/25 19:33:49 phk Exp $
*/
#include <sys/param.h>
@@ -326,13 +326,9 @@ ptrace(curp, uap, retval)
*retval = *(int*)((u_int)p->p_addr + (u_int)uap->addr);
return 0;
case PT_WRITE_U:
- if ((u_int)uap->addr > (UPAGES * NBPG - sizeof(int))) {
- return EFAULT;
- }
p->p_addr->u_kproc.kp_proc = *p;
fill_eproc (p, &p->p_addr->u_kproc.kp_eproc);
- *(int*)((u_int)p->p_addr + (u_int)uap->addr) = uap->data;
- return 0;
+ return ptrace_write_u(p, (vm_offset_t)uap->addr, uap->data);
case PT_KILL:
p->p_xstat = SIGKILL;
setrunnable(p);
OpenPOWER on IntegriCloud