Plug memory disclosures via ptrace(2).
On some architectures, the structures returned by PT_GET*REGS were not fully populated and could contain uninitialized stack memory. The same issue existed with the register files in procfs. Reported by: Thomas Barabosch, Fraunhofer FKIE Reviewed by: kib MFC after: 3 days Security: kernel stack memory disclosure Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D18421
This commit is contained in:
parent
afa4092620
commit
53d55c9af9
@ -2045,6 +2045,7 @@ fill_regs(struct thread *td, struct reg *regs)
|
||||
int
|
||||
fill_frame_regs(struct trapframe *tp, struct reg *regs)
|
||||
{
|
||||
|
||||
regs->r_r15 = tp->tf_r15;
|
||||
regs->r_r14 = tp->tf_r14;
|
||||
regs->r_r13 = tp->tf_r13;
|
||||
@ -2076,6 +2077,8 @@ fill_frame_regs(struct trapframe *tp, struct reg *regs)
|
||||
regs->r_fs = 0;
|
||||
regs->r_gs = 0;
|
||||
}
|
||||
regs->r_err = 0;
|
||||
regs->r_trapno = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,8 @@ fill_regs32(struct thread *td, struct reg32 *regs)
|
||||
regs->r_eflags = tp->tf_rflags;
|
||||
regs->r_esp = tp->tf_rsp;
|
||||
regs->r_ss = tp->tf_ss;
|
||||
regs->r_err = 0;
|
||||
regs->r_trapno = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,7 @@ fill_regs(struct thread *td, struct reg *regs)
|
||||
regs->r_cpsr = tf->tf_spsr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
fill_fpregs(struct thread *td, struct fpreg *regs)
|
||||
{
|
||||
@ -134,8 +135,11 @@ set_fpregs(struct thread *td, struct fpreg *regs)
|
||||
int
|
||||
fill_dbregs(struct thread *td, struct dbreg *regs)
|
||||
{
|
||||
|
||||
bzero(regs, sizeof(*regs));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
set_dbregs(struct thread *td, struct dbreg *regs)
|
||||
{
|
||||
|
@ -112,8 +112,10 @@ procfs_doprocdbregs(PFS_FILL_ARGS)
|
||||
return (EINVAL);
|
||||
}
|
||||
wrap32 = 1;
|
||||
}
|
||||
memset(&r32, 0, sizeof(r32));
|
||||
} else
|
||||
#endif
|
||||
memset(&r, 0, sizeof(r));
|
||||
error = PROC(read, dbregs, td2, &r);
|
||||
if (error == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
|
@ -102,7 +102,6 @@ procfs_doprocfpregs(PFS_FILL_ARGS)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
/* XXXKSE: */
|
||||
td2 = FIRST_THREAD_IN_PROC(p);
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (SV_CURPROC_FLAG(SV_ILP32)) {
|
||||
@ -111,8 +110,10 @@ procfs_doprocfpregs(PFS_FILL_ARGS)
|
||||
return (EINVAL);
|
||||
}
|
||||
wrap32 = 1;
|
||||
}
|
||||
memset(&r32, 0, sizeof(r32));
|
||||
} else
|
||||
#endif
|
||||
memset(&r, 0, sizeof(r));
|
||||
error = PROC(read, fpregs, td2, &r);
|
||||
if (error == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
|
@ -102,7 +102,6 @@ procfs_doprocregs(PFS_FILL_ARGS)
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
/* XXXKSE: */
|
||||
td2 = FIRST_THREAD_IN_PROC(p);
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (SV_CURPROC_FLAG(SV_ILP32)) {
|
||||
@ -111,8 +110,10 @@ procfs_doprocregs(PFS_FILL_ARGS)
|
||||
return (EINVAL);
|
||||
}
|
||||
wrap32 = 1;
|
||||
}
|
||||
memset(&r32, 0, sizeof(r32));
|
||||
} else
|
||||
#endif
|
||||
memset(&r, 0, sizeof(r));
|
||||
error = PROC(read, regs, td2, &r);
|
||||
if (error == 0) {
|
||||
PROC_UNLOCK(p);
|
||||
|
@ -2816,6 +2816,7 @@ fill_regs(struct thread *td, struct reg *regs)
|
||||
int
|
||||
fill_frame_regs(struct trapframe *tp, struct reg *regs)
|
||||
{
|
||||
|
||||
regs->r_fs = tp->tf_fs;
|
||||
regs->r_es = tp->tf_es;
|
||||
regs->r_ds = tp->tf_ds;
|
||||
@ -2831,6 +2832,8 @@ fill_frame_regs(struct trapframe *tp, struct reg *regs)
|
||||
regs->r_eflags = tp->tf_eflags;
|
||||
regs->r_esp = tp->tf_esp;
|
||||
regs->r_ss = tp->tf_ss;
|
||||
regs->r_err = 0;
|
||||
regs->r_trapno = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -541,6 +541,9 @@ struct ptrace_args {
|
||||
* copyin(uap->addr, &r.reg32, sizeof r.reg32);
|
||||
* .. except this is done at runtime.
|
||||
*/
|
||||
#define BZERO(a, s) wrap32 ? \
|
||||
bzero(a ## 32, s ## 32) : \
|
||||
bzero(a, s)
|
||||
#define COPYIN(u, k, s) wrap32 ? \
|
||||
copyin(u, k ## 32, s ## 32) : \
|
||||
copyin(u, k, s)
|
||||
@ -573,7 +576,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
struct ptrace_lwpinfo32 pl32;
|
||||
struct ptrace_vm_entry32 pve32;
|
||||
#endif
|
||||
char args[nitems(td->td_sa.args) * sizeof(register_t)];
|
||||
char args[sizeof(td->td_sa.args)];
|
||||
int ptevents;
|
||||
} r;
|
||||
void *addr;
|
||||
@ -590,12 +593,18 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
addr = &r;
|
||||
switch (uap->req) {
|
||||
case PT_GET_EVENT_MASK:
|
||||
case PT_GETREGS:
|
||||
case PT_GETFPREGS:
|
||||
case PT_GETDBREGS:
|
||||
case PT_LWPINFO:
|
||||
case PT_GET_SC_ARGS:
|
||||
break;
|
||||
case PT_GETREGS:
|
||||
BZERO(&r.reg, sizeof r.reg);
|
||||
break;
|
||||
case PT_GETFPREGS:
|
||||
BZERO(&r.fpreg, sizeof r.fpreg);
|
||||
break;
|
||||
case PT_GETDBREGS:
|
||||
BZERO(&r.dbreg, sizeof r.dbreg);
|
||||
break;
|
||||
case PT_SETREGS:
|
||||
error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
|
||||
break;
|
||||
@ -662,6 +671,7 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
}
|
||||
#undef COPYIN
|
||||
#undef COPYOUT
|
||||
#undef BZERO
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
/*
|
||||
|
@ -1056,6 +1056,7 @@ fill_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs));
|
||||
fpregs->fr_fsr = tf->tf_fsr;
|
||||
fpregs->fr_gsr = tf->tf_gsr;
|
||||
fpregs->fr_pad[0] = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user