--- //depot/vendor/freebsd/src/sys/compat/linux/linux_misc.c 2006/06/23 18:51:05 +++ //depot/projects/smpng/sys/compat/linux/linux_misc.c 2006/07/13 20:50:08 @@ -229,7 +229,7 @@ unsigned long bss_size; char *library; int error; - int locked; + int locked, vfslocked; LCONVPATHEXIST(td, args->library, &library); @@ -239,32 +239,24 @@ #endif a_out = NULL; + vfslocked = 0; locked = 0; vp = NULL; - /* - * XXX: This code should make use of vn_open(), rather than doing - * all this stuff itself. - */ - NDINIT(&ni, LOOKUP, ISOPEN|FOLLOW|LOCKLEAF, UIO_SYSSPACE, library, td); + NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, + UIO_SYSSPACE, library, td); error = namei(&ni); LFREEPATH(library); if (error) goto cleanup; vp = ni.ni_vp; - /* - * XXX - This looks like a bogus check. A LOCKLEAF namei should not - * succeed without returning a vnode. - */ - if (vp == NULL) { - error = ENOEXEC; /* ?? */ - goto cleanup; - } + vfslocked = NDHASGIANT(&ni); NDFREE(&ni, NDF_ONLY_PNBUF); /* * From here on down, we have a locked vnode that must be unlocked. + * XXX: The code below largely duplicates exec_check_permissions(). */ locked++; @@ -281,6 +273,7 @@ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { + /* EACCESS is what exec(2) returns. */ error = ENOEXEC; goto cleanup; } @@ -299,6 +292,8 @@ /* * XXX: This should use vn_open() so that it is properly authorized, * and to reduce code redundancy all over the place here. + * XXX: Not really, it duplicates far more of exec_check_permissions() + * than vn_open(). */ #ifdef MAC error = mac_check_vnode_open(td->td_ucred, vp, FREAD); @@ -312,12 +307,6 @@ /* Pull in executable header into kernel_map */ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); - /* - * Lock no longer needed - */ - locked = 0; - VOP_UNLOCK(vp, 0, td); - if (error) goto cleanup; @@ -372,11 +361,21 @@ } PROC_UNLOCK(td->td_proc); - mp_fixme("Unlocked vflags access."); - /* prevent more writers */ + /* + * Prevent more writers. + * XXX: Note that if any of the VM operations fail below we don't + * clear this flag. + */ vp->v_vflag |= VV_TEXT; /* + * Lock no longer needed + */ + locked = 0; + VOP_UNLOCK(vp, 0, td); + VFS_UNLOCK_GIANT(vfslocked); + + /* * Check if file_offset page aligned. Currently we cannot handle * misalinged file offsets, and so we read in the entire image * (what a waste). @@ -453,8 +452,10 @@ cleanup: /* Unlock vnode if needed */ - if (locked) + if (locked) { VOP_UNLOCK(vp, 0, td); + VFS_UNLOCK_GIANT(vfslocked); + } /* Release the kernel mapping. */ if (a_out) --- //depot/vendor/freebsd/src/sys/compat/svr4/svr4_misc.c 2006/07/19 19:07:12 +++ //depot/projects/smpng/sys/compat/svr4/svr4_misc.c 2006/07/19 20:19:51 @@ -606,34 +606,36 @@ struct svr4_sys_fchroot_args *uap; { struct filedesc *fdp = td->td_proc->p_fd; - struct vnode *vp, *vpold; + struct vnode *vp; struct file *fp; - int error; + int error, vfslocked; if ((error = suser(td)) != 0) return error; if ((error = getvnode(fdp, uap->fd, &fp)) != 0) return error; vp = fp->f_vnode; + VREF(vp); + fdrop(fp, td); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - if (vp->v_type != VDIR) - error = ENOTDIR; - else - error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + error = change_dir(vp, td); + if (error) + goto fail; +#ifdef MAC + error = mac_check_vnode_chroot(td->td_ucred, vp); + if (error) + goto fail; +#endif VOP_UNLOCK(vp, 0, td); - if (error) { - fdrop(fp, td); - return error; - } - VREF(vp); - FILEDESC_LOCK_FAST(fdp); - vpold = fdp->fd_rdir; - fdp->fd_rdir = vp; - FILEDESC_UNLOCK_FAST(fdp); - if (vpold != NULL) - vrele(vpold); - fdrop(fp, td); - return 0; + error = change_root(vp, td); + vrele(vp); + VFS_UNLOCK_GIANT(vfslocked); + return (error); +fail: + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); + return (error); }