svn commit: r314486 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Wed Mar 1 10:22:08 UTC 2017
Author: kib
Date: Wed Mar 1 10:22:07 2017
New Revision: 314486
URL: https://svnweb.freebsd.org/changeset/base/314486
Log:
When deallocating the vm object in elf_map_insert() due to
vm_map_insert() failure, drop the vnode lock around the call to
vm_object_deallocate().
Since the deallocated object is the vm object of the vnode, we might
get the vnode lock recursion there. In fact, it is almost impossible
to make vm_map_insert() failing there on stock kernel.
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Modified:
head/sys/kern/imgact_elf.c
Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c Wed Mar 1 09:05:12 2017 (r314485)
+++ head/sys/kern/imgact_elf.c Wed Mar 1 10:22:07 2017 (r314486)
@@ -422,13 +422,14 @@ __elfN(map_partial)(vm_map_t map, vm_obj
}
static int
-__elfN(map_insert)(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
- vm_offset_t start, vm_offset_t end, vm_prot_t prot, int cow)
+__elfN(map_insert)(struct image_params *imgp, vm_map_t map, vm_object_t object,
+ vm_ooffset_t offset, vm_offset_t start, vm_offset_t end, vm_prot_t prot,
+ int cow)
{
struct sf_buf *sf;
vm_offset_t off;
vm_size_t sz;
- int error, rv;
+ int error, locked, rv;
if (start != trunc_page(start)) {
rv = __elfN(map_partial)(map, object, offset, start,
@@ -480,8 +481,12 @@ __elfN(map_insert)(vm_map_t map, vm_obje
rv = vm_map_insert(map, object, offset, start, end,
prot, VM_PROT_ALL, cow);
vm_map_unlock(map);
- if (rv != KERN_SUCCESS)
+ if (rv != KERN_SUCCESS) {
+ locked = VOP_ISLOCKED(imgp->vp);
+ VOP_UNLOCK(imgp->vp, 0);
vm_object_deallocate(object);
+ vn_lock(imgp->vp, locked | LK_RETRY);
+ }
}
return (rv);
} else {
@@ -538,7 +543,7 @@ __elfN(load_section)(struct image_params
cow = MAP_COPY_ON_WRITE | MAP_PREFAULT |
(prot & VM_PROT_WRITE ? 0 : MAP_DISABLE_COREDUMP);
- rv = __elfN(map_insert)(map,
+ rv = __elfN(map_insert)(imgp, map,
object,
file_addr, /* file offset */
map_addr, /* virtual start */
@@ -568,8 +573,8 @@ __elfN(load_section)(struct image_params
/* This had damn well better be true! */
if (map_len != 0) {
- rv = __elfN(map_insert)(map, NULL, 0, map_addr, map_addr +
- map_len, VM_PROT_ALL, 0);
+ rv = __elfN(map_insert)(imgp, map, NULL, 0, map_addr,
+ map_addr + map_len, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
return (EINVAL);
}
More information about the svn-src-all
mailing list