1 /* $NetBSD: kern_systrace.c,v 1.63 2006/11/28 17:58:10 elad Exp $ */
2
3 /*
4 * Copyright 2002, 2003 Niels Provos <provos@citi.umich.edu>
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 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Niels Provos.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.63 2006/11/28 17:58:10 elad Exp $");
35
36 #include "opt_systrace.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/tree.h>
41 #include <sys/malloc.h>
42 #include <sys/syscall.h>
43 #include <sys/vnode.h>
44 #include <sys/errno.h>
45 #include <sys/conf.h>
46 #include <sys/device.h>
47 #include <sys/proc.h>
48 #include <sys/file.h>
49 #include <sys/filedesc.h>
50 #include <sys/filio.h>
51 #include <sys/signalvar.h>
52 #include <sys/lock.h>
53 #include <sys/pool.h>
54 #include <sys/mount.h>
55 #include <sys/poll.h>
56 #include <sys/ptrace.h>
57 #include <sys/namei.h>
58 #include <sys/systrace.h>
59 #include <sys/sa.h>
60 #include <sys/savar.h>
61 #include <sys/kauth.h>
62
63 #include <compat/common/compat_util.h>
64
65 #ifdef __NetBSD__
66 #define SYSTRACE_LOCK(fst, p) lockmgr(&fst->lock, LK_EXCLUSIVE, NULL)
67 #define SYSTRACE_UNLOCK(fst, p) lockmgr(&fst->lock, LK_RELEASE, NULL)
68 #else
69 #define SYSTRACE_LOCK(fst, p) lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p)
70 #define SYSTRACE_UNLOCK(fst, p) lockmgr(&fst->lock, LK_RELEASE, NULL, p)
71 #endif
72 #ifndef M_XDATA
73 MALLOC_DEFINE(M_SYSTR, "systrace", "systrace");
74 #define M_XDATA M_SYSTR
75 #endif
76
77 #ifdef __NetBSD__
78 dev_type_open(systraceopen);
79 #else
80 cdev_decl(systrace);
81 #endif
82
83 #ifdef __NetBSD__
84 int systracef_read(struct file *, off_t *, struct uio *, kauth_cred_t,
85 int);
86 int systracef_write(struct file *, off_t *, struct uio *, kauth_cred_t,
87 int);
88 int systracef_poll(struct file *, int, struct lwp *);
89 int systracef_ioctl(struct file *, u_long, void *, struct lwp *);
90 int systracef_close(struct file *, struct lwp *);
91 #else
92 int systracef_read(struct file *, off_t *, struct uio *, kauth_cred_t);
93 int systracef_write(struct file *, off_t *, struct uio *, kauth_cred_t);
94 int systracef_select(struct file *, int, struct proc *);
95 int systracef_ioctl(struct file *, u_long, caddr_t, struct proc *);
96 int systracef_stat(struct file *, struct stat *, struct proc *);
97 int systracef_close(struct file *, struct proc *);
98 #endif
99
100 struct str_policy {
101 TAILQ_ENTRY(str_policy) next;
102
103 int nr;
104
105 const struct emul *emul; /* Is only valid for this emulation */
106
107 int refcount;
108
109 int nsysent;
110 u_char *sysent;
111 };
112
113 #define STR_PROC_ONQUEUE 0x01
114 #define STR_PROC_WAITANSWER 0x02
115 #define STR_PROC_SYSCALLRES 0x04
116 #define STR_PROC_REPORT 0x08 /* Report emulation */
117 #define STR_PROC_NEEDSEQNR 0x10 /* Answer must quote seqnr */
118 #define STR_PROC_SETEUID 0x20 /* Elevate privileges */
119 #define STR_PROC_SETEGID 0x40
120 #define STR_PROC_DIDSETUGID 0x80
121
122 struct str_process {
123 TAILQ_ENTRY(str_process) next;
124
125 struct proc *proc;
126 const struct emul *oldemul;
127 uid_t olduid;
128 gid_t oldgid;
129
130 pid_t pid;
131
132 struct fsystrace *parent;
133 struct str_policy *policy;
134
135 struct systrace_replace *replace;
136 char *fname[SYSTR_MAXFNAME];
137 size_t nfname;
138
139 int flags;
140 short answer;
141 short error;
142 uint16_t seqnr; /* expected reply sequence number */
143
144 uid_t seteuid;
145 uid_t saveuid;
146 gid_t setegid;
147 gid_t savegid;
148
149 int isscript;
150 char scriptname[MAXPATHLEN];
151 };
152
153 uid_t systrace_seteuid(struct lwp *, uid_t);
154 gid_t systrace_setegid(struct lwp *, gid_t);
155 void systrace_lock(void);
156 void systrace_unlock(void);
157
158 /* Needs to be called with fst locked */
159
160 int systrace_attach(struct fsystrace *, pid_t);
161 int systrace_detach(struct str_process *);
162 int systrace_answer(struct str_process *, struct systrace_answer *);
163 int systrace_setscriptname(struct str_process *, struct
164 systrace_scriptname *);
165 int systrace_io(struct str_process *, struct systrace_io *);
166 int systrace_policy(struct fsystrace *, struct systrace_policy *);
167 int systrace_preprepl(struct str_process *, struct systrace_replace *);
168 int systrace_replace(struct str_process *, size_t, register_t []);
169 int systrace_getcwd(struct fsystrace *, struct str_process *);
170 int systrace_fname(struct str_process *, caddr_t, size_t);
171 void systrace_replacefree(struct str_process *);
172
173 int systrace_processready(struct str_process *);
174 struct proc *systrace_find(struct str_process *);
175 struct str_process *systrace_findpid(struct fsystrace *fst, pid_t pid);
176 void systrace_wakeup(struct fsystrace *);
177 void systrace_closepolicy(struct fsystrace *, struct str_policy *);
178 int systrace_insert_process(struct fsystrace *, struct proc *,
179 struct str_process **);
180 struct str_policy *systrace_newpolicy(struct fsystrace *, int);
181 int systrace_msg_child(struct fsystrace *, struct str_process *, pid_t);
182 int systrace_msg_policyfree(struct fsystrace *, struct str_policy *);
183 int systrace_msg_ask(struct fsystrace *, struct str_process *,
184 int, size_t, register_t []);
185 int systrace_msg_result(struct fsystrace *, struct str_process *,
186 int, int, size_t, register_t [], register_t []);
187 int systrace_msg_emul(struct fsystrace *, struct str_process *);
188 int systrace_msg_ugid(struct fsystrace *, struct str_process *);
189 int systrace_make_msg(struct str_process *, int, struct str_message *);
190
191 static const struct fileops systracefops = {
192 systracef_read,
193 systracef_write,
194 systracef_ioctl,
195 fnullop_fcntl,
196 systracef_poll,
197 fbadop_stat,
198 systracef_close,
199 fnullop_kqfilter
200 };
201
202 #ifdef __NetBSD__
203 POOL_INIT(systr_proc_pl, sizeof(struct str_process), 0, 0, 0, "strprocpl",
204 NULL);
205 POOL_INIT(systr_policy_pl, sizeof(struct str_policy), 0, 0, 0, "strpolpl",
206 NULL);
207 POOL_INIT(systr_msgcontainer_pl, sizeof(struct str_msgcontainer), 0, 0, 0,
208 "strmsgpl", NULL);
209
210 struct lock systrace_lck = LOCK_INITIALIZER(PLOCK, "systrace", 0, 0);
211 #else /* ! __NetBSD__ */
212 struct pool systr_proc_pl;
213 struct pool systr_policy_pl;
214 struct pool systr_msgcontainer_pl;
215
216 struct lock systrace_lck;
217 #endif /* __NetBSD__ */
218
219 int systrace_debug = 0;
220
221 #ifdef __NetBSD__
222 const struct cdevsw systrace_cdevsw = {
223 systraceopen, noclose, noread, nowrite, noioctl,
224 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
225 };
226 #endif
227
228 #define DPRINTF(y) if (systrace_debug) printf y;
229
230 /* ARGSUSED */
231 int
232 systracef_read(struct file *fp, off_t *poff, struct uio *uio, kauth_cred_t cred,
233 int flags)
234 {
235 struct fsystrace *fst = (struct fsystrace *)fp->f_data;
236 struct str_msgcontainer *cont;
237 int error = 0;
238
239 if (uio->uio_resid != sizeof(struct str_message))
240 return (EINVAL);
241
242 again:
243 systrace_lock();
244 SYSTRACE_LOCK(fst, curlwp);
245 systrace_unlock();
246 if ((cont = TAILQ_FIRST(&fst->messages)) != NULL) {
247 error = uiomove((caddr_t)&cont->msg,
248 sizeof(struct str_message), uio);
249 if (!error) {
250 TAILQ_REMOVE(&fst->messages, cont, next);
251 if (!SYSTR_MSG_NOPROCESS(cont))
252 CLR(cont->strp->flags, STR_PROC_ONQUEUE);
253 pool_put(&systr_msgcontainer_pl, cont);
254
255 }
256 } else if (TAILQ_FIRST(&fst->processes) == NULL) {
257 /* EOF situation */
258 ;
259 } else {
260 if (fp->f_flag & FNONBLOCK)
261 error = EAGAIN;
262 else {
263 SYSTRACE_UNLOCK(fst, curlwp);
264 error = tsleep(fst, PWAIT|PCATCH, "systrrd", 0);
265 if (error)
266 goto out;
267 goto again;
268 }
269
270 }
271
272 SYSTRACE_UNLOCK(fst, curlwp);
273 out:
274 return (error);
275 }
276
277 /* ARGSUSED */
278 int
279 systracef_write(struct file *fp, off_t *poff, struct uio *uio,
280 kauth_cred_t cred, int flags)
281 {
282
283 return (EIO);
284 }
285
286 #define POLICY_VALID(x) ((x) == SYSTR_POLICY_PERMIT || \
287 (x) == SYSTR_POLICY_ASK || \
288 (x) == SYSTR_POLICY_NEVER)
289
290 /* ARGSUSED */
291 int
292 systracef_ioctl(struct file *fp, u_long cmd, void *data, struct lwp *l)
293 {
294 int ret = 0;
295 struct fsystrace *fst = (struct fsystrace *)fp->f_data;
296 #ifdef __NetBSD__
297 struct proc *p = l->l_proc;
298 struct cwdinfo *cwdp;
299 #else
300 struct filedesc *fdp;
301 #endif
302 struct str_process *strp = NULL;
303 pid_t pid = 0;
304
305 switch (cmd) {
306 case FIONBIO:
307 case FIOASYNC:
308 return (0);
309
310 case STRIOCDETACH:
311 case STRIOCREPORT:
312 pid = *(pid_t *)data;
313 if (!pid)
314 ret = EINVAL;
315 break;
316 case STRIOCANSWER:
317 pid = ((struct systrace_answer *)data)->stra_pid;
318 if (!pid)
319 ret = EINVAL;
320 break;
321 case STRIOCIO:
322 pid = ((struct systrace_io *)data)->strio_pid;
323 if (!pid)
324 ret = EINVAL;
325 break;
326 case STRIOCSCRIPTNAME:
327 pid = ((struct systrace_scriptname *)data)->sn_pid;
328 if (!pid)
329 ret = EINVAL;
330 break;
331 case STRIOCGETCWD:
332 pid = *(pid_t *)data;
333 if (!pid)
334 ret = EINVAL;
335 break;
336 case STRIOCATTACH:
337 case STRIOCRESCWD:
338 case STRIOCPOLICY:
339 break;
340 case STRIOCREPLACE:
341 pid = ((struct systrace_replace *)data)->strr_pid;
342 if (!pid)
343 ret = EINVAL;
344 break;
345 default:
346 ret = EINVAL;
347 break;
348 }
349
350 if (ret)
351 return (ret);
352
353 systrace_lock();
354 SYSTRACE_LOCK(fst, curlwp);
355 systrace_unlock();
356 if (pid) {
357 strp = systrace_findpid(fst, pid);
358 if (strp == NULL) {
359 ret = ESRCH;
360 goto unlock;
361 }
362 }
363
364 switch (cmd) {
365 case STRIOCATTACH:
366 pid = *(pid_t *)data;
367 if (!pid)
368 ret = EINVAL;
369 else
370 ret = systrace_attach(fst, pid);
371 DPRINTF(("%s: attach to %u: %d\n", __func__, pid, ret));
372 break;
373 case STRIOCDETACH:
374 ret = systrace_detach(strp);
375 break;
376 case STRIOCREPORT:
377 SET(strp->flags, STR_PROC_REPORT);
378 break;
379 case STRIOCANSWER:
380 ret = systrace_answer(strp, (struct systrace_answer *)data);
381 break;
382 case STRIOCIO:
383 ret = systrace_io(strp, (struct systrace_io *)data);
384 break;
385 case STRIOCSCRIPTNAME:
386 ret = systrace_setscriptname(strp,
387 (struct systrace_scriptname *)data);
388 break;
389 case STRIOCPOLICY:
390 ret = systrace_policy(fst, (struct systrace_policy *)data);
391 break;
392 case STRIOCREPLACE:
393 ret = systrace_preprepl(strp, (struct systrace_replace *)data);
394 break;
395 case STRIOCRESCWD:
396 if (!fst->fd_pid) {
397 ret = EINVAL;
398 break;
399 }
400 #ifdef __NetBSD__
401 cwdp = p->p_cwdi;
402
403 /* Release cwd from other process */
404 if (cwdp->cwdi_cdir)
405 vrele(cwdp->cwdi_cdir);
406 if (cwdp->cwdi_rdir)
407 vrele(cwdp->cwdi_rdir);
408 cwdp->cwdi_cdir = fst->fd_cdir;
409 cwdp->cwdi_rdir = fst->fd_rdir;
410 #else
411 fdp = p->p_fd;
412
413 /* Release cwd from other process */
414 if (fdp->fd_cdir)
415 vrele(fdp->fd_cdir);
416 if (fdp->fd_rdir)
417 vrele(fdp->fd_rdir);
418 /* This restores the cwd we had before */
419 fdp->fd_cdir = fst->fd_cdir;
420 fdp->fd_rdir = fst->fd_rdir;
421 #endif
422 /* Note that we are normal again */
423 fst->fd_pid = 0;
424 fst->fd_cdir = fst->fd_rdir = NULL;
425 break;
426 case STRIOCGETCWD:
427 ret = systrace_getcwd(fst, strp);
428 break;
429 default:
430 ret = EINVAL;
431 break;
432 }
433
434 unlock:
435 SYSTRACE_UNLOCK(fst, curlwp);
436
437 return (ret);
438 }
439
440 #ifdef __NetBSD__
441 int
442 systracef_poll(struct file *fp, int events, struct lwp *l)
443 {
444 struct fsystrace *fst = (struct fsystrace *)fp->f_data;
445 int revents = 0;
446
447 if ((events & (POLLIN | POLLRDNORM)) == 0)
448 return (revents);
449
450 systrace_lock();
451 SYSTRACE_LOCK(fst, l->l_proc);
452 systrace_unlock();
453 if (!TAILQ_EMPTY(&fst->messages))
454 revents |= events & (POLLIN | POLLRDNORM);
455 if (revents == 0)
456 selrecord(l, &fst->si);
457 SYSTRACE_UNLOCK(fst, l->l_proc);
458
459 return (revents);
460 }
461 #else
462 int
463 systracef_select(struct file *fp, int which, struct proc *p)
464 {
465 struct fsystrace *fst = (struct fsystrace *)fp->f_data;
466 int ready = 0;
467
468 if (which != FREAD)
469 return (0);
470
471 systrace_lock();
472 SYSTRACE_LOCK(fst, p);
473 systrace_unlock();
474 ready = TAILQ_FIRST(&fst->messages) != NULL;
475 if (!ready)
476 selrecord(p, &fst->si);
477 SYSTRACE_UNLOCK(fst, p);
478
479 return (ready);
480 }
481 #endif /* __NetBSD__ */
482
483 /* ARGSUSED */
484 int
485 systracef_close(struct file *fp, struct lwp *l)
486 {
487 struct fsystrace *fst = (struct fsystrace *)fp->f_data;
488 struct str_process *strp;
489 struct str_msgcontainer *cont;
490 struct str_policy *strpol;
491
492 systrace_lock();
493 SYSTRACE_LOCK(fst, curlwp);
494 systrace_unlock();
495
496 /* Untrace all processes */
497 for (strp = TAILQ_FIRST(&fst->processes); strp;
498 strp = TAILQ_FIRST(&fst->processes)) {
499 struct proc *q = strp->proc;
500
501 systrace_detach(strp);
502 psignal(q, SIGKILL);
503 }
504
505 /* Clean up fork and exit messages */
506 for (cont = TAILQ_FIRST(&fst->messages); cont;
507 cont = TAILQ_FIRST(&fst->messages)) {
508 TAILQ_REMOVE(&fst->messages, cont, next);
509 pool_put(&systr_msgcontainer_pl, cont);
510 }
511
512 /* Clean up all policies */
513 for (strpol = TAILQ_FIRST(&fst->policies); strpol;
514 strpol = TAILQ_FIRST(&fst->policies))
515 systrace_closepolicy(fst, strpol);
516
517 /* Release vnodes */
518 if (fst->fd_cdir)
519 vrele(fst->fd_cdir);
520 if (fst->fd_rdir)
521 vrele(fst->fd_rdir);
522 SYSTRACE_UNLOCK(fst, curlwp);
523
524 FREE(fp->f_data, M_XDATA);
525 fp->f_data = NULL;
526
527 return (0);
528 }
529
530 void
531 systrace_lock(void)
532 {
533 #ifdef __NetBSD__
534 lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL);
535 #else
536 lockmgr(&systrace_lck, LK_EXCLUSIVE, NULL, curlwp);
537 #endif
538 }
539
540 void
541 systrace_unlock(void)
542 {
543 #ifdef __NetBSD__
544 lockmgr(&systrace_lck, LK_RELEASE, NULL);
545 #else
546 lockmgr(&systrace_lck, LK_RELEASE, NULL, curlwp);
547 #endif
548 }
549
550 #ifndef __NetBSD__
551 void
552 systrace_init(void)
553 {
554
555 pool_init(&systr_proc_pl, sizeof(struct str_process), 0, 0, 0,
556 "strprocpl", NULL);
557 pool_init(&systr_policy_pl, sizeof(struct str_policy), 0, 0, 0,
558 "strpolpl", NULL);
559 pool_init(&systr_msgcontainer_pl, sizeof(struct str_msgcontainer),
560 0, 0, 0, "strmsgpl", NULL);
561
562 lockinit(&systrace_lck, PLOCK, "systrace", 0, 0);
563 }
564 #endif /* ! __NetBSD__ */
565
566 int
567 systraceopen(dev_t dev, int flag, int mode, struct lwp *l)
568 {
569 struct fsystrace *fst;
570 struct file *fp;
571 int error, fd;
572
573 /* falloc() will use the descriptor for us. */
574 if ((error = falloc(l, &fp, &fd)) != 0)
575 return (error);
576
577 MALLOC(fst, struct fsystrace *, sizeof(*fst), M_XDATA, M_WAITOK);
578
579 memset(fst, 0, sizeof(struct fsystrace));
580 lockinit(&fst->lock, PLOCK, "systrace", 0, 0);
581
582 TAILQ_INIT(&fst->processes);
583 TAILQ_INIT(&fst->messages);
584 TAILQ_INIT(&fst->policies);
585
586 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
587 &l->l_acflag) == 0)
588 fst->issuser = 1;
589 fst->p_ruid = kauth_cred_getuid(l->l_cred);
590 fst->p_rgid = kauth_cred_getgid(l->l_cred);
591
592 return fdclone(l, fp, fd, flag, &systracefops, fst);
593 }
594
595 void
596 systrace_wakeup(struct fsystrace *fst)
597 {
598 wakeup((caddr_t)fst);
599 selwakeup(&fst->si);
600 }
601
602 struct proc *
603 systrace_find(struct str_process *strp)
604 {
605 struct proc *proc;
606
607 if ((proc = pfind(strp->pid)) == NULL)
608 return (NULL);
609
610 if (proc != strp->proc)
611 return (NULL);
612
613 if (!ISSET(proc->p_flag, P_SYSTRACE))
614 return (NULL);
615
616 return (proc);
617 }
618
619 void
620 systrace_sys_exit(struct proc *proc)
621 {
622 struct str_process *strp;
623 struct fsystrace *fst;
624
625 systrace_lock();
626 strp = proc->p_systrace;
627 if (strp != NULL) {
628 fst = strp->parent;
629 SYSTRACE_LOCK(fst, curlwp);
630 systrace_unlock();
631
632 /* Insert Exit message */
633 systrace_msg_child(fst, strp, -1);
634
635 systrace_detach(strp);
636 SYSTRACE_UNLOCK(fst, curlwp);
637 } else
638 systrace_unlock();
639 CLR(proc->p_flag, P_SYSTRACE);
640 }
641
642 void
643 systrace_sys_fork(struct proc *oldproc, struct proc *p)
644 {
645 struct str_process *oldstrp, *strp;
646 struct fsystrace *fst;
647
648 systrace_lock();
649 oldstrp = oldproc->p_systrace;
650 if (oldstrp == NULL) {
651 systrace_unlock();
652 return;
653 }
654
655 fst = oldstrp->parent;
656 SYSTRACE_LOCK(fst, curlwp);
657 systrace_unlock();
658
659 if (systrace_insert_process(fst, p, &strp)) {
660 /* We need to kill the child */
661 psignal(p, SIGKILL);
662 goto out;
663 }
664
665 /* Reference policy */
666 if ((strp->policy = oldstrp->policy) != NULL)
667 strp->policy->refcount++;
668
669 /* Insert fork message */
670 systrace_msg_child(fst, oldstrp, p->p_pid);
671 out:
672 SYSTRACE_UNLOCK(fst, curlwp);
673 }
674
675 int
676 systrace_enter(struct lwp *l, register_t code, void *v)
677 {
678 const struct sysent *callp;
679 struct str_process *strp;
680 struct str_policy *strpolicy;
681 struct fsystrace *fst;
682 struct proc *p = l->l_proc;
683 kauth_cred_t pc;
684 int policy, error = 0, maycontrol = 0, issuser = 0;
685 size_t argsize;
686
687 systrace_lock();
688 strp = p->p_systrace;
689 if (strp == NULL) {
690 systrace_unlock();
691 return (EINVAL);
692 }
693
694 KASSERT(strp->proc == p);
695
696 fst = strp->parent;
697
698 SYSTRACE_LOCK(fst, p);
699 systrace_unlock();
700
701 /*
702 * We can not monitor a SUID process unless we are root,
703 * but we wait until it executes something unprivileged.
704 * A non-root user may only monitor if the real uid and
705 * real gid match the monitored process. Changing the
706 * uid or gid causes P_SUGID to be set.
707 */
708 if (fst->issuser) {
709 maycontrol = 1;
710 issuser = 1;
711 } else if (!(p->p_flag & P_SUGID)) {
712 maycontrol = fst->p_ruid == kauth_cred_getuid(p->p_cred) &&
713 fst->p_rgid == kauth_cred_getgid(p->p_cred);
714 }
715
716 if (!maycontrol) {
717 policy = SYSTR_POLICY_PERMIT;
718 } else {
719 /* Find out current policy */
720 if ((strpolicy = strp->policy) == NULL)
721 policy = SYSTR_POLICY_ASK;
722 else {
723 if (code >= strpolicy->nsysent)
724 policy = SYSTR_POLICY_NEVER;
725 else
726 policy = strpolicy->sysent[code];
727 }
728 }
729
730 callp = p->p_emul->e_sysent + code;
731
732 /* Fast-path */
733 if (policy != SYSTR_POLICY_ASK) {
734 if (policy != SYSTR_POLICY_PERMIT) {
735 if (policy > 0)
736 error = policy;
737 else
738 error = EPERM;
739 }
740 strp->oldemul = NULL;
741 systrace_replacefree(strp);
742 SYSTRACE_UNLOCK(fst, p);
743 return (error);
744 }
745
746 /* Get the (adjusted) argsize */
747 argsize = callp->sy_argsize;
748 #ifdef _LP64
749 if (p->p_flag & P_32)
750 argsize = argsize << 1;
751 #endif
752
753 /* Puts the current process to sleep, return unlocked */
754 error = systrace_msg_ask(fst, strp, code, argsize, v);
755
756 /* lock has been released in systrace_msg_ask() */
757 fst = NULL;
758 /* We might have detached by now for some reason */
759 if (!error && (strp = p->p_systrace) != NULL) {
760 /* XXX - do I need to lock here? */
761 if (strp->answer == SYSTR_POLICY_NEVER) {
762 error = strp->error;
763 systrace_replacefree(strp);
764 } else {
765 if (ISSET(strp->flags, STR_PROC_SYSCALLRES)) {
766 #ifndef __NetBSD__
767 CLR(strp->flags, STR_PROC_SYSCALLRES);
768 #endif
769 }
770 /* Replace the arguments if necessary */
771 if (strp->replace != NULL) {
772 error = systrace_replace(strp, argsize, v);
773 }
774 }
775 }
776
777 systrace_lock();
778 if ((strp = p->p_systrace) == NULL)
779 goto out;
780
781 if (error) {
782 strp->oldemul = NULL;
783 goto out;
784 }
785
786 pc = p->p_cred;
787 strp->oldemul = p->p_emul;
788 strp->olduid = kauth_cred_getuid(pc);
789 strp->oldgid = kauth_cred_getgid(pc);
790
791 /* Elevate privileges as desired */
792 if (issuser) {
793 if (ISSET(strp->flags, STR_PROC_SETEUID)) {
794 strp->saveuid = systrace_seteuid(l, strp->seteuid);
795 SET(strp->flags, STR_PROC_DIDSETUGID);
796 }
797 if (ISSET(strp->flags, STR_PROC_SETEGID)) {
798 strp->savegid = systrace_setegid(l, strp->setegid);
799 SET(strp->flags, STR_PROC_DIDSETUGID);
800 }
801 } else
802 CLR(strp->flags,
803 STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID);
804
805 out:
806 systrace_unlock();
807 return (error);
808 }
809
810 void
811 systrace_exit(struct lwp *l, register_t code, void *v, register_t retval[],
812 int error)
813 {
814 const struct sysent *callp;
815 struct str_process *strp;
816 struct fsystrace *fst;
817 struct proc *p = l->l_proc;
818 kauth_cred_t pc;
819
820 /* Report change in emulation */
821 systrace_lock();
822 strp = p->p_systrace;
823 if (strp == NULL || strp->oldemul == NULL) {
824 systrace_unlock();
825 return;
826 }
827 DPRINTF(("exit syscall %lu, oldemul %p\n", (u_long)code, strp->oldemul));
828
829 /* Return to old privileges */
830 pc = p->p_cred;
831 if (ISSET(strp->flags, STR_PROC_DIDSETUGID)) {
832 if (ISSET(strp->flags, STR_PROC_SETEUID)) {
833 if (kauth_cred_geteuid(pc) == strp->seteuid)
834 systrace_seteuid(l, strp->saveuid);
835 }
836 if (ISSET(strp->flags, STR_PROC_SETEGID)) {
837 if (kauth_cred_getegid(pc) == strp->setegid)
838 systrace_setegid(l, strp->savegid);
839 }
840 }
841 CLR(strp->flags,
842 STR_PROC_SETEUID|STR_PROC_SETEGID|STR_PROC_DIDSETUGID);
843
844 systrace_replacefree(strp);
845
846 if (p->p_flag & P_SUGID) {
847 if ((fst = strp->parent) == NULL || !fst->issuser) {
848 systrace_unlock();
849 return;
850 }
851 }
852
853 /* See if we should force a report */
854 if (ISSET(strp->flags, STR_PROC_REPORT)) {
855 CLR(strp->flags, STR_PROC_REPORT);
856 strp->oldemul = NULL;
857 }
858
859 if (p->p_emul != strp->oldemul && strp != NULL) {
860 fst = strp->parent;
861 SYSTRACE_LOCK(fst, p);
862 systrace_unlock();
863
864 /* Old policy is without meaning now */
865 if (strp->policy) {
866 systrace_closepolicy(fst, strp->policy);
867 strp->policy = NULL;
868 }
869 systrace_msg_emul(fst, strp);
870 } else
871 systrace_unlock();
872
873 /* Report if effective uid or gid changed */
874 systrace_lock();
875 strp = p->p_systrace;
876 if (strp != NULL && (strp->olduid != kauth_cred_getuid(p->p_cred) ||
877 strp->oldgid != kauth_cred_getgid(p->p_cred))) {
878
879 fst = strp->parent;
880 SYSTRACE_LOCK(fst, p);
881 systrace_unlock();
882
883 systrace_msg_ugid(fst, strp);
884 } else
885 systrace_unlock();
886
887 /* Report result from system call */
888 systrace_lock();
889 strp = p->p_systrace;
890 if (strp != NULL && ISSET(strp->flags, STR_PROC_SYSCALLRES)) {
891 size_t argsize;
892
893 CLR(strp->flags, STR_PROC_SYSCALLRES);
894 fst = strp->parent;
895 SYSTRACE_LOCK(fst, p);
896 systrace_unlock();
897 DPRINTF(("will ask syscall %lu, strp %p\n", (u_long)code, strp));
898
899 /* Get the (adjusted) argsize */
900 callp = p->p_emul->e_sysent + code;
901 argsize = callp->sy_argsize;
902 #ifdef _LP64
903 if (p->p_flag & P_32)
904 argsize = argsize << 1;
905 #endif
906
907 systrace_msg_result(fst, strp, error, code, argsize, v, retval);
908 } else {
909 DPRINTF(("will not ask syscall %lu, strp %p\n", (u_long)code, strp));
910 systrace_unlock();
911 }
912 }
913
914 uid_t
915 systrace_seteuid(struct lwp *l, uid_t euid)
916 {
917 struct proc *p = l->l_proc;
918 kauth_cred_t cred;
919 uid_t oeuid;
920
921 proc_crmod_enter(p);
922 cred = p->p_cred;
923
924 oeuid = kauth_cred_geteuid(cred);
925 if (oeuid == euid) {
926 proc_crmod_leave(p, cred, NULL);
927 return (oeuid);
928 }
929
930 /* Copy credentials so other references do not see our changes. */
931 cred = kauth_cred_dup(cred);
932 kauth_cred_seteuid(cred, euid);
933
934 /* Mark process as having changed credentials, stops tracing etc */
935 p_sugid(p);
936
937 /* Broadcast our credentials to the process and other LWPs. */
938 proc_crmod_leave(p, cred, p->p_cred);
939
940 /* Update our copy of the credentials. */
941 lwp_update_creds(l);
942
943 return (oeuid);
944 }
945
946 gid_t
947 systrace_setegid(struct lwp *l, gid_t egid)
948 {
949 struct proc *p = l->l_proc;
950 kauth_cred_t cred;
951 gid_t oegid;
952
953 proc_crmod_enter(p);
954 cred = p->p_cred;
955
956 oegid = kauth_cred_getegid(cred);
957 if (oegid == egid) {
958 proc_crmod_leave(p, cred, NULL);
959 return (oegid);
960 }
961
962 /* Copy credentials so other references do not see our changes. */
963 cred = kauth_cred_dup(cred);
964 kauth_cred_setegid(cred, egid);
965
966 /* Mark process as having changed credentials, stops tracing etc */
967 p_sugid(p);
968
969 /* Broadcast our credentials to the process and other LWPs. */
970 proc_crmod_leave(p, cred, p->p_cred);
971
972 /* Update our copy of the credentials. */
973 lwp_update_creds(l);
974
975 return (oegid);
976 }
977
978 /* Called with fst locked */
979
980 int
981 systrace_answer(struct str_process *strp, struct systrace_answer *ans)
982 {
983 int error = 0;
984
985 DPRINTF(("%s: %u: policy %d\n", __func__,
986 ans->stra_pid, ans->stra_policy));
987
988 if (!POLICY_VALID(ans->stra_policy)) {
989 error = EINVAL;
990 goto out;
991 }
992
993 /* Check if answer is in sync with us */
994 if (ans->stra_seqnr != strp->seqnr) {
995 error = ESRCH;
996 goto out;
997 }
998
999 if ((error = systrace_processready(strp)) != 0)
1000 goto out;
1001
1002 strp->answer = ans->stra_policy;
1003 strp->error = ans->stra_error;
1004 if (!strp->error)
1005 strp->error = EPERM;
1006 if (ISSET(ans->stra_flags, SYSTR_FLAGS_RESULT))
1007 SET(strp->flags, STR_PROC_SYSCALLRES);
1008
1009 /* See if we should elevate privileges for this system call */
1010 if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEUID)) {
1011 SET(strp->flags, STR_PROC_SETEUID);
1012 strp->seteuid = ans->stra_seteuid;
1013 }
1014 if (ISSET(ans->stra_flags, SYSTR_FLAGS_SETEGID)) {
1015 SET(strp->flags, STR_PROC_SETEGID);
1016 strp->setegid = ans->stra_setegid;
1017 }
1018
1019
1020 /* Clearing the flag indicates to the process that it woke up */
1021 CLR(strp->flags, STR_PROC_WAITANSWER);
1022 wakeup(strp);
1023 out:
1024
1025 return (error);
1026 }
1027
1028 int
1029 systrace_setscriptname(struct str_process *strp,
1030 struct systrace_scriptname *ans)
1031 {
1032 strlcpy(strp->scriptname, ans->sn_scriptname,
1033 sizeof(strp->scriptname));
1034
1035 return (0);
1036 }
1037
1038 int
1039 systrace_policy(struct fsystrace *fst, struct systrace_policy *pol)
1040 {
1041 struct str_policy *strpol;
1042 struct str_process *strp;
1043
1044 switch(pol->strp_op) {
1045 case SYSTR_POLICY_NEW:
1046 DPRINTF(("%s: new, ents %d\n", __func__,
1047 pol->strp_maxents));
1048 if (pol->strp_maxents <= 0 || pol->strp_maxents > 1024)
1049 return (EINVAL);
1050 strpol = systrace_newpolicy(fst, pol->strp_maxents);
1051 if (strpol == NULL)
1052 return (ENOBUFS);
1053 pol->strp_num = strpol->nr;
1054 break;
1055 case SYSTR_POLICY_ASSIGN:
1056 DPRINTF(("%s: %d -> pid %d\n", __func__,
1057 pol->strp_num, pol->strp_pid));
1058
1059 /* Find right policy by number */
1060 TAILQ_FOREACH(strpol, &fst->policies, next)
1061 if (strpol->nr == pol->strp_num)
1062 break;
1063 if (strpol == NULL)
1064 return (EINVAL);
1065
1066 strp = systrace_findpid(fst, pol->strp_pid);
1067 if (strp == NULL)
1068 return (EINVAL);
1069
1070 /* Check that emulation matches */
1071 if (strpol->emul && strpol->emul != strp->proc->p_emul)
1072 return (EINVAL);
1073
1074 if (strp->policy)
1075 systrace_closepolicy(fst, strp->policy);
1076 strp->policy = strpol;
1077 strpol->refcount++;
1078
1079 /* Record emulation for this policy */
1080 if (strpol->emul == NULL)
1081 strpol->emul = strp->proc->p_emul;
1082
1083 break;
1084 case SYSTR_POLICY_MODIFY:
1085 DPRINTF(("%s: %d: code %d -> policy %d\n", __func__,
1086 pol->strp_num, pol->strp_code, pol->strp_policy));
1087 if (!POLICY_VALID(pol->strp_policy))
1088 return (EINVAL);
1089 TAILQ_FOREACH(strpol, &fst->policies, next)
1090 if (strpol->nr == pol->strp_num)
1091 break;
1092 if (strpol == NULL)
1093 return (EINVAL);
1094 if (pol->strp_code < 0 || pol->strp_code >= strpol->nsysent)
1095 return (EINVAL);
1096 strpol->sysent[pol->strp_code] = pol->strp_policy;
1097 break;
1098 default:
1099 return (EINVAL);
1100 }
1101
1102 return (0);
1103 }
1104
1105 int
1106 systrace_processready(struct str_process *strp)
1107 {
1108 if (ISSET(strp->flags, STR_PROC_ONQUEUE))
1109 return (EBUSY);
1110
1111 if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
1112 return (EBUSY);
1113
1114 /* XXX - ignore until systrace knows about lwps. :-(
1115 if (strp->proc->p_stat != LSSLEEP)
1116 return (EBUSY);
1117 */
1118 return (0);
1119 }
1120
1121 int
1122 systrace_getcwd(struct fsystrace *fst, struct str_process *strp)
1123 {
1124 #ifdef __NetBSD__
1125 struct cwdinfo *mycwdp, *cwdp;
1126 #else
1127 struct filedesc *myfdp, *fdp;
1128 #endif
1129 int error;
1130
1131 DPRINTF(("%s: %d\n", __func__, strp->pid));
1132
1133 error = systrace_processready(strp);
1134 if (error)
1135 return (error);
1136
1137 #ifdef __NetBSD__
1138 mycwdp = curproc->p_cwdi;
1139 cwdp = strp->proc->p_cwdi;
1140 if (mycwdp == NULL || cwdp == NULL)
1141 return (EINVAL);
1142
1143 /* Store our current values */
1144 fst->fd_pid = strp->pid;
1145 fst->fd_cdir = mycwdp->cwdi_cdir;
1146 fst->fd_rdir = mycwdp->cwdi_rdir;
1147
1148 if ((mycwdp->cwdi_cdir = cwdp->cwdi_cdir) != NULL)
1149 VREF(mycwdp->cwdi_cdir);
1150 if ((mycwdp->cwdi_rdir = cwdp->cwdi_rdir) != NULL)
1151 VREF(mycwdp->cwdi_rdir);
1152 #else
1153 myfdp = curlwp->p_fd;
1154 fdp = strp->proc->p_fd;
1155 if (myfdp == NULL || fdp == NULL)
1156 return (EINVAL);
1157
1158 /* Store our current values */
1159 fst->fd_pid = strp->pid;
1160 fst->fd_cdir = myfdp->fd_cdir;
1161 fst->fd_rdir = myfdp->fd_rdir;
1162
1163 if ((myfdp->fd_cdir = fdp->fd_cdir) != NULL)
1164 VREF(myfdp->fd_cdir);
1165 if ((myfdp->fd_rdir = fdp->fd_rdir) != NULL)
1166 VREF(myfdp->fd_rdir);
1167 #endif
1168
1169 return (0);
1170 }
1171
1172 int
1173 systrace_io(struct str_process *strp, struct systrace_io *io)
1174 {
1175 struct proc *t = strp->proc;
1176 struct lwp *l = curlwp;
1177 struct uio uio;
1178 struct iovec iov;
1179 int error = 0;
1180
1181 DPRINTF(("%s: %u: %p(%lu)\n", __func__,
1182 io->strio_pid, io->strio_offs, (u_long)io->strio_len));
1183
1184 switch (io->strio_op) {
1185 case SYSTR_READ:
1186 uio.uio_rw = UIO_READ;
1187 break;
1188 case SYSTR_WRITE:
1189 uio.uio_rw = UIO_WRITE;
1190 break;
1191 default:
1192 return (EINVAL);
1193 }
1194
1195 error = systrace_processready(strp);
1196 if (error)
1197 goto out;
1198
1199 iov.iov_base = io->strio_addr;
1200 iov.iov_len = io->strio_len;
1201 uio.uio_iov = &iov;
1202 uio.uio_iovcnt = 1;
1203 uio.uio_offset = (off_t)(unsigned long)io->strio_offs;
1204 uio.uio_resid = io->strio_len;
1205 uio.uio_vmspace = l->l_proc->p_vmspace;
1206
1207 error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSYSTRACE,
1208 t, NULL, NULL, NULL);
1209 if (error)
1210 return (error);
1211
1212 #ifdef __NetBSD__
1213 error = process_domem(l, proc_representative_lwp(t), &uio);
1214 #else
1215 error = procfs_domem(p, t, NULL, &uio);
1216 #endif
1217 io->strio_len -= uio.uio_resid;
1218 out:
1219
1220 return (error);
1221 }
1222
1223 int
1224 systrace_attach(struct fsystrace *fst, pid_t pid)
1225 {
1226 int error = 0;
1227 struct proc *proc, *p = curproc;
1228
1229 if ((proc = pfind(pid)) == NULL) {
1230 error = ESRCH;
1231 goto out;
1232 }
1233
1234 if (ISSET(proc->p_flag, P_INEXEC)) {
1235 error = EAGAIN;
1236 goto out;
1237 }
1238
1239 /*
1240 * You can't attach to a process if:
1241 * (1) it's the process that's doing the attaching,
1242 */
1243 if (proc->p_pid == p->p_pid) {
1244 error = EINVAL;
1245 goto out;
1246 }
1247
1248 /*
1249 * (2) it's a system process
1250 */
1251 if (ISSET(proc->p_flag, P_SYSTEM)) {
1252 error = EPERM;
1253 goto out;
1254 }
1255
1256 /*
1257 * (3) it's being traced already
1258 */
1259 if (ISSET(proc->p_flag, P_SYSTRACE)) {
1260 error = EBUSY;
1261 goto out;
1262 }
1263
1264 /*
1265 * (4) the security model prevents it it.
1266 */
1267 error = kauth_authorize_process(kauth_cred_get(),
1268 KAUTH_PROCESS_CANSYSTRACE, proc, NULL, NULL, NULL);
1269 if (error)
1270 goto out;
1271
1272 error = systrace_insert_process(fst, proc, NULL);
1273
1274 #if defined(__NetBSD__) && defined(__HAVE_SYSCALL_INTERN)
1275 /*
1276 * Make sure we're using the version of the syscall handler that
1277 * has systrace hooks.
1278 */
1279 if (!error)
1280 (*proc->p_emul->e_syscall_intern)(proc);
1281 #endif
1282 out:
1283 return (error);
1284 }
1285
1286 void
1287 systrace_execve0(struct proc *p)
1288 {
1289 struct str_process *strp;
1290
1291 systrace_lock();
1292 strp = p->p_systrace;
1293 strp->isscript = 0;
1294 systrace_unlock();
1295 }
1296
1297 void
1298 systrace_execve1(char *path, struct proc *p)
1299 {
1300 struct str_process *strp;
1301 struct fsystrace *fst;
1302 struct str_message msg;
1303 struct str_msg_execve *msg_execve;
1304
1305 do {
1306 systrace_lock();
1307 strp = p->p_systrace;
1308 if (strp == NULL) {
1309 systrace_unlock();
1310 return;
1311 }
1312
1313 msg_execve = &msg.msg_data.msg_execve;
1314 fst = strp->parent;
1315 SYSTRACE_LOCK(fst, curlwp);
1316 systrace_unlock();
1317
1318 /*
1319 * susers will get the execve call anyway. Also, if
1320 * we're not allowed to control the process, escape.
1321 */
1322 if (fst->issuser ||
1323 fst->p_ruid != kauth_cred_getuid(p->p_cred) ||
1324 fst->p_rgid != kauth_cred_getgid(p->p_cred)) {
1325 SYSTRACE_UNLOCK(fst, curlwp);
1326 return;
1327 }
1328
1329 strlcpy(msg_execve->path, path, sizeof(msg_execve->path));
1330 } while (systrace_make_msg(strp, SYSTR_MSG_EXECVE, &msg) != 0);
1331 }
1332
1333 /* Prepare to replace arguments */
1334
1335 int
1336 systrace_preprepl(struct str_process *strp, struct systrace_replace *repl)
1337 {
1338 size_t len;
1339 int i, ret = 0;
1340
1341 ret = systrace_processready(strp);
1342 if (ret)
1343 return (ret);
1344
1345 systrace_replacefree(strp);
1346
1347 if (repl->strr_nrepl < 0 || repl->strr_nrepl > SYSTR_MAXARGS)
1348 return (EINVAL);
1349
1350 for (i = 0, len = 0; i < repl->strr_nrepl; i++) {
1351 if (repl->strr_argind[i] < 0 ||
1352 repl->strr_argind[i] >= SYSTR_MAXARGS)
1353 return (EINVAL);
1354 if (repl->strr_offlen[i] == 0)
1355 continue;
1356 len += repl->strr_offlen[i];
1357 if (repl->strr_offlen[i] > SYSTR_MAXREPLEN ||
1358 repl->strr_off[i] > SYSTR_MAXREPLEN ||
1359 len > SYSTR_MAXREPLEN)
1360 return (EINVAL);
1361 if (repl->strr_offlen[i] + repl->strr_off[i] > len)
1362 return (EINVAL);
1363 }
1364
1365 /* Make sure that the length adds up */
1366 if (repl->strr_len != len)
1367 return (EINVAL);
1368
1369 /* Check against a maximum length */
1370 if (repl->strr_len > SYSTR_MAXREPLEN)
1371 return (EINVAL);
1372
1373 strp->replace = (struct systrace_replace *)
1374 malloc(sizeof(struct systrace_replace) + len, M_XDATA, M_WAITOK);
1375
1376 memcpy(strp->replace, repl, sizeof(struct systrace_replace));
1377 ret = copyin(repl->strr_base, strp->replace + 1, len);
1378 if (ret) {
1379 free(strp->replace, M_XDATA);
1380 strp->replace = NULL;
1381 return (ret);
1382 }
1383
1384 /* Adjust the offset */
1385 repl = strp->replace;
1386 repl->strr_base = (caddr_t)(repl + 1);
1387
1388 return (0);
1389 }
1390
1391 /*
1392 * Replace the arguments with arguments from the monitoring process.
1393 */
1394
1395 int
1396 systrace_replace(struct str_process *strp, size_t argsize, register_t args[])
1397 {
1398 struct proc *p = strp->proc;
1399 struct systrace_replace *repl = strp->replace;
1400 caddr_t sg, kdata, udata, kbase, ubase;
1401 int i, maxarg, ind, ret = 0;
1402
1403 maxarg = argsize/sizeof(register_t);
1404 #ifdef __NetBSD__
1405 sg = stackgap_init(p, 0);
1406 ubase = stackgap_alloc(p, &sg, repl->strr_len);
1407 #else
1408 sg = stackgap_init(p->p_emul);
1409 ubase = stackgap_alloc(&sg, repl->strr_len);
1410 #endif
1411 if (ubase == NULL) {
1412 ret = EINVAL;
1413 goto out;
1414 }
1415
1416 kbase = repl->strr_base;
1417 for (i = 0; i < maxarg && i < repl->strr_nrepl; i++) {
1418 ind = repl->strr_argind[i];
1419 if (ind < 0 || ind >= maxarg) {
1420 ret = EINVAL;
1421 goto out;
1422 }
1423 if (repl->strr_offlen[i] == 0) {
1424 args[ind] = repl->strr_off[i];
1425 continue;
1426 }
1427 kdata = kbase + repl->strr_off[i];
1428 udata = ubase + repl->strr_off[i];
1429 if (repl->strr_flags[i] & SYSTR_NOLINKS) {
1430 ret = systrace_fname(strp, kdata, repl->strr_offlen[i]);
1431 if (ret != 0)
1432 goto out;
1433 }
1434 if (copyout(kdata, udata, repl->strr_offlen[i])) {
1435 ret = EINVAL;
1436 goto out;
1437 }
1438
1439 /* Replace the argument with the new address */
1440 args[ind] = (register_t)(intptr_t)udata;
1441 }
1442
1443 out:
1444 return (ret);
1445 }
1446
1447 int
1448 systrace_fname(struct str_process *strp, caddr_t kdata, size_t len)
1449 {
1450 if (strp->nfname >= SYSTR_MAXFNAME || len < 2)
1451 return EINVAL;
1452
1453 strp->fname[strp->nfname] = kdata;
1454 strp->fname[strp->nfname][len - 1] = '\0';
1455 strp->nfname++;
1456
1457 return 0;
1458 }
1459
1460 void
1461 systrace_replacefree(struct str_process *strp)
1462 {
1463
1464 if (strp->replace != NULL) {
1465 free(strp->replace, M_XDATA);
1466 strp->replace = NULL;
1467 }
1468 while (strp->nfname > 0) {
1469 strp->nfname--;
1470 strp->fname[strp->nfname] = NULL;
1471 }
1472 }
1473
1474 int
1475 systrace_scriptname(struct proc *p, char *dst)
1476 {
1477 struct str_process *strp;
1478 struct fsystrace *fst;
1479 int error = 0;
1480
1481 systrace_lock();
1482 strp = p->p_systrace;
1483 if (strp == NULL) {
1484 systrace_unlock();
1485 return (EINVAL);
1486 }
1487
1488 fst = strp->parent;
1489
1490 SYSTRACE_LOCK(fst, curlwp);
1491 systrace_unlock();
1492
1493 if (!fst->issuser && (ISSET(p->p_flag, P_SUGID) ||
1494 fst->p_ruid != kauth_cred_getuid(p->p_cred) ||
1495 fst->p_rgid != kauth_cred_getgid(p->p_cred))) {
1496 error = EPERM;
1497 goto out;
1498 }
1499
1500 if (strp->scriptname[0] == '\0') {
1501 error = ENOENT;
1502 goto out;
1503 }
1504
1505 strlcpy(dst, strp->scriptname, MAXPATHLEN);
1506 strp->isscript = 1;
1507
1508 out:
1509 strp->scriptname[0] = '\0';
1510 SYSTRACE_UNLOCK(fst, curlwp);
1511
1512 return (error);
1513 }
1514
1515 void
1516 systrace_namei(struct nameidata *ndp)
1517 {
1518 struct str_process *strp;
1519 struct fsystrace *fst = NULL; /* XXXGCC */
1520 struct componentname *cnp = &ndp->ni_cnd;
1521 size_t i;
1522 int hamper = 0;
1523
1524 systrace_lock();
1525 strp = cnp->cn_lwp->l_proc->p_systrace;
1526 if (strp != NULL) {
1527 fst = strp->parent;
1528 SYSTRACE_LOCK(fst, curlwp);
1529 systrace_unlock();
1530
1531 for (i = 0; i < strp->nfname; i++) {
1532 if (strcmp(cnp->cn_pnbuf, strp->fname[i]) == 0) {
1533 hamper = 1;
1534 break;
1535 }
1536 }
1537
1538 if (!hamper && strp->isscript &&
1539 strcmp(cnp->cn_pnbuf, strp->scriptname) == 0)
1540 hamper = 1;
1541
1542 SYSTRACE_UNLOCK(fst, curlwp);
1543 } else
1544 systrace_unlock();
1545
1546 if (hamper) {
1547 /* ELOOP if namei() tries to readlink */
1548 ndp->ni_loopcnt = MAXSYMLINKS;
1549 cnp->cn_flags &= ~FOLLOW;
1550 cnp->cn_flags |= NOFOLLOW;
1551 }
1552 }
1553
1554 struct str_process *
1555 systrace_findpid(struct fsystrace *fst, pid_t pid)
1556 {
1557 struct str_process *strp;
1558 struct proc *proc = NULL;
1559
1560 TAILQ_FOREACH(strp, &fst->processes, next)
1561 if (strp->pid == pid)
1562 break;
1563
1564 if (strp == NULL)
1565 return (NULL);
1566
1567 proc = systrace_find(strp);
1568
1569 return (proc ? strp : NULL);
1570 }
1571
1572 int
1573 systrace_detach(struct str_process *strp)
1574 {
1575 struct proc *proc;
1576 struct fsystrace *fst = NULL;
1577 int error = 0;
1578
1579 DPRINTF(("%s: Trying to detach from %d\n", __func__, strp->pid));
1580
1581 if ((proc = systrace_find(strp)) != NULL) {
1582 CLR(proc->p_flag, P_SYSTRACE);
1583 proc->p_systrace = NULL;
1584 } else
1585 error = ESRCH;
1586
1587 if (ISSET(strp->flags, STR_PROC_WAITANSWER)) {
1588 CLR(strp->flags, STR_PROC_WAITANSWER);
1589 wakeup(strp);
1590 }
1591
1592 fst = strp->parent;
1593 systrace_wakeup(fst);
1594
1595 TAILQ_REMOVE(&fst->processes, strp, next);
1596 fst->nprocesses--;
1597
1598 if (strp->policy)
1599 systrace_closepolicy(fst, strp->policy);
1600 systrace_replacefree(strp);
1601 pool_put(&systr_proc_pl, strp);
1602
1603 return (error);
1604 }
1605
1606 void
1607 systrace_closepolicy(struct fsystrace *fst, struct str_policy *policy)
1608 {
1609 if (--policy->refcount)
1610 return;
1611
1612 fst->npolicies--;
1613
1614 if (policy->nsysent)
1615 free(policy->sysent, M_XDATA);
1616
1617 TAILQ_REMOVE(&fst->policies, policy, next);
1618
1619 pool_put(&systr_policy_pl, policy);
1620 }
1621
1622
1623 int
1624 systrace_insert_process(struct fsystrace *fst, struct proc *proc,
1625 struct str_process **pstrp)
1626 {
1627 struct str_process *strp;
1628
1629 strp = pool_get(&systr_proc_pl, PR_NOWAIT);
1630 if (strp == NULL)
1631 return (ENOBUFS);
1632
1633 memset((caddr_t)strp, 0, sizeof(struct str_process));
1634 strp->pid = proc->p_pid;
1635 strp->proc = proc;
1636 strp->parent = fst;
1637
1638 TAILQ_INSERT_TAIL(&fst->processes, strp, next);
1639 fst->nprocesses++;
1640
1641 proc->p_systrace = strp;
1642 SET(proc->p_flag, P_SYSTRACE);
1643
1644 /* Pass the new pointer back to the caller */
1645 if (pstrp != NULL)
1646 *pstrp = strp;
1647
1648 return (0);
1649 }
1650
1651 struct str_policy *
1652 systrace_newpolicy(struct fsystrace *fst, int maxents)
1653 {
1654 struct str_policy *pol;
1655 int i;
1656
1657 if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) {
1658 struct str_policy *tmp;
1659
1660 /* Try to find a policy for freeing */
1661 TAILQ_FOREACH(tmp, &fst->policies, next) {
1662 if (tmp->refcount == 1)
1663 break;
1664 }
1665
1666 if (tmp == NULL)
1667 return (NULL);
1668
1669 /* Notify userland about freed policy */
1670 systrace_msg_policyfree(fst, tmp);
1671 /* Free this policy */
1672 systrace_closepolicy(fst, tmp);
1673 }
1674
1675 pol = pool_get(&systr_policy_pl, PR_NOWAIT);
1676 if (pol == NULL)
1677 return (NULL);
1678
1679 DPRINTF(("%s: allocating %d -> %lu\n", __func__,
1680 maxents, (u_long)maxents * sizeof(int)));
1681
1682 memset((caddr_t)pol, 0, sizeof(struct str_policy));
1683
1684 pol->sysent = (u_char *)malloc(maxents * sizeof(u_char),
1685 M_XDATA, M_WAITOK);
1686 pol->nsysent = maxents;
1687 for (i = 0; i < maxents; i++)
1688 pol->sysent[i] = SYSTR_POLICY_ASK;
1689
1690 fst->npolicies++;
1691 pol->nr = fst->npolicynr++;
1692 pol->refcount = 1;
1693
1694 TAILQ_INSERT_TAIL(&fst->policies, pol, next);
1695
1696 return (pol);
1697 }
1698
1699 int
1700 systrace_msg_ask(struct fsystrace *fst, struct str_process *strp, int code,
1701 size_t argsize, register_t args[])
1702 {
1703 struct str_message msg;
1704 struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
1705 int i;
1706
1707 msg_ask->code = code;
1708 msg_ask->argsize = argsize;
1709 for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
1710 msg_ask->args[i] = args[i];
1711
1712 return (systrace_make_msg(strp, SYSTR_MSG_ASK, &msg));
1713 }
1714
1715 int
1716 systrace_msg_result(struct fsystrace *fst, struct str_process *strp, int error,
1717 int code, size_t argsize, register_t args[], register_t rval[])
1718 {
1719 struct str_message msg;
1720 struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
1721 int i;
1722
1723 msg_ask->code = code;
1724 msg_ask->argsize = argsize;
1725 msg_ask->result = error;
1726 for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
1727 msg_ask->args[i] = args[i];
1728
1729 msg_ask->rval[0] = rval[0];
1730 msg_ask->rval[1] = rval[1];
1731
1732 return (systrace_make_msg(strp, SYSTR_MSG_RES, &msg));
1733 }
1734
1735 int
1736 systrace_msg_emul(struct fsystrace *fst, struct str_process *strp)
1737 {
1738 struct str_message msg;
1739 struct str_msg_emul *msg_emul = &msg.msg_data.msg_emul;
1740 struct proc *p = strp->proc;
1741
1742 memcpy(msg_emul->emul, p->p_emul->e_name, SYSTR_EMULEN);
1743
1744 return (systrace_make_msg(strp, SYSTR_MSG_EMUL, &msg));
1745 }
1746
1747 int
1748 systrace_msg_ugid(struct fsystrace *fst, struct str_process *strp)
1749 {
1750 struct str_message msg;
1751 struct str_msg_ugid *msg_ugid = &msg.msg_data.msg_ugid;
1752 struct proc *p = strp->proc;
1753
1754 msg_ugid->uid = kauth_cred_getuid(p->p_cred);
1755 msg_ugid->gid = kauth_cred_getgid(p->p_cred);
1756
1757 return (systrace_make_msg(strp, SYSTR_MSG_UGID, &msg));
1758 }
1759
1760 int
1761 systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg)
1762 {
1763 struct str_msgcontainer *cont;
1764 struct str_message *msg;
1765 struct fsystrace *fst = strp->parent;
1766 int st;
1767
1768 cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
1769 memset(cont, 0, sizeof(struct str_msgcontainer));
1770 cont->strp = strp;
1771
1772 msg = &cont->msg;
1773
1774 /* Copy the already filled in fields */
1775 memcpy(&msg->msg_data, &tmsg->msg_data, sizeof(msg->msg_data));
1776
1777 /* Add the extra fields to the message */
1778 msg->msg_seqnr = ++strp->seqnr;
1779 msg->msg_type = type;
1780 msg->msg_pid = strp->pid;
1781 if (strp->policy)
1782 msg->msg_policy = strp->policy->nr;
1783 else
1784 msg->msg_policy = -1;
1785
1786 SET(strp->flags, STR_PROC_WAITANSWER);
1787 if (ISSET(strp->flags, STR_PROC_ONQUEUE))
1788 goto out;
1789
1790 TAILQ_INSERT_TAIL(&fst->messages, cont, next);
1791 SET(strp->flags, STR_PROC_ONQUEUE);
1792
1793 out:
1794 systrace_wakeup(fst);
1795
1796 /* Release the lock - XXX */
1797 SYSTRACE_UNLOCK(fst, strp->proc);
1798
1799 while (1) {
1800 int f;
1801 f = curlwp->l_flag & L_SA;
1802 curlwp->l_flag &= ~L_SA;
1803 st = tsleep(strp, PWAIT, "systrmsg", 0);
1804 curlwp->l_flag |= f;
1805 if (st != 0)
1806 return (ERESTART);
1807 /* If we detach, then everything is permitted */
1808 if ((strp = curproc->p_systrace) == NULL)
1809 return (0);
1810 if (!ISSET(strp->flags, STR_PROC_WAITANSWER))
1811 break;
1812 }
1813
1814 return (0);
1815 }
1816
1817 int
1818 systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid)
1819 {
1820 struct str_msgcontainer *cont;
1821 struct str_message *msg;
1822 struct str_msg_child *msg_child;
1823
1824 cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
1825 memset(cont, 0, sizeof(struct str_msgcontainer));
1826 cont->strp = strp;
1827
1828 msg = &cont->msg;
1829
1830 DPRINTF(("%s: %p: pid %d -> pid %d\n", __func__,
1831 msg, strp->pid, npid));
1832
1833 msg_child = &msg->msg_data.msg_child;
1834
1835 msg->msg_type = SYSTR_MSG_CHILD;
1836 msg->msg_pid = strp->pid;
1837 if (strp->policy)
1838 msg->msg_policy = strp->policy->nr;
1839 else
1840 msg->msg_policy = -1;
1841 msg_child->new_pid = npid;
1842
1843 TAILQ_INSERT_TAIL(&fst->messages, cont, next);
1844
1845 systrace_wakeup(fst);
1846
1847 return (0);
1848 }
1849
1850 int
1851 systrace_msg_policyfree(struct fsystrace *fst, struct str_policy *strpol)
1852 {
1853 struct str_msgcontainer *cont;
1854 struct str_message *msg;
1855
1856 cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
1857 memset(cont, 0, sizeof(struct str_msgcontainer));
1858
1859 msg = &cont->msg;
1860
1861 DPRINTF(("%s: free %d\n", __func__, strpol->nr));
1862
1863 msg->msg_type = SYSTR_MSG_POLICYFREE;
1864 msg->msg_policy = strpol->nr;
1865
1866 TAILQ_INSERT_TAIL(&fst->messages, cont, next);
1867
1868 systrace_wakeup(fst);
1869
1870 return (0);
1871 }
Cache object: 7b99fa5c1d4b93808896e5ddd4991127
|