Use shared vnode locks for the ELF interpreter.

Reviewed by:	kib
MFC after:	2 weeks
Sponsored by:	DARPA, AFRL
Differential Revision:	https://reviews.freebsd.org/D19874
This commit is contained in:
Edward Tomasz Napierala 2019-04-11 11:21:45 +00:00
parent f1ef572a1e
commit 4033ecc915

View File

@ -716,7 +716,7 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
struct nameidata *nd;
struct vattr *attr;
struct image_params *imgp;
u_long rbase;
u_long flags, rbase;
u_long base_addr = 0;
int error;
@ -744,7 +744,10 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
imgp->object = NULL;
imgp->execlabel = NULL;
NDINIT(nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, curthread);
flags = FOLLOW | LOCKSHARED | LOCKLEAF;
again:
NDINIT(nd, LOOKUP, flags, UIO_SYSSPACE, file, curthread);
if ((error = namei(nd)) != 0) {
nd->ni_vp = NULL;
goto fail;
@ -759,16 +762,31 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
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 almost always
* already set.
*/
if (VOP_IS_TEXT(nd->ni_vp) == 0) {
if (VOP_ISLOCKED(nd->ni_vp) != LK_EXCLUSIVE) {
/*
* LK_UPGRADE could have resulted in dropping
* the lock. Just try again from the start,
* this time with exclusive vnode lock.
*/
vput(nd->ni_vp);
flags &= ~LOCKSHARED;
goto again;
}
VOP_SET_TEXT(nd->ni_vp);
}
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;
hdr = (const Elf_Ehdr *)imgp->image_header;