Date: Thu, 11 Feb 2010 18:00:54 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r203783 - in head: lib/libc/sys sys/kern sys/sys Message-ID: <201002111800.o1BI0s9k046889@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Thu Feb 11 18:00:53 2010 New Revision: 203783 URL: http://svn.freebsd.org/changeset/base/203783 Log: o Add support for COMPAT_IA32. o Incorporate review comments: - Properly reference and lock the map - Take into account that the VM map can change inbetween requests - Add the fileid and fsid attributes Credits: kib@ Reviewed by: kib@ Modified: head/lib/libc/sys/ptrace.2 head/sys/kern/sys_process.c head/sys/sys/ptrace.h Modified: head/lib/libc/sys/ptrace.2 ============================================================================== --- head/lib/libc/sys/ptrace.2 Thu Feb 11 17:30:30 2010 (r203782) +++ head/lib/libc/sys/ptrace.2 Thu Feb 11 18:00:53 2010 (r203783) @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd February 8, 2010 +.Dd February 11, 2010 .Dt PTRACE 2 .Os .Sh NAME @@ -343,23 +343,30 @@ argument specifies a pointer to a which is defined as follows: .Bd -literal struct ptrace_vm_entry { - void *pve_cookie; - u_long pve_start; - u_long pve_end; - u_long pve_offset; - u_int pve_prot; - u_int pve_pathlen; - char *pve_path; + int pve_entry; + int pve_timestamp; + u_long pve_start; + u_long pve_end; + u_long pve_offset; + u_int pve_prot; + u_int pve_pathlen; + long pve_fileid; + uint32_t pve_fsid; + char *pve_path; }; .Ed .Pp The first entry is returned by setting -.Va pve_cookie -to -.Dv NULL . +.Va pve_entry +to zero. Subsequent entries are returned by leaving -.Va pve_cookie +.Va pve_entry unmodified from the value returned by previous requests. +The +.Va pve_timestamp +field can be used to detect changes to the VM map while iterating over the +entries. +The tracing process can then take appropriate action, such as restarting. By setting .Va pve_pathlen to a non-zero value on entry, the pathname of the backing object is returned @@ -434,7 +441,8 @@ was attempted on a process with no valid .It .Dv PT_VM_ENTRY was given an invalid value for -.Fa pve_cookie . +.Fa pve_entry . +This can also be caused by changes to the VM map of the process. .El .It Bq Er EBUSY .Bl -bullet -compact Modified: head/sys/kern/sys_process.c ============================================================================== --- head/sys/kern/sys_process.c Thu Feb 11 17:30:30 2010 (r203782) +++ head/sys/kern/sys_process.c Thu Feb 11 18:00:53 2010 (r203783) @@ -75,12 +75,15 @@ struct ptrace_io_desc32 { }; struct ptrace_vm_entry32 { - uint32_t pve_cookie; + int pve_entry; + int pve_timestamp; uint32_t pve_start; uint32_t pve_end; uint32_t pve_offset; u_int pve_prot; u_int pve_pathlen; + int32_t pve_fileid; + u_int pve_fsid; uint32_t pve_path; }; @@ -360,88 +363,141 @@ proc_rwmem(struct proc *p, struct uio *u static int ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve) { + struct vattr vattr; vm_map_t map; vm_map_entry_t entry; vm_object_t obj, tobj, lobj; + struct vmspace *vm; struct vnode *vp; char *freepath, *fullpath; u_int pathlen; - int error, vfslocked; + int error, index, vfslocked; - map = &p->p_vmspace->vm_map; - entry = map->header.next; - if (pve->pve_cookie != NULL) { - while (entry != &map->header && entry != pve->pve_cookie) + error = 0; + obj = NULL; + + vm = vmspace_acquire_ref(p); + map = &vm->vm_map; + vm_map_lock_read(map); + + do { + entry = map->header.next; + index = 0; + while (index < pve->pve_entry && entry != &map->header) { entry = entry->next; - if (entry != pve->pve_cookie) - return (EINVAL); - entry = entry->next; - } - while (entry != &map->header && (entry->eflags & MAP_ENTRY_IS_SUB_MAP)) - entry = entry->next; - if (entry == &map->header) - return (ENOENT); - - /* We got an entry. */ - pve->pve_cookie = entry; - pve->pve_start = entry->start; - pve->pve_end = entry->end - 1; - pve->pve_offset = entry->offset; - pve->pve_prot = entry->protection; - - /* Backing object's path needed? */ - if (pve->pve_pathlen == 0) - return (0); - - pathlen = pve->pve_pathlen; - pve->pve_pathlen = 0; - - obj = entry->object.vm_object; - if (obj == NULL) - return (0); - - VM_OBJECT_LOCK(obj); - for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { - if (tobj != obj) - VM_OBJECT_LOCK(tobj); - if (lobj != obj) - VM_OBJECT_UNLOCK(lobj); - lobj = tobj; - pve->pve_offset += tobj->backing_object_offset; - } - if (lobj != NULL) { + index++; + } + if (index != pve->pve_entry) { + error = EINVAL; + break; + } + while (entry != &map->header && + (entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) { + entry = entry->next; + index++; + } + if (entry == &map->header) { + error = ENOENT; + break; + } + + /* We got an entry. */ + pve->pve_entry = index + 1; + pve->pve_timestamp = map->timestamp; + pve->pve_start = entry->start; + pve->pve_end = entry->end - 1; + pve->pve_offset = entry->offset; + pve->pve_prot = entry->protection; + + /* Backing object's path needed? */ + if (pve->pve_pathlen == 0) + break; + + pathlen = pve->pve_pathlen; + pve->pve_pathlen = 0; + + obj = entry->object.vm_object; + if (obj != NULL) + VM_OBJECT_LOCK(obj); + } while (0); + + vm_map_unlock_read(map); + vmspace_free(vm); + + if (error == 0 && obj != NULL) { + lobj = obj; + for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) { + if (tobj != obj) + VM_OBJECT_LOCK(tobj); + if (lobj != obj) + VM_OBJECT_UNLOCK(lobj); + lobj = tobj; + pve->pve_offset += tobj->backing_object_offset; + } vp = (lobj->type == OBJT_VNODE) ? lobj->handle : NULL; if (vp != NULL) vref(vp); if (lobj != obj) VM_OBJECT_UNLOCK(lobj); VM_OBJECT_UNLOCK(obj); - } else - vp = NULL; - if (vp == NULL) - return (0); + if (vp != NULL) { + freepath = NULL; + fullpath = NULL; + vn_fullpath(td, vp, &fullpath, &freepath); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY); + if (VOP_GETATTR(vp, &vattr, td->td_ucred) == 0) { + pve->pve_fileid = vattr.va_fileid; + pve->pve_fsid = vattr.va_fsid; + } + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); - freepath = NULL; - fullpath = NULL; - vn_fullpath(td, vp, &fullpath, &freepath); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); + if (fullpath != NULL) { + pve->pve_pathlen = strlen(fullpath) + 1; + if (pve->pve_pathlen <= pathlen) { + error = copyout(fullpath, pve->pve_path, + pve->pve_pathlen); + } else + error = ENAMETOOLONG; + } + if (freepath != NULL) + free(freepath, M_TEMP); + } + } - error = 0; - if (fullpath != NULL) { - pve->pve_pathlen = strlen(fullpath) + 1; - if (pve->pve_pathlen <= pathlen) { - error = copyout(fullpath, pve->pve_path, - pve->pve_pathlen); - } else - error = ENAMETOOLONG; + return (error); +} + +#ifdef COMPAT_IA32 +static int +ptrace_vm_entry32(struct thread *td, struct proc *p, + struct ptrace_vm_entry32 *pve32) +{ + struct ptrace_vm_entry pve; + int error; + + pve.pve_entry = pve32->pve_entry; + pve.pve_pathlen = pve32->pve_pathlen; + pve.pve_path = (void *)(uintptr_t)pve32->pve_path; + + error = ptrace_vm_entry(td, p, &pve); + if (error == 0) { + pve32->pve_entry = pve.pve_entry; + pve32->pve_timestamp = pve.pve_timestamp; + pve32->pve_start = pve.pve_start; + pve32->pve_end = pve.pve_end; + pve32->pve_offset = pve.pve_offset; + pve32->pve_prot = pve.pve_prot; + pve32->pve_fileid = pve.pve_fileid; + pve32->pve_fsid = pve.pve_fsid; } - if (freepath != NULL) - free(freepath, M_TEMP); + + pve32->pve_pathlen = pve.pve_pathlen; return (error); } +#endif /* COMPAT_IA32 */ /* * Process debugging system call. @@ -1087,14 +1143,12 @@ kern_ptrace(struct thread *td, int req, break; case PT_VM_ENTRY: + PROC_UNLOCK(p); #ifdef COMPAT_IA32 - /* XXX to be implemented. */ - if (wrap32) { - error = EDOOFUS; - break; - } + if (wrap32) + error = ptrace_vm_entry32(td, p, addr); + else #endif - PROC_UNLOCK(p); error = ptrace_vm_entry(td, p, addr); PROC_LOCK(p); break; Modified: head/sys/sys/ptrace.h ============================================================================== --- head/sys/sys/ptrace.h Thu Feb 11 17:30:30 2010 (r203782) +++ head/sys/sys/ptrace.h Thu Feb 11 18:00:53 2010 (r203783) @@ -104,13 +104,16 @@ struct ptrace_lwpinfo { /* Argument structure for PT_VM_ENTRY. */ struct ptrace_vm_entry { - void *pve_cookie; /* Token used to iterate. */ - u_long pve_start; /* Start VA of range. */ - u_long pve_end; /* End VA of range (incl). */ - u_long pve_offset; /* Offset in backing object. */ - u_int pve_prot; /* Protection of memory range. */ - u_int pve_pathlen; /* Size of path. */ - char *pve_path; /* Path name of object. */ + int pve_entry; /* Entry number used for iteration. */ + int pve_timestamp; /* Generation number of VM map. */ + u_long pve_start; /* Start VA of range. */ + u_long pve_end; /* End VA of range (incl). */ + u_long pve_offset; /* Offset in backing object. */ + u_int pve_prot; /* Protection of memory range. */ + u_int pve_pathlen; /* Size of path. */ + long pve_fileid; /* File ID. */ + uint32_t pve_fsid; /* File system ID. */ + char *pve_path; /* Path name of object. */ }; #ifdef _KERNEL
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002111800.o1BI0s9k046889>