"Fossies" - the Fresh Open Source Software Archive 
Member "reptyr-reptyr-0.8.0/platform/freebsd/freebsd.c" (29 Sep 2020, 9113 Bytes) of package /linux/privat/reptyr-reptyr-0.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "freebsd.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
0.7.0_vs_0.8.0.
1 /*
2 * Copyright (C) 2014 Christian Heckendorf <heckendorfc@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #ifdef __FreeBSD__
24
25 #include "freebsd.h"
26 #include "../platform.h"
27 #include "../../reptyr.h"
28 #include "../../ptrace.h"
29
30 void check_ptrace_scope(void) {
31 }
32
33 int check_pgroup(pid_t target) {
34 struct procstat *procstat;
35 struct kinfo_proc *kp;
36 pid_t pg;
37 unsigned int cnt;
38
39 pg = getpgid(target);
40
41 procstat = procstat_open_sysctl();
42 cnt = 0;
43 kp = procstat_getprocs(procstat, KERN_PROC_PGRP, pg, &cnt);
44 procstat_freeprocs(procstat, kp);
45 procstat_close(procstat);
46
47 if (cnt > 1) {
48 error("Process %d shares a process group with %d other processes. Unable to attach.\n", target, cnt - 1);
49 return EINVAL;
50 }
51
52 return 0;
53 }
54
55 int check_proc_stopped(pid_t pid, int fd) {
56 struct procstat *procstat;
57 struct kinfo_proc *kp;
58 int state = 0;
59 unsigned int cnt;
60
61 procstat = procstat_open_sysctl();
62 cnt = 0;
63 kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
64
65 if (cnt > 0)
66 state = kp->ki_stat;
67
68 procstat_freeprocs(procstat, kp);
69 procstat_close(procstat);
70
71 if (cnt < 1)
72 return 1;
73
74
75 if (state == SSTOP)
76 return 1;
77
78 return 0;
79 }
80
81 struct filestat_list* get_procfiles(pid_t pid, struct kinfo_proc **kp, struct procstat **procstat, unsigned int *cnt) {
82 int mflg = 0; // include mmapped files
83 (*procstat) = procstat_open_sysctl();
84 *cnt = 0;
85 (*kp) = procstat_getprocs(*procstat, KERN_PROC_PID, pid, cnt);
86 if ((*kp) == NULL || *cnt < 1)
87 return NULL;
88
89 return procstat_getfiles(*procstat, *kp, mflg);
90 }
91
92 int *get_child_tty_fds(struct ptrace_child *child, int statfd, int *count) {
93 struct filestat *fst;
94 struct filestat_list *head;
95 struct procstat *procstat;
96 struct kinfo_proc *kp;
97 unsigned int cnt;
98 struct fd_array fds = {};
99 struct vnstat vn;
100 int er;
101 char errbuf[_POSIX2_LINE_MAX];
102
103 head = get_procfiles(child->pid, &kp, &procstat, &cnt);
104
105 STAILQ_FOREACH(fst, head, next) {
106 if (fst->fs_type == PS_FST_TYPE_VNODE) {
107 er = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
108 if (er != 0) {
109 error("%s", errbuf);
110 goto out;
111 }
112
113 if (vn.vn_dev == kp->ki_tdev && fst->fs_fd >= 0) {
114 if (fd_array_push(&fds, fst->fs_fd) != 0) {
115 error("Unable to allocate memory for fd array.");
116 goto out;
117 }
118 }
119 }
120 }
121
122 out:
123 procstat_freefiles(procstat, head);
124 procstat_freeprocs(procstat, kp);
125 procstat_close(procstat);
126 *count = fds.n;
127 debug("Found %d tty fds in child %d.", fds.n, child->pid);
128 return fds.fds;
129 }
130
131 // Find the PID of the terminal emulator for `target's terminal.
132 //
133 // We assume that the terminal emulator is the parent of the session
134 // leader. This is true in most cases, although in principle you can
135 // construct situations where it is false. We should fail safe later
136 // on if this turns out to be wrong, however.
137 int find_terminal_emulator(struct steal_pty_state *steal) {
138 struct procstat *procstat;
139 struct kinfo_proc *kp;
140 unsigned int cnt;
141
142 procstat = procstat_open_sysctl();
143 cnt = 0;
144 kp = procstat_getprocs(procstat, KERN_PROC_PID, steal->target_stat.sid, &cnt);
145
146 if (kp && cnt > 0)
147 steal->emulator_pid = kp->ki_ppid;
148
149 procstat_freeprocs(procstat, kp);
150 procstat_close(procstat);
151
152 return (cnt != 0 ? 0 : 1);
153 }
154
155 int fill_proc_stat(struct steal_pty_state *steal, struct kinfo_proc *kp) {
156 struct proc_stat *ps = &steal->target_stat;
157
158 if (strlcpy(ps->comm, kp->ki_comm, sizeof(ps->comm)) >= sizeof(ps->comm))
159 return ENOMEM;
160 ps->pid = kp->ki_pid;
161 ps->ppid = kp->ki_ppid;
162 ps->sid = kp->ki_sid;
163 ps->pgid = kp->ki_pgid;
164 ps->ctty = kp->ki_tdev;
165
166 return 0;
167 }
168
169 int grab_uid(pid_t pid, uid_t *out) {
170 struct procstat *procstat;
171 struct kinfo_proc *kp;
172 unsigned int cnt;
173
174 procstat = procstat_open_sysctl();
175 cnt = 0;
176 kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt);
177
178 if (kp && cnt > 0)
179 *out = kp->ki_uid;
180 else
181 return ESRCH;
182 procstat_freeprocs(procstat, kp);
183 procstat_close(procstat);
184
185 return 0;
186 }
187
188 int get_terminal_state(struct steal_pty_state *steal, pid_t target) {
189 struct procstat *procstat;
190 struct kinfo_proc *kp;
191 unsigned int cnt;
192 int err = 0;
193
194 procstat = procstat_open_sysctl();
195 cnt = 0;
196 kp = procstat_getprocs(procstat, KERN_PROC_PID, target, &cnt);
197 if (kp == NULL || cnt < 1)
198 goto done;
199
200 if (kp->ki_tdev == NODEV) {
201 error("Child is not connected to a pseudo-TTY. Unable to steal TTY.");
202 err = EINVAL;
203 goto done;
204 }
205
206 if ((err = fill_proc_stat(steal, kp)))
207 return err;
208
209 if ((err = find_terminal_emulator(steal)))
210 return err;
211
212 if ((err = grab_uid(steal->emulator_pid, &steal->emulator_uid)))
213 return err;
214 done:
215 procstat_freeprocs(procstat, kp);
216 procstat_close(procstat);
217 return err;
218 }
219
220 int find_master_fd(struct steal_pty_state *steal) {
221 char errbuf[_POSIX2_LINE_MAX];
222 struct filestat *fst;
223 struct filestat_list *head;
224 struct procstat *procstat;
225 struct kinfo_proc *kp;
226 struct ptsstat pts;
227 unsigned int cnt;
228 int err;
229
230 head = get_procfiles(steal->child.pid, &kp, &procstat, &cnt);
231
232 STAILQ_FOREACH(fst, head, next) {
233 if (fst->fs_type != PS_FST_TYPE_PTS)
234 continue;
235
236 err = procstat_get_pts_info(procstat, fst, &pts, errbuf);
237 if (err != 0) {
238 error("error discovering fd=%d", fst->fs_fd);
239 continue;
240 }
241
242 if (pts.dev != steal->target_stat.ctty)
243 continue;
244
245 if (fd_array_push(&steal->master_fds, fst->fs_fd) != 0) {
246 error("unable to allocate memory for fd array");
247 return ENOMEM;
248 }
249 }
250
251 procstat_freefiles(procstat, head);
252 procstat_freeprocs(procstat, kp);
253 procstat_close(procstat);
254 debug("Found %d master tty fds in child %d.", steal->master_fds.n, steal->child.pid);
255 if (steal->master_fds.n == 0)
256 return ESRCH;
257 return 0;
258 }
259
260 int get_pt() {
261 return posix_openpt(O_RDWR | O_NOCTTY);
262 }
263
264 int get_process_tty_termios(pid_t pid, struct termios *tio) {
265 int err = EINVAL;
266 struct kinfo_proc *kp;
267 unsigned int cnt;
268 struct filestat_list *head;
269 struct filestat *fst;
270 struct procstat *procstat;
271 int fd = -1;
272
273 head = get_procfiles(pid, &kp, &procstat, &cnt);
274
275 STAILQ_FOREACH(fst, head, next) {
276 if (fst->fs_type == PS_FST_TYPE_VNODE) {
277 if (fst->fs_path) {
278 fd = open(fst->fs_path, O_RDONLY);
279 if (fd >= 0 && isatty(fd)) {
280 if (tcgetattr(fd, tio) < 0) {
281 err = -assert_nonzero(errno);
282 }
283 else {
284 close(fd);
285 err = 0;
286 goto done;
287 }
288 }
289 close(fd);
290 }
291 }
292 }
293
294 done:
295 procstat_freefiles(procstat, head);
296 procstat_freeprocs(procstat, kp);
297 procstat_close(procstat);
298 return err;
299 }
300
301 void move_process_group(struct ptrace_child *child, pid_t from, pid_t to) {
302 struct procstat *procstat;
303 struct kinfo_proc *kp;
304 unsigned int cnt;
305 int i;
306 int err;
307
308 procstat = procstat_open_sysctl();
309 cnt = 0;
310 kp = procstat_getprocs(procstat, KERN_PROC_PGRP, from, &cnt);
311
312 for (i = 0; i < cnt; i++) {
313 debug("Change pgid for pid %d to %d", kp[i].ki_pid, to);
314 err = do_syscall(child, setpgid, kp[i].ki_pid, to, 0, 0, 0, 0);
315 if (err < 0)
316 error(" failed: %s", strerror(-err));
317 }
318 procstat_freeprocs(procstat, kp);
319 procstat_close(procstat);
320 }
321
322 void copy_user(struct ptrace_child *d, struct ptrace_child *s) {
323 memcpy(&d->regs, &s->regs, sizeof(s->regs));
324 }
325
326 #endif