1 /* $NetBSD: procfs_mem.c,v 1.25 2000/06/28 02:44:07 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993 Sean Eric Fagan 6 * Copyright (c) 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Jan-Simon Pendry and Sean Eric Fagan. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94 41 */ 42 43 /* 44 * This is a lightly hacked and merged version 45 * of sef's pread/pwrite functions 46 */ 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/time.h> 51 #include <sys/kernel.h> 52 #include <sys/proc.h> 53 #include <sys/vnode.h> 54 55 #include <miscfs/procfs/procfs.h> 56 57 #include <uvm/uvm_extern.h> 58 59 #define ISSET(t, f) ((t) & (f)) 60 61 /* 62 * Copy data in and out of the target process. 63 * We do this by mapping the process's page into 64 * the kernel and then doing a uiomove direct 65 * from the kernel address space. 66 */ 67 int 68 procfs_domem(curp, p, pfs, uio) 69 struct proc *curp; /* tracer */ 70 struct proc *p; /* traced */ 71 struct pfsnode *pfs; 72 struct uio *uio; 73 { 74 int error; 75 76 size_t len; 77 vaddr_t addr; 78 79 len = uio->uio_resid; 80 81 if (len == 0) 82 return (0); 83 84 addr = uio->uio_offset; 85 86 if ((error = procfs_checkioperm(curp, p)) != 0) 87 return (error); 88 89 /* XXXCDC: how should locking work here? */ 90 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 91 return(EFAULT); 92 PHOLD(p); 93 p->p_vmspace->vm_refcnt++; /* XXX */ 94 error = uvm_io(&p->p_vmspace->vm_map, uio); 95 PRELE(p); 96 uvmspace_free(p->p_vmspace); 97 98 #ifdef PMAP_NEED_PROCWR 99 if (uio->uio_rw == UIO_WRITE) 100 pmap_procwr(p, addr, len); 101 #endif 102 return (error); 103 } 104 105 /* 106 * Given process (p), find the vnode from which 107 * it's text segment is being executed. 108 * 109 * It would be nice to grab this information from 110 * the VM system, however, there is no sure-fire 111 * way of doing that. Instead, fork(), exec() and 112 * wait() all maintain the p_textvp field in the 113 * process proc structure which contains a held 114 * reference to the exec'ed vnode. 115 */ 116 struct vnode * 117 procfs_findtextvp(p) 118 struct proc *p; 119 { 120 121 return (p->p_textvp); 122 } 123 124 /* 125 * Ensure that a process has permission to perform I/O on another. 126 * Arguments: 127 * p The process wishing to do the I/O (the tracer). 128 * t The process who's memory/registers will be read/written. 129 */ 130 int 131 procfs_checkioperm(p, t) 132 struct proc *p, *t; 133 { 134 int error; 135 136 /* 137 * You cannot attach to a processes mem/regs if: 138 * 139 * (1) it's not owned by you, or is set-id on exec 140 * (unless you're root), or... 141 */ 142 if ((t->p_cred->p_ruid != p->p_cred->p_ruid || 143 ISSET(t->p_flag, P_SUGID)) && 144 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 145 return (error); 146 147 /* 148 * (2) ...it's init, which controls the security level 149 * of the entire system, and the system was not 150 * compiled with permanetly insecure mode turned on. 151 */ 152 if (t == initproc && securelevel > -1) 153 return (EPERM); 154 155 /* 156 * (3) the tracer is chrooted, and its root directory is 157 * not at or above the root directory of the tracee 158 */ 159 160 if (!proc_isunder(t, p)) 161 return EPERM; 162 163 return (0); 164 } 165 166 #ifdef probably_never 167 /* 168 * Given process (p), find the vnode from which 169 * it's text segment is being mapped. 170 * 171 * (This is here, rather than in procfs_subr in order 172 * to keep all the VM related code in one place.) 173 */ 174 struct vnode * 175 procfs_findtextvp(p) 176 struct proc *p; 177 { 178 int error; 179 vm_object_t object; 180 vaddr_t pageno; /* page number */ 181 182 /* find a vnode pager for the user address space */ 183 184 for (pageno = VM_MIN_ADDRESS; 185 pageno < VM_MAXUSER_ADDRESS; 186 pageno += PAGE_SIZE) { 187 vm_map_t map; 188 vm_map_entry_t out_entry; 189 vm_prot_t out_prot; 190 boolean_t wired, single_use; 191 vaddr_t off; 192 193 map = &p->p_vmspace->vm_map; 194 error = vm_map_lookup(&map, pageno, 195 VM_PROT_READ, 196 &out_entry, &object, &off, &out_prot, 197 &wired, &single_use); 198 199 if (!error) { 200 vm_pager_t pager; 201 202 printf("procfs: found vm object\n"); 203 vm_map_lookup_done(map, out_entry); 204 printf("procfs: vm object = %p\n", object); 205 206 /* 207 * At this point, assuming no errors, object 208 * is the VM object mapping UVA (pageno). 209 * Ensure it has a vnode pager, then grab 210 * the vnode from that pager's handle. 211 */ 212 213 pager = object->pager; 214 printf("procfs: pager = %p\n", pager); 215 if (pager) 216 printf("procfs: found pager, type = %d\n", 217 pager->pg_type); 218 if (pager && pager->pg_type == PG_VNODE) { 219 struct vnode *vp; 220 221 vp = (struct vnode *) pager->pg_handle; 222 printf("procfs: vp = %p\n", vp); 223 return (vp); 224 } 225 } 226 } 227 228 printf("procfs: text object not found\n"); 229 return (0); 230 } 231 #endif /* probably_never */ 232