netmap: fix issues in nm_os_extmem_create()

- Call vm_object_reference() before vm_map_lookup_done().
- Use vm_mmap_to_errno() to convert vm_map_* return values to errno.
- Fix memory leak of e->obj.

Reported by:	markj
Reviewed by:	markj
MFC after:	1 week
This commit is contained in:
Vincenzo Maffione 2021-03-20 17:15:50 +00:00
parent 8c9e45503f
commit ee7ffaa2e6

View File

@ -664,6 +664,7 @@ nm_os_vi_detach(struct ifnet *ifp)
#ifdef WITH_EXTMEM #ifdef WITH_EXTMEM
#include <vm/vm_map.h> #include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h> #include <vm/vm_kern.h>
struct nm_os_extmem { struct nm_os_extmem {
vm_object_t obj; vm_object_t obj;
@ -726,17 +727,18 @@ nm_os_extmem_create(unsigned long p, struct nmreq_pools_info *pi, int *perror)
&obj, &index, &prot, &wired); &obj, &index, &prot, &wired);
if (rv != KERN_SUCCESS) { if (rv != KERN_SUCCESS) {
nm_prerr("address %lx not found", p); nm_prerr("address %lx not found", p);
error = vm_mmap_to_errno(rv);
goto out_free; goto out_free;
} }
vm_object_reference(obj);
/* check that we are given the whole vm_object ? */ /* check that we are given the whole vm_object ? */
vm_map_lookup_done(map, entry); vm_map_lookup_done(map, entry);
// XXX can we really use obj after releasing the map lock?
e->obj = obj; e->obj = obj;
vm_object_reference(obj); /* Wire the memory and add the vm_object to the kernel map,
/* wire the memory and add the vm_object to the kernel map, * to make sure that it is not freed even if all the processes
* to make sure that it is not fred even if the processes that * that are mmap()ing should munmap() it.
* are mmap()ing it all exit
*/ */
e->kva = vm_map_min(kernel_map); e->kva = vm_map_min(kernel_map);
e->size = obj->size << PAGE_SHIFT; e->size = obj->size << PAGE_SHIFT;
@ -745,12 +747,14 @@ nm_os_extmem_create(unsigned long p, struct nmreq_pools_info *pi, int *perror)
VM_PROT_READ | VM_PROT_WRITE, 0); VM_PROT_READ | VM_PROT_WRITE, 0);
if (rv != KERN_SUCCESS) { if (rv != KERN_SUCCESS) {
nm_prerr("vm_map_find(%zx) failed", (size_t)e->size); nm_prerr("vm_map_find(%zx) failed", (size_t)e->size);
error = vm_mmap_to_errno(rv);
goto out_rel; goto out_rel;
} }
rv = vm_map_wire(kernel_map, e->kva, e->kva + e->size, rv = vm_map_wire(kernel_map, e->kva, e->kva + e->size,
VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES); VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
if (rv != KERN_SUCCESS) { if (rv != KERN_SUCCESS) {
nm_prerr("vm_map_wire failed"); nm_prerr("vm_map_wire failed");
error = vm_mmap_to_errno(rv);
goto out_rem; goto out_rem;
} }
@ -760,9 +764,9 @@ nm_os_extmem_create(unsigned long p, struct nmreq_pools_info *pi, int *perror)
out_rem: out_rem:
vm_map_remove(kernel_map, e->kva, e->kva + e->size); vm_map_remove(kernel_map, e->kva, e->kva + e->size);
e->obj = NULL;
out_rel: out_rel:
vm_object_deallocate(e->obj); vm_object_deallocate(e->obj);
e->obj = NULL;
out_free: out_free:
nm_os_free(e); nm_os_free(e);
out: out: