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