aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/imgact_aout.c
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2019-05-05 11:20:43 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2019-05-05 11:20:43 +0000
commit78022527bb7aad6015ea88102562ad6ede2752fa (patch)
treeaa5f2c3500763d961ae6e99d0d1ef55d30dd62de /sys/kern/imgact_aout.c
parent7f1446052fd7ff1006f9a98a76f8b1010e4e413e (diff)
downloadsrc-78022527bb7aad6015ea88102562ad6ede2752fa.tar.gz
src-78022527bb7aad6015ea88102562ad6ede2752fa.zip
Switch to use shared vnode locks for text files during image activation.
kern_execve() locks text vnode exclusive to be able to set and clear VV_TEXT flag. VV_TEXT is mutually exclusive with the v_writecount > 0 condition. The change removes VV_TEXT, replacing it with the condition v_writecount <= -1, and puts v_writecount under the vnode interlock. Each text reference decrements v_writecount. To clear the text reference when the segment is unmapped, it is recorded in the vm_map_entry backed by the text file as MAP_ENTRY_VN_TEXT flag, and v_writecount is incremented on the map entry removal The operations like VOP_ADD_WRITECOUNT() and VOP_SET_TEXT() check that v_writecount does not contradict the desired change. vn_writecheck() is now racy and its use was eliminated everywhere except access. Atomic check for writeability and increment of v_writecount is performed by the VOP. vn_truncate() now increments v_writecount around VOP_SETATTR() call, lack of which is arguably a bug on its own. nullfs bypasses v_writecount to the lower vnode always, so nullfs vnode has its own v_writecount correct, and lower vnode gets all references, since object->handle is always lower vnode. On the text vnode' vm object dealloc, the v_writecount value is reset to zero, and deadfs vop_unset_text short-circuit the operation. Reclamation of lowervp always reclaims all nullfs vnodes referencing lowervp first, so no stray references are left. Reviewed by: markj, trasz Tested by: mjg, pho Sponsored by: The FreeBSD Foundation MFC after: 1 month Differential revision: https://reviews.freebsd.org/D19923
Notes
Notes: svn path=/head/; revision=347151
Diffstat (limited to 'sys/kern/imgact_aout.c')
-rw-r--r--sys/kern/imgact_aout.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index c8989fd55c74..0ca39b69d908 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -247,8 +247,8 @@ exec_aout_imgact(struct image_params *imgp)
/* data + bss can't exceed rlimit */
a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) ||
racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) {
- PROC_UNLOCK(imgp->proc);
- return (ENOMEM);
+ PROC_UNLOCK(imgp->proc);
+ return (ENOMEM);
}
PROC_UNLOCK(imgp->proc);
@@ -267,7 +267,7 @@ exec_aout_imgact(struct image_params *imgp)
*/
error = exec_new_vmspace(imgp, &aout_sysvec);
- vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
if (error)
return (error);
@@ -286,12 +286,13 @@ exec_aout_imgact(struct image_params *imgp)
file_offset,
virtual_offset, text_end,
VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL,
- MAP_COPY_ON_WRITE | MAP_PREFAULT);
+ MAP_COPY_ON_WRITE | MAP_PREFAULT | MAP_VN_EXEC);
if (error) {
vm_map_unlock(map);
vm_object_deallocate(object);
return (error);
}
+ VOP_SET_TEXT_CHECKED(imgp->vp);
data_end = text_end + a_out->a_data;
if (a_out->a_data) {
vm_object_reference(object);
@@ -299,12 +300,13 @@ exec_aout_imgact(struct image_params *imgp)
file_offset + a_out->a_text,
text_end, data_end,
VM_PROT_ALL, VM_PROT_ALL,
- MAP_COPY_ON_WRITE | MAP_PREFAULT);
+ MAP_COPY_ON_WRITE | MAP_PREFAULT | MAP_VN_EXEC);
if (error) {
vm_map_unlock(map);
vm_object_deallocate(object);
return (error);
}
+ VOP_SET_TEXT_CHECKED(imgp->vp);
}
if (bss_size) {