Fix the NFS client for "text file modified, process killed" mmap'd case.

When an mmap'd text file is written and then executed immediately
afterwards, it was possible that the modify time would change after the
text file was executing, resulting in the process executing the file
being killed. This was usually only observed when the file system's
times were set to higher resolution, but could have occurred for any
time resolution.
This was reported on a recent email list discussion.
This patch adds a VOP_SET_TEXT() to the NFS client which flushed all
dirty pages to the NFS server and then makes sure that n_mtime is up
to date to avoid this from occurring.
Thanks go to kib@ and pho@ for their help with developing this patch.

Tested by:	pho
Reviewed by:	kib
MFC after:	2 weeks
This commit is contained in:
Rick Macklem
2017-04-12 21:37:12 +00:00
parent a9250603fd
commit 0649fcaea5
+35
View File
@@ -140,6 +140,7 @@ static vop_advlock_t nfs_advlock;
static vop_advlockasync_t nfs_advlockasync;
static vop_getacl_t nfs_getacl;
static vop_setacl_t nfs_setacl;
static vop_set_text_t nfs_set_text;
/*
* Global vfs data structures for nfs
@@ -176,6 +177,7 @@ struct vop_vector newnfs_vnodeops = {
.vop_write = ncl_write,
.vop_getacl = nfs_getacl,
.vop_setacl = nfs_setacl,
.vop_set_text = nfs_set_text,
};
struct vop_vector newnfs_fifoops = {
@@ -3381,6 +3383,39 @@ nfs_setacl(struct vop_setacl_args *ap)
return (error);
}
static int
nfs_set_text(struct vop_set_text_args *ap)
{
struct vnode *vp = ap->a_vp;
struct nfsnode *np;
/*
* If the text file has been mmap'd, flush any dirty pages to the
* buffer cache and then...
* Make sure all writes are pushed to the NFS server. If this is not
* done, the modify time of the file can change while the text
* file is being executed. This will cause the process that is
* executing the text file to be terminated.
*/
if (vp->v_object != NULL) {
VM_OBJECT_WLOCK(vp->v_object);
vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
VM_OBJECT_WUNLOCK(vp->v_object);
}
/* Now, flush the buffer cache. */
ncl_flush(vp, MNT_WAIT, NULL, curthread, 0, 0);
/* And, finally, make sure that n_mtime is up to date. */
np = VTONFS(vp);
mtx_lock(&np->n_mtx);
np->n_mtime = np->n_vattr.na_mtime;
mtx_unlock(&np->n_mtx);
vp->v_vflag |= VV_TEXT;
return (0);
}
/*
* Return POSIX pathconf information applicable to nfs filesystems.
*/