Change useracc() and kernacc() to use VM_PROT_{READ|WRITE|EXECUTE} for the

"rw" argument, rather than hijacking B_{READ|WRITE}.

Fix two bugs (physio & cam) resulting by the confusion caused by this.

Submitted by:   Tor.Egge@fast.no
Reviewed by:    alc, ken (partly)
This commit is contained in:
Poul-Henning Kamp 1999-10-30 06:32:05 +00:00
parent 1c6972cf90
commit 02c58685a4
20 changed files with 77 additions and 64 deletions

View File

@ -64,10 +64,11 @@ and
.Fa len .
The possible values of
.Fa rw
are
.Dv B_READ
are any bitwise combination of
.Dv VM_PROT_READ ,
.Dv VM_PROT_WRITE
and
.Dv B_WRITE .
.Dv VM_PROT_EXECUTE .
.Fn kernacc
checks addresses in the kernel address space, while
.Fn useracc
@ -78,9 +79,11 @@ operation is taken from the global variable
.Va curproc .
.Pp
.Sh RETURN VALUES
Both functions return 1 if the type of access specified by
Both functions return boolean true if the type of access specified
by
.Fa rw
is permitted. Otherwise 0 is returned.
is permitted. Otherwise boolean false is returned.
.Pp
.Sh BUGS
The process pointer should be passed in as an argument.
The process pointer should be passed in as an argument to
.Fn useracc .

View File

@ -1192,7 +1192,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);
(void)grow_stack(p, (u_long)sip);
if (useracc((caddr_t)sip, fsize, B_WRITE) == 0) {
if (!useracc((caddr_t)sip, fsize, VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -1319,7 +1319,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
printf("sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
sig, &sf, sfp);
#endif
if (useracc((caddr_t)sfp, sizeof(sf), B_WRITE) == 0) {
if (!useracc((caddr_t)sfp, sizeof(sf), VM_PROT_WRITE)) {
#ifdef DEBUG
if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
printf("sendsig(%d): useracc failed on sig %d\n",
@ -1421,7 +1421,7 @@ osigreturn(struct proc *p,
* Test and fetch the context structure.
* We grab it all at once for speed.
*/
if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0 ||
if (useracc((caddr_t)scp, sizeof (*scp), VM_PROT_WRITE) == 0 ||
copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
return (EINVAL);
@ -1491,7 +1491,7 @@ sigreturn(struct proc *p,
* Test and fetch the context structure.
* We grab it all at once for speed.
*/
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0 ||
if (useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_WRITE) == 0 ||
copyin((caddr_t)ucp, (caddr_t)&uc, sizeof(ucontext_t)))
return (EINVAL);

View File

@ -202,7 +202,8 @@ mmrw(dev, uio, flags)
return (EFAULT);
#else
if (!kernacc((caddr_t)v, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
uio->uio_rw == UIO_READ ?
VM_PROT_READ : VM_PROT_WRITE))
return (EFAULT);
#endif
error = uiomove((caddr_t)v, c, uio);

View File

@ -961,7 +961,7 @@ unaligned_fixup(va, opcode, reg, p)
* Even if it's an unknown opcode, SEGV if the access
* should have failed.
*/
if (!useracc((caddr_t)va, size ? size : 1, B_WRITE)) {
if (!useracc((caddr_t)va, size ? size : 1, VM_PROT_WRITE)) {
signal = SIGSEGV;
goto out;
}

View File

@ -221,7 +221,8 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if ((grow_stack (p, (int)fp) == FALSE) ||
(useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
!useracc((caddr_t)fp, sizeof (struct linux_sigframe),
VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.

View File

@ -501,7 +501,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if (grow_stack(p, (int)fp) == FALSE ||
useracc((caddr_t)fp, sizeof(struct osigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)fp, sizeof(struct osigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -648,7 +648,7 @@ sendsig(catcher, sig, mask, code)
* access is denied.
*/
if (grow_stack(p, (int)sfp) == FALSE ||
useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)sfp, sizeof(struct sigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -769,7 +769,7 @@ osigreturn(p, uap)
scp = uap->sigcntxp;
if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0)
if (!useracc((caddr_t)scp, sizeof (struct osigcontext), VM_PROT_WRITE))
return(EFAULT);
eflags = scp->sc_ps;
@ -880,7 +880,7 @@ sigreturn(p, uap)
ucp = uap->sigcntxp;
eflags = ucp->uc_mcontext.mc_eflags;
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0)
if (!useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_WRITE))
return(EFAULT);
if (eflags & PSL_VM) {

View File

@ -204,7 +204,8 @@ mmrw(dev, uio, flags)
return EFAULT;
if (!kernacc((caddr_t)(int)uio->uio_offset, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
uio->uio_rw == UIO_READ ?
VM_PROT_READ : VM_PROT_WRITE))
return (EFAULT);
error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
continue;

View File

@ -560,8 +560,9 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
}
if (dirs[i] & CAM_DIR_OUT) {
flags[i] = B_READ;
if (useracc(*data_ptrs[i], lengths[i], B_READ) == 0){
flags[i] = B_WRITE;
if (!useracc(*data_ptrs[i], lengths[i],
VM_PROT_READ)) {
printf("cam_periph_mapmem: error, "
"address %p, length %lu isn't "
"user accessible for READ\n",
@ -576,8 +577,9 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
* is all 0's, and so it is "set" all the time.
*/
if (dirs[i] & CAM_DIR_IN) {
flags[i] |= B_WRITE;
if (useracc(*data_ptrs[i], lengths[i], B_WRITE) == 0){
flags[i] |= B_READ;
if (!useracc(*data_ptrs[i], lengths[i],
VM_PROT_WRITE)) {
printf("cam_periph_mapmem: error, "
"address %p, length %lu isn't "
"user accessible for WRITE\n",

View File

@ -663,7 +663,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
* Check the user's buffer to make sure it's readable.
*/
if (!useracc((caddr_t)cio->patterns,
cio->pat_buf_len, B_READ)) {
cio->pat_buf_len, VM_PROT_READ)) {
printf("pci_ioctl: pattern buffer %p, "
"length %u isn't user accessible for"
" READ\n", cio->patterns,
@ -699,7 +699,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
* Make sure we can write to the match buffer.
*/
if (!useracc((caddr_t)cio->matches,
cio->match_buf_len, B_WRITE)) {
cio->match_buf_len, VM_PROT_WRITE)) {
printf("pci_ioctl: match buffer %p, length %u "
"isn't user accessible for WRITE\n",
cio->matches, cio->match_buf_len);

View File

@ -501,7 +501,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if (grow_stack(p, (int)fp) == FALSE ||
useracc((caddr_t)fp, sizeof(struct osigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)fp, sizeof(struct osigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -648,7 +648,7 @@ sendsig(catcher, sig, mask, code)
* access is denied.
*/
if (grow_stack(p, (int)sfp) == FALSE ||
useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)sfp, sizeof(struct sigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -769,7 +769,7 @@ osigreturn(p, uap)
scp = uap->sigcntxp;
if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0)
if (!useracc((caddr_t)scp, sizeof (struct osigcontext), VM_PROT_WRITE))
return(EFAULT);
eflags = scp->sc_ps;
@ -880,7 +880,7 @@ sigreturn(p, uap)
ucp = uap->sigcntxp;
eflags = ucp->uc_mcontext.mc_eflags;
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0)
if (!useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_WRITE))
return(EFAULT);
if (eflags & PSL_VM) {

View File

@ -204,7 +204,8 @@ mmrw(dev, uio, flags)
return EFAULT;
if (!kernacc((caddr_t)(int)uio->uio_offset, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
uio->uio_rw == UIO_READ ?
VM_PROT_READ : VM_PROT_WRITE))
return (EFAULT);
error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
continue;

View File

@ -221,7 +221,8 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if ((grow_stack (p, (int)fp) == FALSE) ||
(useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
!useracc((caddr_t)fp, sizeof (struct linux_sigframe),
VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.

View File

@ -101,7 +101,8 @@ physio(dev_t dev, struct uio *uio, int ioflag)
if (uio->uio_segflg == UIO_USERSPACE) {
if (!useracc(bp->b_data, bp->b_bufsize,
bp->b_flags & B_READ)) {
bp->b_flags & B_READ ?
VM_PROT_WRITE : VM_PROT_READ)) {
error = EFAULT;
goto doerror;
}

View File

@ -845,13 +845,13 @@ userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t *old
}
if (old) {
if (!useracc(old, req.oldlen, B_WRITE))
if (!useracc(old, req.oldlen, VM_PROT_WRITE))
return (EFAULT);
req.oldptr= old;
}
if (newlen) {
if (!useracc(new, req.newlen, B_READ))
if (!useracc(new, req.newlen, VM_PROT_READ))
return (EFAULT);
req.newlen = newlen;
req.newptr = new;

View File

@ -276,7 +276,8 @@ nanosleep(p, uap)
if (error)
return (error);
if (SCARG(uap, rmtp))
if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt),
VM_PROT_WRITE))
return (EFAULT);
error = nanosleep1(p, &rqt, &rmt);
if (error && SCARG(uap, rmtp)) {

View File

@ -916,7 +916,6 @@ aio_qphysio(p, aiocbe)
struct aiocb *cb;
struct file *fp;
struct buf *bp;
int bflags;
struct vnode *vp;
struct kaioinfo *ki;
struct filedesc *fdp;
@ -924,7 +923,6 @@ aio_qphysio(p, aiocbe)
int fd;
int s;
int cnt;
int rw;
struct cdevsw *cdev;
cb = &aiocbe->uaiocb;
@ -996,29 +994,26 @@ aio_qphysio(p, aiocbe)
bp->b_dev = vp->v_rdev;
error = bp->b_error = 0;
if (cb->aio_lio_opcode == LIO_WRITE) {
rw = 0;
bflags = B_WRITE;
} else {
rw = 1;
bflags = B_READ;
}
bp->b_bcount = cb->aio_nbytes;
bp->b_bufsize = cb->aio_nbytes;
bp->b_flags = B_PHYS | B_CALL | bflags;
bp->b_flags = B_PHYS | B_CALL;
bp->b_iodone = aio_physwakeup;
bp->b_saveaddr = bp->b_data;
bp->b_data = (void *) cb->aio_buf;
bp->b_blkno = btodb(cb->aio_offset);
if (rw && !useracc(bp->b_data, bp->b_bufsize, B_WRITE)) {
error = EFAULT;
goto doerror;
}
if (!rw && !useracc(bp->b_data, bp->b_bufsize, B_READ)) {
error = EFAULT;
goto doerror;
if (cb->aio_lio_opcode == LIO_WRITE) {
bp->b_flags |= B_WRITE;
if (!useracc(bp->b_data, bp->b_bufsize, VM_PROT_READ)) {
error = EFAULT;
goto doerror;
}
} else {
bp->b_flags |= B_READ;
if (!useracc(bp->b_data, bp->b_bufsize, VM_PROT_WRITE)) {
error = EFAULT;
goto doerror;
}
}
/* bring buffer into kernel space */

View File

@ -514,7 +514,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if (grow_stack(p, (int)fp) == FALSE ||
useracc((caddr_t)fp, sizeof(struct osigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)fp, sizeof(struct osigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -661,7 +661,7 @@ sendsig(catcher, sig, mask, code)
* access is denied.
*/
if (grow_stack(p, (int)sfp) == FALSE ||
useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)sfp, sizeof(struct sigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -782,7 +782,7 @@ osigreturn(p, uap)
scp = uap->sigcntxp;
if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0)
if (!useracc((caddr_t)scp, sizeof (struct osigcontext), VM_PROT_WRITE))
return(EFAULT);
eflags = scp->sc_ps;
@ -893,7 +893,7 @@ sigreturn(p, uap)
ucp = uap->sigcntxp;
eflags = ucp->uc_mcontext.mc_eflags;
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0)
if (!useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_WRITE))
return(EFAULT);
if (eflags & PSL_VM) {

View File

@ -514,7 +514,7 @@ osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
* if access is denied.
*/
if (grow_stack(p, (int)fp) == FALSE ||
useracc((caddr_t)fp, sizeof(struct osigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)fp, sizeof(struct osigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -661,7 +661,7 @@ sendsig(catcher, sig, mask, code)
* access is denied.
*/
if (grow_stack(p, (int)sfp) == FALSE ||
useracc((caddr_t)sfp, sizeof(struct sigframe), B_WRITE) == FALSE) {
!useracc((caddr_t)sfp, sizeof(struct sigframe), VM_PROT_WRITE)) {
/*
* Process has trashed its stack; give it an illegal
* instruction to halt it in its tracks.
@ -782,7 +782,7 @@ osigreturn(p, uap)
scp = uap->sigcntxp;
if (useracc((caddr_t)scp, sizeof (struct osigcontext), B_WRITE) == 0)
if (!useracc((caddr_t)scp, sizeof (struct osigcontext), VM_PROT_WRITE))
return(EFAULT);
eflags = scp->sc_ps;
@ -893,7 +893,7 @@ sigreturn(p, uap)
ucp = uap->sigcntxp;
eflags = ucp->uc_mcontext.mc_eflags;
if (useracc((caddr_t)ucp, sizeof(ucontext_t), B_WRITE) == 0)
if (!useracc((caddr_t)ucp, sizeof(ucontext_t), VM_PROT_WRITE))
return(EFAULT);
if (eflags & PSL_VM) {

View File

@ -663,7 +663,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
* Check the user's buffer to make sure it's readable.
*/
if (!useracc((caddr_t)cio->patterns,
cio->pat_buf_len, B_READ)) {
cio->pat_buf_len, VM_PROT_READ)) {
printf("pci_ioctl: pattern buffer %p, "
"length %u isn't user accessible for"
" READ\n", cio->patterns,
@ -699,7 +699,7 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
* Make sure we can write to the match buffer.
*/
if (!useracc((caddr_t)cio->matches,
cio->match_buf_len, B_WRITE)) {
cio->match_buf_len, VM_PROT_WRITE)) {
printf("pci_ioctl: match buffer %p, length %u "
"isn't user accessible for WRITE\n",
cio->matches, cio->match_buf_len);

View File

@ -118,8 +118,11 @@ kernacc(addr, len, rw)
{
boolean_t rv;
vm_offset_t saddr, eaddr;
vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
vm_prot_t prot;
KASSERT(rw & (~VM_PROT_ALL),
("illegal ``rw'' argument to kernacc (%x)\n", rw));
prot = rw;
saddr = trunc_page((vm_offset_t)addr);
eaddr = round_page((vm_offset_t)addr + len);
vm_map_lock_read(kernel_map);
@ -134,10 +137,13 @@ useracc(addr, len, rw)
int len, rw;
{
boolean_t rv;
vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE;
vm_prot_t prot;
vm_map_t map;
vm_map_entry_t save_hint;
KASSERT(rw & (~VM_PROT_ALL),
("illegal ``rw'' argument to useracc (%x)\n", rw));
prot = rw;
/*
* XXX - check separately to disallow access to user area and user
* page tables - they are in the map.