Add a small API to manage the MD user trap structures. Specifically, we
now use a pool mutex to manage the reference counts. This fixes races resulting in use-after-free. Tested by: kris, David Cornejo dave at dogwood dot com Reported by: bmilekic's MemGuard MFC after: 1 week
This commit is contained in:
parent
efa42cbc93
commit
7d9ace1d46
@ -45,10 +45,14 @@ extern vm_offset_t kstack0;
|
||||
extern vm_paddr_t kstack0_phys;
|
||||
|
||||
struct pcpu;
|
||||
struct md_utrap;
|
||||
|
||||
void cpu_identify(u_long vers, u_int clock, u_int id);
|
||||
void cpu_setregs(struct pcpu *pc);
|
||||
int is_physical_memory(vm_paddr_t addr);
|
||||
struct md_utrap *utrap_alloc(void);
|
||||
void utrap_free(struct md_utrap *ut);
|
||||
struct md_utrap *utrap_hold(struct md_utrap *ut);
|
||||
|
||||
cpu_block_copy_t spitfire_block_copy;
|
||||
cpu_block_zero_t spitfire_block_zero;
|
||||
|
@ -744,7 +744,6 @@ void
|
||||
exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
|
||||
{
|
||||
struct trapframe *tf;
|
||||
struct md_utrap *ut;
|
||||
struct pcb *pcb;
|
||||
struct proc *p;
|
||||
u_long sp;
|
||||
@ -752,10 +751,8 @@ exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
|
||||
/* XXX no cpu_exec */
|
||||
p = td->td_proc;
|
||||
p->p_md.md_sigtramp = NULL;
|
||||
if ((ut = p->p_md.md_utrap) != NULL) {
|
||||
ut->ut_refcnt--;
|
||||
if (ut->ut_refcnt == 0)
|
||||
free(ut, M_SUBPROC);
|
||||
if (p->p_md.md_utrap != NULL) {
|
||||
utrap_free(p->p_md.md_utrap);
|
||||
p->p_md.md_utrap = NULL;
|
||||
}
|
||||
|
||||
@ -838,3 +835,40 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
|
||||
tf->tf_gsr = fpregs->fr_gsr;
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct md_utrap *
|
||||
utrap_alloc(void)
|
||||
{
|
||||
struct md_utrap *ut;
|
||||
|
||||
ut = malloc(sizeof(struct md_utrap), M_SUBPROC, M_WAITOK | M_ZERO);
|
||||
ut->ut_refcnt = 1;
|
||||
return (ut);
|
||||
}
|
||||
|
||||
void
|
||||
utrap_free(struct md_utrap *ut)
|
||||
{
|
||||
int refcnt;
|
||||
|
||||
if (ut == NULL)
|
||||
return;
|
||||
mtx_pool_lock(mtxpool_sleep, ut);
|
||||
ut->ut_refcnt--;
|
||||
refcnt = ut->ut_refcnt;
|
||||
mtx_pool_unlock(mtxpool_sleep, ut);
|
||||
if (refcnt == 0)
|
||||
free(ut, M_SUBPROC);
|
||||
}
|
||||
|
||||
struct md_utrap *
|
||||
utrap_hold(struct md_utrap *ut)
|
||||
{
|
||||
|
||||
if (ut == NULL)
|
||||
return (NULL);
|
||||
mtx_pool_lock(mtxpool_sleep, ut);
|
||||
ut->ut_refcnt++;
|
||||
mtx_pool_unlock(mtxpool_sleep, ut);
|
||||
return (ut);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysproto.h>
|
||||
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/utrap.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
@ -119,9 +120,7 @@ sparc_utrap_install(struct thread *td, char *args)
|
||||
}
|
||||
if (ua.type != UTH_NOCHANGE) {
|
||||
if (ut == NULL) {
|
||||
ut = malloc(sizeof *ut, M_SUBPROC,
|
||||
M_WAITOK | M_ZERO);
|
||||
ut->ut_refcnt = 1;
|
||||
ut = utrap_alloc();
|
||||
td->td_proc->p_md.md_utrap = ut;
|
||||
}
|
||||
ut->ut_precise[ua.type] = ua.new_precise;
|
||||
|
@ -111,15 +111,12 @@ PMAP_STATS_VAR(uma_nsmall_free);
|
||||
void
|
||||
cpu_exit(struct thread *td)
|
||||
{
|
||||
struct md_utrap *ut;
|
||||
struct proc *p;
|
||||
|
||||
p = td->td_proc;
|
||||
p->p_md.md_sigtramp = NULL;
|
||||
if ((ut = p->p_md.md_utrap) != NULL) {
|
||||
ut->ut_refcnt--;
|
||||
if (ut->ut_refcnt == 0)
|
||||
free(ut, M_SUBPROC);
|
||||
if (p->p_md.md_utrap != NULL) {
|
||||
utrap_free(p->p_md.md_utrap);
|
||||
p->p_md.md_utrap = NULL;
|
||||
}
|
||||
}
|
||||
@ -200,7 +197,6 @@ cpu_set_upcall_kse(struct thread *td, struct kse_upcall *ku)
|
||||
void
|
||||
cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
{
|
||||
struct md_utrap *ut;
|
||||
struct trapframe *tf;
|
||||
struct frame *fp;
|
||||
struct pcb *pcb1;
|
||||
@ -216,9 +212,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
return;
|
||||
|
||||
p2->p_md.md_sigtramp = td1->td_proc->p_md.md_sigtramp;
|
||||
if ((ut = td1->td_proc->p_md.md_utrap) != NULL)
|
||||
ut->ut_refcnt++;
|
||||
p2->p_md.md_utrap = ut;
|
||||
p2->p_md.md_utrap = utrap_hold(td1->td_proc->p_md.md_utrap);
|
||||
|
||||
/* The pcb must be aligned on a 64-byte boundary. */
|
||||
pcb1 = td1->td_pcb;
|
||||
|
Loading…
Reference in New Issue
Block a user