diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 9b6880d..ac912b2 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -876,10 +876,12 @@ static int linprocfs_doprocmaps(PFS_FILL_ARGS) { vm_map_t map = &p->p_vmspace->vm_map; - vm_map_entry_t entry; + vm_map_entry_t entry, tmp_entry; vm_object_t obj, tobj, lobj; - vm_offset_t saved_end; + vm_offset_t e_start, e_end; vm_ooffset_t off = 0; + vm_prot_t e_prot; + unsigned int last_timestamp; char *name = "", *freename = NULL; ino_t ino; int ref_count, shadow_count, flags; @@ -905,7 +907,9 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) freename = NULL; if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) continue; - saved_end = entry->end; + e_prot = entry->protection; + e_start = entry->start; + e_end = entry->end; obj = entry->object.vm_object; for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { VM_OBJECT_LOCK(tobj); @@ -913,6 +917,8 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) VM_OBJECT_UNLOCK(lobj); lobj = tobj; } + last_timestamp = map->timestamp; + vm_map_unlock_read(map); ino = 0; if (lobj) { off = IDX_TO_OFF(lobj->size); @@ -950,10 +956,10 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) */ error = sbuf_printf(sb, "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", - (u_long)entry->start, (u_long)entry->end, - (entry->protection & VM_PROT_READ)?"r":"-", - (entry->protection & VM_PROT_WRITE)?"w":"-", - (entry->protection & VM_PROT_EXECUTE)?"x":"-", + (u_long)e_start, (u_long)e_end, + (e_prot & VM_PROT_READ)?"r":"-", + (e_prot & VM_PROT_WRITE)?"w":"-", + (e_prot & VM_PROT_EXECUTE)?"x":"-", "p", (u_long)off, 0, @@ -968,6 +974,16 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) error = 0; break; } + vm_map_lock_read(map); + if (last_timestamp + 1 != map->timestamp) { + /* + * Look again for the entry because the map was + * modified while it was unlocked. Specifically, + * the entry may have been clipped, merged, or deleted. + */ + vm_map_lookup_entry(map, e_end - 1, &tmp_entry); + entry = tmp_entry; + } } vm_map_unlock_read(map); diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c index 0c671b4..11aa713 100644 --- a/sys/fs/procfs/procfs_map.c +++ b/sys/fs/procfs/procfs_map.c @@ -84,9 +84,10 @@ procfs_doprocmap(PFS_FILL_ARGS) { int error, vfslocked; vm_map_t map = &p->p_vmspace->vm_map; - vm_map_entry_t entry; + vm_map_entry_t entry, tmp_entry; struct vnode *vp; char *fullpath, *freepath; + unsigned int last_timestamp; #ifdef COMPAT_IA32 int wrap32 = 0; #endif @@ -113,13 +114,19 @@ procfs_doprocmap(PFS_FILL_ARGS) entry = entry->next) { vm_object_t obj, tobj, lobj; int ref_count, shadow_count, flags; - vm_offset_t addr; + vm_offset_t e_start, e_end, addr; int resident, privateresident; char *type; + vm_eflags_t e_eflags; + vm_prot_t e_prot; if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) continue; + e_eflags = entry->eflags; + e_prot = entry->protection; + e_start = entry->start; + e_end = entry->end; privateresident = 0; obj = entry->object.vm_object; if (obj != NULL) { @@ -143,11 +150,13 @@ procfs_doprocmap(PFS_FILL_ARGS) VM_OBJECT_UNLOCK(lobj); lobj = tobj; } + last_timestamp = map->timestamp; + vm_map_unlock_read(map); freepath = NULL; fullpath = "-"; if (lobj) { - switch(lobj->type) { + switch (lobj->type) { default: case OBJT_DEFAULT: type = "default"; @@ -193,19 +202,19 @@ procfs_doprocmap(PFS_FILL_ARGS) */ error = sbuf_printf(sb, "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s %s\n", - (u_long)entry->start, (u_long)entry->end, + (u_long)e_start, (u_long)e_end, resident, privateresident, #ifdef COMPAT_IA32 wrap32 ? NULL : obj, /* Hide 64 bit value */ #else obj, #endif - (entry->protection & VM_PROT_READ)?"r":"-", - (entry->protection & VM_PROT_WRITE)?"w":"-", - (entry->protection & VM_PROT_EXECUTE)?"x":"-", + (e_prot & VM_PROT_READ)?"r":"-", + (e_prot & VM_PROT_WRITE)?"w":"-", + (e_prot & VM_PROT_EXECUTE)?"x":"-", ref_count, shadow_count, flags, - (entry->eflags & MAP_ENTRY_COW)?"COW":"NCOW", - (entry->eflags & MAP_ENTRY_NEEDS_COPY)?"NC":"NNC", + (e_eflags & MAP_ENTRY_COW)?"COW":"NCOW", + (e_eflags & MAP_ENTRY_NEEDS_COPY)?"NC":"NNC", type, fullpath); if (freepath != NULL) @@ -215,6 +224,16 @@ procfs_doprocmap(PFS_FILL_ARGS) error = 0; break; } + vm_map_lock_read(map); + if (last_timestamp + 1 != map->timestamp) { + /* + * Look again for the entry because the map was + * modified while it was unlocked. Specifically, + * the entry may have been clipped, merged, or deleted. + */ + vm_map_lookup_entry(map, e_end - 1, &tmp_entry); + entry = tmp_entry; + } } vm_map_unlock_read(map); return (error); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 0b6b6d5..9f42891 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1412,13 +1412,32 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) lobj = tobj; } + kve->kve_start = (void*)entry->start; + kve->kve_end = (void*)entry->end; + kve->kve_offset = (off_t)entry->offset; + + if (entry->protection & VM_PROT_READ) + kve->kve_protection |= KVME_PROT_READ; + if (entry->protection & VM_PROT_WRITE) + kve->kve_protection |= KVME_PROT_WRITE; + if (entry->protection & VM_PROT_EXECUTE) + kve->kve_protection |= KVME_PROT_EXEC; + + if (entry->eflags & MAP_ENTRY_COW) + kve->kve_flags |= KVME_FLAG_COW; + if (entry->eflags & MAP_ENTRY_NEEDS_COPY) + kve->kve_flags |= KVME_FLAG_NEEDS_COPY; + + last_timestamp = map->timestamp; + vm_map_unlock_read(map); + kve->kve_fileid = 0; kve->kve_fsid = 0; freepath = NULL; fullpath = ""; if (lobj) { vp = NULL; - switch(lobj->type) { + switch (lobj->type) { case OBJT_DEFAULT: kve->kve_type = KVME_TYPE_DEFAULT; break; @@ -1468,28 +1487,10 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) kve->kve_shadow_count = 0; } - kve->kve_start = (void*)entry->start; - kve->kve_end = (void*)entry->end; - kve->kve_offset = (off_t)entry->offset; - - if (entry->protection & VM_PROT_READ) - kve->kve_protection |= KVME_PROT_READ; - if (entry->protection & VM_PROT_WRITE) - kve->kve_protection |= KVME_PROT_WRITE; - if (entry->protection & VM_PROT_EXECUTE) - kve->kve_protection |= KVME_PROT_EXEC; - - if (entry->eflags & MAP_ENTRY_COW) - kve->kve_flags |= KVME_FLAG_COW; - if (entry->eflags & MAP_ENTRY_NEEDS_COPY) - kve->kve_flags |= KVME_FLAG_NEEDS_COPY; - strlcpy(kve->kve_path, fullpath, sizeof(kve->kve_path)); if (freepath != NULL) free(freepath, M_TEMP); - last_timestamp = map->timestamp; - vm_map_unlock_read(map); error = SYSCTL_OUT(req, kve, sizeof(*kve)); vm_map_lock_read(map); if (error) @@ -1577,13 +1578,32 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) lobj = tobj; } + kve->kve_start = entry->start; + kve->kve_end = entry->end; + kve->kve_offset = entry->offset; + + if (entry->protection & VM_PROT_READ) + kve->kve_protection |= KVME_PROT_READ; + if (entry->protection & VM_PROT_WRITE) + kve->kve_protection |= KVME_PROT_WRITE; + if (entry->protection & VM_PROT_EXECUTE) + kve->kve_protection |= KVME_PROT_EXEC; + + if (entry->eflags & MAP_ENTRY_COW) + kve->kve_flags |= KVME_FLAG_COW; + if (entry->eflags & MAP_ENTRY_NEEDS_COPY) + kve->kve_flags |= KVME_FLAG_NEEDS_COPY; + + last_timestamp = map->timestamp; + vm_map_unlock_read(map); + kve->kve_fileid = 0; kve->kve_fsid = 0; freepath = NULL; fullpath = ""; if (lobj) { vp = NULL; - switch(lobj->type) { + switch (lobj->type) { case OBJT_DEFAULT: kve->kve_type = KVME_TYPE_DEFAULT; break; @@ -1633,28 +1653,10 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) kve->kve_shadow_count = 0; } - kve->kve_start = entry->start; - kve->kve_end = entry->end; - kve->kve_offset = entry->offset; - - if (entry->protection & VM_PROT_READ) - kve->kve_protection |= KVME_PROT_READ; - if (entry->protection & VM_PROT_WRITE) - kve->kve_protection |= KVME_PROT_WRITE; - if (entry->protection & VM_PROT_EXECUTE) - kve->kve_protection |= KVME_PROT_EXEC; - - if (entry->eflags & MAP_ENTRY_COW) - kve->kve_flags |= KVME_FLAG_COW; - if (entry->eflags & MAP_ENTRY_NEEDS_COPY) - kve->kve_flags |= KVME_FLAG_NEEDS_COPY; - strlcpy(kve->kve_path, fullpath, sizeof(kve->kve_path)); if (freepath != NULL) free(freepath, M_TEMP); - last_timestamp = map->timestamp; - vm_map_unlock_read(map); /* Pack record size down */ kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) + strlen(kve->kve_path) + 1;