1 /* $OpenBSD: procfs_mem.c,v 1.22 2004/05/20 09:20:41 kettenis Exp $ */
2 /* $NetBSD: procfs_mem.c,v 1.8 1996/02/09 22:40:50 christos Exp $ */
3
4 /*
5 * Copyright (c) 1993 Jan-Simon Pendry
6 * Copyright (c) 1993 Sean Eric Fagan
7 * Copyright (c) 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry and Sean Eric Fagan.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
38 */
39
40 /*
41 * This is a lightly hacked and merged version
42 * of sef's pread/pwrite functions
43 */
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/time.h>
48 #include <sys/kernel.h>
49 #include <sys/proc.h>
50 #include <sys/vnode.h>
51 #include <miscfs/procfs/procfs.h>
52
53 #include <uvm/uvm_extern.h>
54
55 /*
56 * Copy data in and out of the target process.
57 * We do this by mapping the process's page into
58 * the kernel and then doing a uiomove direct
59 * from the kernel address space.
60 */
61 int
procfs_domem(curp,p,pfs,uio)62 procfs_domem(curp, p, pfs, uio)
63 struct proc *curp; /* tracer */
64 struct proc *p; /* traced */
65 struct pfsnode *pfs;
66 struct uio *uio;
67 {
68 int error;
69 vaddr_t addr;
70 vsize_t len;
71
72 len = uio->uio_resid;
73 if (len == 0)
74 return (0);
75
76 if ((error = procfs_checkioperm(curp, p)) != 0)
77 return (error);
78
79 /* XXXCDC: how should locking work here? */
80 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1))
81 return(EFAULT);
82 addr = uio->uio_offset;
83 p->p_vmspace->vm_refcnt++; /* XXX */
84 error = uvm_io(&p->p_vmspace->vm_map, uio);
85 uvmspace_free(p->p_vmspace);
86
87 if (error == 0 && uio->uio_rw == UIO_WRITE)
88 pmap_proc_iflush(p, addr, len);
89
90 return error;
91 }
92
93 /*
94 * Ensure that a process has permission to perform I/O on another.
95 * Arguments:
96 * p The process wishing to do the I/O (the tracer).
97 * t The process who's memory/registers will be read/written.
98 *
99 * You cannot attach to a process's mem/regs if:
100 *
101 * (1) It's not owned by you, or the last exec
102 * gave us setuid/setgid privs (unless
103 * you're root), or...
104 *
105 * (2) It's init, which controls the security level
106 * of the entire system, and the system was not
107 * compiled with permanently insecure mode turned
108 * on.
109 *
110 * (3) It's currently execing.
111 */
112 int
procfs_checkioperm(p,t)113 procfs_checkioperm(p, t)
114 struct proc *p, *t;
115 {
116 int error;
117
118 if ((t->p_cred->p_ruid != p->p_cred->p_ruid ||
119 ISSET(t->p_flag, P_SUGIDEXEC) ||
120 ISSET(t->p_flag, P_SUGID)) &&
121 (error = suser(p, 0)) != 0)
122 return (error);
123
124 if ((t->p_pid == 1) && (securelevel > -1))
125 return (EPERM);
126
127 if (t->p_flag & P_INEXEC)
128 return (EAGAIN);
129
130 return (0);
131 }
132