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