Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -744,7 +744,8 @@ imgp->object = NULL; imgp->execlabel = NULL; - NDINIT(nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, curthread); + NDINIT(nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, + file, curthread); if ((error = namei(nd)) != 0) { nd->ni_vp = NULL; goto fail; @@ -752,6 +753,7 @@ NDFREE(nd, NDF_ONLY_PNBUF); imgp->vp = nd->ni_vp; +again: /* * Check permissions, modes, uid, etc on the file, and "open" it. */ @@ -759,15 +761,31 @@ if (error) goto fail; + /* + * Also make certain that the interpreter stays the same, + * so set its VV_TEXT flag, too. Since this function is only + * used to load the interpreter, the VV_TEXT is pretty much + * always already set. + */ + if (VOP_IS_TEXT(nd->ni_vp) == 0) { + if (VOP_ISLOCKED(nd->ni_vp) != LK_EXCLUSIVE) { + vn_lock(nd->ni_vp, LK_UPGRADE | LK_RETRY); + + /* + * LK_UPGRADE might have resulted in dropping + * the lock, which would invalidate the checks + * done in exec_check_permissions(). + */ + goto again; + } + + VOP_SET_TEXT(nd->ni_vp); + vn_lock(nd->ni_vp, LK_DOWNGRADE | LK_RETRY); + } + error = exec_map_first_page(imgp); if (error) goto fail; - - /* - * Also make certain that the interpreter stays the same, so set - * its VV_TEXT flag, too. - */ - VOP_SET_TEXT(nd->ni_vp); imgp->object = nd->ni_vp->v_object;