1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2001 Dag-Erling Coïdan Smørgrav
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD$
31 */
32
33 #include <sys/param.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/pioctl.h>
37 #include <sys/priv.h>
38 #include <sys/proc.h>
39 #include <sys/signalvar.h>
40 #include <sys/systm.h>
41
42 #include <fs/pseudofs/pseudofs.h>
43 #include <fs/procfs/procfs.h>
44
45 #ifdef COMPAT_FREEBSD32
46 struct procfs_status32 {
47 int state; /* Running, stopped, something else? */
48 int flags; /* Any flags */
49 unsigned int events; /* Events to stop on */
50 int why; /* What event, if any, proc stopped on */
51 unsigned int val; /* Any extra data */
52 };
53
54 #define PIOCWAIT32 _IOR('p', 4, struct procfs_status32)
55 #define PIOCSTATUS32 _IOR('p', 6, struct procfs_status32)
56 #endif
57
58 /*
59 * Process ioctls
60 */
61 int
62 procfs_ioctl(PFS_IOCTL_ARGS)
63 {
64 struct procfs_status *ps;
65 #ifdef COMPAT_FREEBSD32
66 struct procfs_status32 *ps32;
67 #endif
68 int error, flags, sig;
69 #ifdef COMPAT_FREEBSD6
70 int ival;
71 #endif
72 static struct timeval lasttime;
73 static struct timeval interval = { .tv_sec = 1, .tv_usec = 0 };
74
75 KASSERT(p != NULL,
76 ("%s() called without a process", __func__));
77 PROC_LOCK_ASSERT(p, MA_OWNED);
78
79 switch (cmd) {
80 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
81 case _IOC(IOC_IN, 'p', 1, 0):
82 #endif
83 #ifdef COMPAT_FREEBSD6
84 case _IO('p', 1):
85 #endif
86 case PIOCBIS:
87 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
88 case _IOC(IOC_IN, 'p', 2, 0):
89 #endif
90 #ifdef COMPAT_FREEBSD6
91 case _IO('p', 2):
92 #endif
93 case PIOCBIC:
94 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
95 case _IOC(IOC_IN, 'p', 3, 0):
96 #endif
97 #ifdef COMPAT_FREEBSD6
98 case _IO('p', 3):
99 #endif
100 case PIOCSFL:
101 case PIOCGFL:
102 case PIOCWAIT:
103 case PIOCSTATUS:
104 #ifdef COMPAT_FREEBSD32
105 case PIOCWAIT32:
106 case PIOCSTATUS32:
107 #endif
108 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
109 case _IOC(IOC_IN, 'p', 5, 0):
110 #endif
111 #ifdef COMPAT_FREEBSD6
112 case _IO('p', 5):
113 #endif
114 case PIOCCONT:
115 if (ratecheck(&lasttime, &interval) != 0)
116 gone_in(13, "procfs-based process debugging");
117 break;
118 }
119
120 error = 0;
121 switch (cmd) {
122 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
123 case _IOC(IOC_IN, 'p', 1, 0):
124 #endif
125 #ifdef COMPAT_FREEBSD6
126 case _IO('p', 1):
127 ival = IOCPARM_IVAL(data);
128 data = &ival;
129 #endif
130 case PIOCBIS:
131 p->p_stops |= *(unsigned int *)data;
132 break;
133 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
134 case _IOC(IOC_IN, 'p', 2, 0):
135 #endif
136 #ifdef COMPAT_FREEBSD6
137 case _IO('p', 2):
138 ival = IOCPARM_IVAL(data);
139 data = &ival;
140 #endif
141 case PIOCBIC:
142 p->p_stops &= ~*(unsigned int *)data;
143 break;
144 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
145 case _IOC(IOC_IN, 'p', 3, 0):
146 #endif
147 #ifdef COMPAT_FREEBSD6
148 case _IO('p', 3):
149 ival = IOCPARM_IVAL(data);
150 data = &ival;
151 #endif
152 case PIOCSFL:
153 flags = *(unsigned int *)data;
154 if (flags & PF_ISUGID) {
155 /*
156 * XXXRW: Is this specific check required here, as
157 * p_candebug() should implement it, or other checks
158 * are missing.
159 */
160 error = priv_check(td, PRIV_DEBUG_SUGID);
161 if (error)
162 break;
163 }
164 p->p_pfsflags = flags;
165 break;
166 case PIOCGFL:
167 *(unsigned int *)data = p->p_pfsflags;
168 break;
169 case PIOCWAIT:
170 while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) {
171 /* sleep until p stops */
172 _PHOLD(p);
173 error = msleep(&p->p_stype, &p->p_mtx,
174 PWAIT|PCATCH, "pioctl", 0);
175 _PRELE(p);
176 if (error != 0)
177 break;
178 }
179 /* fall through to PIOCSTATUS */
180 case PIOCSTATUS:
181 ps = (struct procfs_status *)data;
182 ps->state = (p->p_step == 0);
183 ps->flags = 0; /* nope */
184 ps->events = p->p_stops;
185 ps->why = p->p_step ? p->p_stype : 0;
186 ps->val = p->p_step ? p->p_xsig : 0;
187 break;
188 #ifdef COMPAT_FREEBSD32
189 case PIOCWAIT32:
190 while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) {
191 /* sleep until p stops */
192 _PHOLD(p);
193 error = msleep(&p->p_stype, &p->p_mtx,
194 PWAIT|PCATCH, "pioctl", 0);
195 _PRELE(p);
196 if (error != 0)
197 break;
198 }
199 /* fall through to PIOCSTATUS32 */
200 case PIOCSTATUS32:
201 ps32 = (struct procfs_status32 *)data;
202 ps32->state = (p->p_step == 0);
203 ps32->flags = 0; /* nope */
204 ps32->events = p->p_stops;
205 ps32->why = p->p_step ? p->p_stype : 0;
206 ps32->val = p->p_step ? p->p_xsig : 0;
207 break;
208 #endif
209 #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
210 case _IOC(IOC_IN, 'p', 5, 0):
211 #endif
212 #ifdef COMPAT_FREEBSD6
213 case _IO('p', 5):
214 ival = IOCPARM_IVAL(data);
215 data = &ival;
216 #endif
217 case PIOCCONT:
218 if (p->p_step == 0)
219 break;
220 sig = *(unsigned int *)data;
221 if (sig != 0 && !_SIG_VALID(sig)) {
222 error = EINVAL;
223 break;
224 }
225 #if 0
226 p->p_step = 0;
227 if (P_SHOULDSTOP(p)) {
228 p->p_xsig = sig;
229 p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG);
230 PROC_SLOCK(p);
231 thread_unsuspend(p);
232 PROC_SUNLOCK(p);
233 } else if (sig)
234 kern_psignal(p, sig);
235 #else
236 if (sig)
237 kern_psignal(p, sig);
238 p->p_step = 0;
239 wakeup(&p->p_step);
240 #endif
241 break;
242 default:
243 error = (ENOTTY);
244 }
245
246 return (error);
247 }
248
249 /*
250 * Clean up on last close
251 */
252 int
253 procfs_close(PFS_CLOSE_ARGS)
254 {
255 if (p != NULL && (p->p_pfsflags & PF_LINGER) == 0) {
256 PROC_LOCK_ASSERT(p, MA_OWNED);
257 p->p_pfsflags = 0;
258 p->p_stops = 0;
259 p->p_step = 0;
260 wakeup(&p->p_step);
261 }
262 return (0);
263 }
Cache object: 1919346db7f5974bde265b0f971c2fcb
|