Change the linprocfs <pid>/maps and procfs <pid>/map handlers to use

sbuf instead of doing uiomove. This allows for reads from non-zero
offsets to work.

Patch is forward-ported des@' one, and was adopted to current code
by dchagin@ and me.

Reviewed by:	des (linprocfs part)
PR:	kern/101453
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2008-10-04 14:08:16 +00:00
parent 0258b0bc1b
commit 9a1e630dfd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=183600
2 changed files with 12 additions and 58 deletions

View File

@ -872,16 +872,13 @@ linprocfs_doprocenviron(PFS_FILL_ARGS)
static int
linprocfs_doprocmaps(PFS_FILL_ARGS)
{
char mebuffer[512];
vm_map_t map = &p->p_vmspace->vm_map;
vm_map_entry_t entry, tmp_entry;
vm_map_entry_t entry;
vm_object_t obj, tobj, lobj;
vm_offset_t saved_end;
vm_ooffset_t off = 0;
char *name = "", *freename = NULL;
size_t len;
ino_t ino;
unsigned int last_timestamp;
int ref_count, shadow_count, flags;
int error;
struct vnode *vp;
@ -897,13 +894,9 @@ linprocfs_doprocmaps(PFS_FILL_ARGS)
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
if (uio->uio_offset != 0)
return (0);
error = 0;
vm_map_lock_read(map);
for (entry = map->header.next;
((uio->uio_resid > 0) && (entry != &map->header));
for (entry = map->header.next; entry != &map->header;
entry = entry->next) {
name = "";
freename = NULL;
@ -952,7 +945,7 @@ linprocfs_doprocmaps(PFS_FILL_ARGS)
* format:
* start, end, access, offset, major, minor, inode, name.
*/
snprintf(mebuffer, sizeof mebuffer,
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":"-",
@ -968,26 +961,9 @@ linprocfs_doprocmaps(PFS_FILL_ARGS)
);
if (freename)
free(freename, M_TEMP);
len = strlen(mebuffer);
if (len > uio->uio_resid)
len = uio->uio_resid; /*
* XXX We should probably return
* EFBIG here, as in procfs.
*/
last_timestamp = map->timestamp;
vm_map_unlock_read(map);
error = uiomove(mebuffer, len, uio);
vm_map_lock_read(map);
if (error)
if (error == -1) {
error = 0;
break;
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, saved_end - 1, &tmp_entry);
entry = tmp_entry;
}
}
vm_map_unlock_read(map);

View File

@ -45,6 +45,7 @@
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/uio.h>
#include <sys/vnode.h>
@ -81,14 +82,11 @@ extern struct sysentvec ia32_freebsd_sysvec;
int
procfs_doprocmap(PFS_FILL_ARGS)
{
int len;
int error, vfslocked;
vm_map_t map = &p->p_vmspace->vm_map;
vm_map_entry_t entry, tmp_entry;
vm_map_entry_t entry;
struct vnode *vp;
char mebuffer[MEBUFFERSIZE];
char *fullpath, *freepath;
unsigned int last_timestamp;
#ifdef COMPAT_IA32
int wrap32 = 0;
#endif
@ -102,9 +100,6 @@ procfs_doprocmap(PFS_FILL_ARGS)
if (uio->uio_rw != UIO_READ)
return (EOPNOTSUPP);
if (uio->uio_offset != 0)
return (0);
#ifdef COMPAT_IA32
if (curthread->td_proc->p_sysent == &ia32_freebsd_sysvec) {
if (p->p_sysent != &ia32_freebsd_sysvec)
@ -114,9 +109,8 @@ procfs_doprocmap(PFS_FILL_ARGS)
#endif
vm_map_lock_read(map);
for (entry = map->header.next;
((uio->uio_resid > 0) && (entry != &map->header));
entry = entry->next) {
for (entry = map->header.next; entry != &map->header;
entry = entry->next) {
vm_object_t obj, tobj, lobj;
int ref_count, shadow_count, flags;
vm_offset_t addr;
@ -198,7 +192,7 @@ procfs_doprocmap(PFS_FILL_ARGS)
* format:
* start, end, resident, private resident, cow, access, type.
*/
snprintf(mebuffer, sizeof mebuffer,
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,
resident, privateresident,
@ -218,26 +212,10 @@ procfs_doprocmap(PFS_FILL_ARGS)
if (freepath != NULL)
free(freepath, M_TEMP);
len = strlen(mebuffer);
if (len > uio->uio_resid) {
error = EFBIG;
if (error == -1) {
error = 0;
break;
}
last_timestamp = map->timestamp;
vm_map_unlock_read(map);
error = uiomove(mebuffer, len, uio);
vm_map_lock_read(map);
if (error)
break;
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, addr - 1, &tmp_entry);
entry = tmp_entry;
}
}
vm_map_unlock_read(map);
return (error);