xref: /freebsd/sys/dev/filemon/filemon_wrapper.c (revision c9dbb1cc52b063bbd9ab078a7afc89a8696da659)
1 /*-
2  * Copyright (c) 2011, David E. O'Brien.
3  * Copyright (c) 2009-2011, Juniper Networks, Inc.
4  * Copyright (c) 2015, EMC Corp.
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  *
16  * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/sx.h>
33 
34 #include "opt_compat.h"
35 
36 #if __FreeBSD_version > 800032
37 #define FILEMON_HAS_LINKAT
38 #endif
39 
40 #if __FreeBSD_version < 900044	/* r225617 (2011-09-16) failed to bump
41 				   __FreeBSD_version.  This really should
42 				   be based on "900045".  "900044" is r225469
43 				   (2011-09-10) so this code is broken for
44 				   9-CURRENT September 10th-16th. */
45 #define sys_chdir	chdir
46 #define sys_execve	execve
47 #define sys_fork	fork
48 #define sys_link	link
49 #define sys_open	open
50 #define sys_rename	rename
51 #define sys_stat	stat
52 #define sys_symlink	symlink
53 #define sys_unlink	unlink
54 #define sys_vfork	vfork
55 #define sys_sys_exit	sys_exit
56 #ifdef FILEMON_HAS_LINKAT
57 #define sys_linkat	linkat
58 #endif
59 #endif	/* __FreeBSD_version */
60 
61 static void
62 filemon_output(struct filemon *filemon, char *msg, size_t len)
63 {
64 	struct uio auio;
65 	struct iovec aiov;
66 
67 	if (filemon->fp == NULL)
68 		return;
69 
70 	aiov.iov_base = msg;
71 	aiov.iov_len = len;
72 	auio.uio_iov = &aiov;
73 	auio.uio_iovcnt = 1;
74 	auio.uio_resid = len;
75 	auio.uio_segflg = UIO_SYSSPACE;
76 	auio.uio_rw = UIO_WRITE;
77 	auio.uio_td = curthread;
78 	auio.uio_offset = (off_t) -1;
79 
80 	bwillwrite();
81 
82 	fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
83 }
84 
85 static struct filemon *
86 filemon_pid_check(struct proc *p)
87 {
88 	struct filemon *filemon;
89 
90 	filemon_lock_read();
91 	if (TAILQ_EMPTY(&filemons_inuse)) {
92 		filemon_unlock_read();
93 		return (NULL);
94 	}
95 	sx_slock(&proctree_lock);
96 	while (p != initproc) {
97 		TAILQ_FOREACH(filemon, &filemons_inuse, link) {
98 			if (p->p_pid == filemon->pid) {
99 				sx_sunlock(&proctree_lock);
100 				filemon_filemon_lock(filemon);
101 				filemon_unlock_read();
102 				return (filemon);
103 			}
104 		}
105 		p = proc_realparent(p);
106 	}
107 	sx_sunlock(&proctree_lock);
108 	filemon_unlock_read();
109 	return (NULL);
110 }
111 
112 static void
113 filemon_comment(struct filemon *filemon)
114 {
115 	int len;
116 	struct timeval now;
117 
118 	/* Load timestamp before locking.  Less accurate but less contention. */
119 	getmicrotime(&now);
120 
121 	/* Lock the found filemon structure. */
122 	filemon_filemon_lock(filemon);
123 
124 	len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
125 	    "# filemon version %d\n# Target pid %d\n# Start %ju.%06ju\nV %d\n",
126 	    FILEMON_VERSION, curproc->p_pid, (uintmax_t)now.tv_sec,
127 	    (uintmax_t)now.tv_usec, FILEMON_VERSION);
128 
129 	filemon_output(filemon, filemon->msgbufr, len);
130 
131 	/* Unlock the found filemon structure. */
132 	filemon_filemon_unlock(filemon);
133 }
134 
135 static int
136 filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
137 {
138 	int ret;
139 	size_t done;
140 	size_t len;
141 	struct filemon *filemon;
142 
143 	if ((ret = sys_chdir(td, uap)) == 0) {
144 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
145 			copyinstr(uap->path, filemon->fname1,
146 			    sizeof(filemon->fname1), &done);
147 
148 			len = snprintf(filemon->msgbufr,
149 			    sizeof(filemon->msgbufr), "C %d %s\n",
150 			    curproc->p_pid, filemon->fname1);
151 
152 			filemon_output(filemon, filemon->msgbufr, len);
153 
154 			/* Unlock the found filemon structure. */
155 			filemon_filemon_unlock(filemon);
156 		}
157 	}
158 
159 	return (ret);
160 }
161 
162 static int
163 filemon_wrapper_execve(struct thread *td, struct execve_args *uap)
164 {
165 	char fname[MAXPATHLEN];
166 	int ret;
167 	size_t done;
168 	size_t len;
169 	struct filemon *filemon;
170 
171 	copyinstr(uap->fname, fname, sizeof(fname), &done);
172 
173 	if ((ret = sys_execve(td, uap)) == 0) {
174 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
175 			len = snprintf(filemon->msgbufr,
176 			    sizeof(filemon->msgbufr), "E %d %s\n",
177 			    curproc->p_pid, fname);
178 
179 			filemon_output(filemon, filemon->msgbufr, len);
180 
181 			/* Unlock the found filemon structure. */
182 			filemon_filemon_unlock(filemon);
183 		}
184 	}
185 
186 	return (ret);
187 }
188 
189 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
190 static int
191 filemon_wrapper_freebsd32_execve(struct thread *td,
192     struct freebsd32_execve_args *uap)
193 {
194 	char fname[MAXPATHLEN];
195 	int ret;
196 	size_t done;
197 	size_t len;
198 	struct filemon *filemon;
199 
200 	copyinstr(uap->fname, fname, sizeof(fname), &done);
201 
202 	if ((ret = freebsd32_execve(td, uap)) == 0) {
203 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
204 			len = snprintf(filemon->msgbufr,
205 			    sizeof(filemon->msgbufr), "E %d %s\n",
206 			    curproc->p_pid, fname);
207 
208 			filemon_output(filemon, filemon->msgbufr, len);
209 
210 			/* Unlock the found filemon structure. */
211 			filemon_filemon_unlock(filemon);
212 		}
213 	}
214 
215 	return (ret);
216 }
217 #endif
218 
219 static int
220 filemon_wrapper_fork(struct thread *td, struct fork_args *uap)
221 {
222 	int ret;
223 	size_t len;
224 	struct filemon *filemon;
225 
226 	if ((ret = sys_fork(td, uap)) == 0) {
227 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
228 			len = snprintf(filemon->msgbufr,
229 			    sizeof(filemon->msgbufr), "F %d %ld\n",
230 			    curproc->p_pid, (long)curthread->td_retval[0]);
231 
232 			filemon_output(filemon, filemon->msgbufr, len);
233 
234 			/* Unlock the found filemon structure. */
235 			filemon_filemon_unlock(filemon);
236 		}
237 	}
238 
239 	return (ret);
240 }
241 
242 static int
243 filemon_wrapper_open(struct thread *td, struct open_args *uap)
244 {
245 	int ret;
246 	size_t done;
247 	size_t len;
248 	struct filemon *filemon;
249 
250 	if ((ret = sys_open(td, uap)) == 0) {
251 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
252 			copyinstr(uap->path, filemon->fname1,
253 			    sizeof(filemon->fname1), &done);
254 
255 			if (uap->flags & O_RDWR) {
256 				/*
257 				 * We'll get the W record below, but need
258 				 * to also output an R to distingish from
259 				 * O_WRONLY.
260 				 */
261 				len = snprintf(filemon->msgbufr,
262 				    sizeof(filemon->msgbufr), "R %d %s\n",
263 				    curproc->p_pid, filemon->fname1);
264 				filemon_output(filemon, filemon->msgbufr, len);
265 			}
266 
267 
268 			len = snprintf(filemon->msgbufr,
269 			    sizeof(filemon->msgbufr), "%c %d %s\n",
270 			    (uap->flags & O_ACCMODE) ? 'W':'R',
271 			    curproc->p_pid, filemon->fname1);
272 			filemon_output(filemon, filemon->msgbufr, len);
273 
274 			/* Unlock the found filemon structure. */
275 			filemon_filemon_unlock(filemon);
276 		}
277 	}
278 
279 	return (ret);
280 }
281 
282 static int
283 filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
284 {
285 	int ret;
286 	size_t done;
287 	size_t len;
288 	struct filemon *filemon;
289 
290 	if ((ret = sys_openat(td, uap)) == 0) {
291 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
292 			copyinstr(uap->path, filemon->fname1,
293 			    sizeof(filemon->fname1), &done);
294 
295 			filemon->fname2[0] = '\0';
296 			if (filemon->fname1[0] != '/' && uap->fd != AT_FDCWD) {
297 				/*
298 				 * rats - we cannot do too much about this.
299 				 * the trace should show a dir we read
300 				 * recently.. output an A record as a clue
301 				 * until we can do better.
302 				 */
303 				len = snprintf(filemon->msgbufr,
304 				    sizeof(filemon->msgbufr), "A %d %s\n",
305 				    curproc->p_pid, filemon->fname1);
306 				filemon_output(filemon, filemon->msgbufr, len);
307 			}
308 			if (uap->flag & O_RDWR) {
309 				/*
310 				 * We'll get the W record below, but need
311 				 * to also output an R to distingish from
312 				 * O_WRONLY.
313 				 */
314 				len = snprintf(filemon->msgbufr,
315 				    sizeof(filemon->msgbufr), "R %d %s%s\n",
316 				    curproc->p_pid, filemon->fname2, filemon->fname1);
317 				filemon_output(filemon, filemon->msgbufr, len);
318 			}
319 
320 
321 			len = snprintf(filemon->msgbufr,
322 			    sizeof(filemon->msgbufr), "%c %d %s%s\n",
323 			    (uap->flag & O_ACCMODE) ? 'W':'R',
324 			    curproc->p_pid, filemon->fname2, filemon->fname1);
325 			filemon_output(filemon, filemon->msgbufr, len);
326 
327 			/* Unlock the found filemon structure. */
328 			filemon_filemon_unlock(filemon);
329 		}
330 	}
331 
332 	return (ret);
333 }
334 
335 static int
336 filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
337 {
338 	int ret;
339 	size_t done;
340 	size_t len;
341 	struct filemon *filemon;
342 
343 	if ((ret = sys_rename(td, uap)) == 0) {
344 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
345 			copyinstr(uap->from, filemon->fname1,
346 			    sizeof(filemon->fname1), &done);
347 			copyinstr(uap->to, filemon->fname2,
348 			    sizeof(filemon->fname2), &done);
349 
350 			len = snprintf(filemon->msgbufr,
351 			    sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
352 			    curproc->p_pid, filemon->fname1, filemon->fname2);
353 
354 			filemon_output(filemon, filemon->msgbufr, len);
355 
356 			/* Unlock the found filemon structure. */
357 			filemon_filemon_unlock(filemon);
358 		}
359 	}
360 
361 	return (ret);
362 }
363 
364 static int
365 filemon_wrapper_link(struct thread *td, struct link_args *uap)
366 {
367 	int ret;
368 	size_t done;
369 	size_t len;
370 	struct filemon *filemon;
371 
372 	if ((ret = sys_link(td, uap)) == 0) {
373 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
374 			copyinstr(uap->path, filemon->fname1,
375 			    sizeof(filemon->fname1), &done);
376 			copyinstr(uap->link, filemon->fname2,
377 			    sizeof(filemon->fname2), &done);
378 
379 			len = snprintf(filemon->msgbufr,
380 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
381 			    curproc->p_pid, filemon->fname1, filemon->fname2);
382 
383 			filemon_output(filemon, filemon->msgbufr, len);
384 
385 			/* Unlock the found filemon structure. */
386 			filemon_filemon_unlock(filemon);
387 		}
388 	}
389 
390 	return (ret);
391 }
392 
393 static int
394 filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
395 {
396 	int ret;
397 	size_t done;
398 	size_t len;
399 	struct filemon *filemon;
400 
401 	if ((ret = sys_symlink(td, uap)) == 0) {
402 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
403 			copyinstr(uap->path, filemon->fname1,
404 			    sizeof(filemon->fname1), &done);
405 			copyinstr(uap->link, filemon->fname2,
406 			    sizeof(filemon->fname2), &done);
407 
408 			len = snprintf(filemon->msgbufr,
409 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
410 			    curproc->p_pid, filemon->fname1, filemon->fname2);
411 
412 			filemon_output(filemon, filemon->msgbufr, len);
413 
414 			/* Unlock the found filemon structure. */
415 			filemon_filemon_unlock(filemon);
416 		}
417 	}
418 
419 	return (ret);
420 }
421 
422 #ifdef FILEMON_HAS_LINKAT
423 static int
424 filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
425 {
426 	int ret;
427 	size_t done;
428 	size_t len;
429 	struct filemon *filemon;
430 
431 	if ((ret = sys_linkat(td, uap)) == 0) {
432 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
433 			copyinstr(uap->path1, filemon->fname1,
434 			    sizeof(filemon->fname1), &done);
435 			copyinstr(uap->path2, filemon->fname2,
436 			    sizeof(filemon->fname2), &done);
437 
438 			len = snprintf(filemon->msgbufr,
439 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
440 			    curproc->p_pid, filemon->fname1, filemon->fname2);
441 
442 			filemon_output(filemon, filemon->msgbufr, len);
443 
444 			/* Unlock the found filemon structure. */
445 			filemon_filemon_unlock(filemon);
446 		}
447 	}
448 
449 	return (ret);
450 }
451 #endif
452 
453 static int
454 filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
455 {
456 	int ret;
457 	size_t done;
458 	size_t len;
459 	struct filemon *filemon;
460 
461 	if ((ret = sys_stat(td, uap)) == 0) {
462 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
463 			copyinstr(uap->path, filemon->fname1,
464 			    sizeof(filemon->fname1), &done);
465 
466 			len = snprintf(filemon->msgbufr,
467 			    sizeof(filemon->msgbufr), "S %d %s\n",
468 			    curproc->p_pid, filemon->fname1);
469 
470 			filemon_output(filemon, filemon->msgbufr, len);
471 
472 			/* Unlock the found filemon structure. */
473 			filemon_filemon_unlock(filemon);
474 		}
475 	}
476 
477 	return (ret);
478 }
479 
480 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
481 static int
482 filemon_wrapper_freebsd32_stat(struct thread *td,
483     struct freebsd32_stat_args *uap)
484 {
485 	int ret;
486 	size_t done;
487 	size_t len;
488 	struct filemon *filemon;
489 
490 	if ((ret = freebsd32_stat(td, uap)) == 0) {
491 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
492 			copyinstr(uap->path, filemon->fname1,
493 			    sizeof(filemon->fname1), &done);
494 
495 			len = snprintf(filemon->msgbufr,
496 			    sizeof(filemon->msgbufr), "S %d %s\n",
497 			    curproc->p_pid, filemon->fname1);
498 
499 			filemon_output(filemon, filemon->msgbufr, len);
500 
501 			/* Unlock the found filemon structure. */
502 			filemon_filemon_unlock(filemon);
503 		}
504 	}
505 
506 	return (ret);
507 }
508 #endif
509 
510 static void
511 filemon_wrapper_sys_exit(struct thread *td, struct sys_exit_args *uap)
512 {
513 	size_t len;
514 	struct filemon *filemon;
515 	struct timeval now;
516 
517 	/* Get timestamp before locking. */
518 	getmicrotime(&now);
519 
520 	if ((filemon = filemon_pid_check(curproc)) != NULL) {
521 		len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
522 		    "X %d %d\n", curproc->p_pid, uap->rval);
523 
524 		filemon_output(filemon, filemon->msgbufr, len);
525 
526 		/* Check if the monitored process is about to exit. */
527 		if (filemon->pid == curproc->p_pid) {
528 			len = snprintf(filemon->msgbufr,
529 			    sizeof(filemon->msgbufr),
530 			    "# Stop %ju.%06ju\n# Bye bye\n",
531 			    (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
532 
533 			filemon_output(filemon, filemon->msgbufr, len);
534 			filemon->pid = -1;
535 		}
536 
537 		/* Unlock the found filemon structure. */
538 		filemon_filemon_unlock(filemon);
539 	}
540 
541 	sys_sys_exit(td, uap);
542 }
543 
544 static int
545 filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
546 {
547 	int ret;
548 	size_t done;
549 	size_t len;
550 	struct filemon *filemon;
551 
552 	if ((ret = sys_unlink(td, uap)) == 0) {
553 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
554 			copyinstr(uap->path, filemon->fname1,
555 			    sizeof(filemon->fname1), &done);
556 
557 			len = snprintf(filemon->msgbufr,
558 			    sizeof(filemon->msgbufr), "D %d %s\n",
559 			    curproc->p_pid, filemon->fname1);
560 
561 			filemon_output(filemon, filemon->msgbufr, len);
562 
563 			/* Unlock the found filemon structure. */
564 			filemon_filemon_unlock(filemon);
565 		}
566 	}
567 
568 	return (ret);
569 }
570 
571 static int
572 filemon_wrapper_vfork(struct thread *td, struct vfork_args *uap)
573 {
574 	int ret;
575 	size_t len;
576 	struct filemon *filemon;
577 
578 	if ((ret = sys_vfork(td, uap)) == 0) {
579 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
580 			len = snprintf(filemon->msgbufr,
581 			    sizeof(filemon->msgbufr), "F %d %ld\n",
582 			    curproc->p_pid, (long)curthread->td_retval[0]);
583 
584 			filemon_output(filemon, filemon->msgbufr, len);
585 
586 			/* Unlock the found filemon structure. */
587 			filemon_filemon_unlock(filemon);
588 		}
589 	}
590 
591 	return (ret);
592 }
593 
594 static void
595 filemon_wrapper_install(void)
596 {
597 #if defined(__LP64__)
598 	struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
599 #else
600 	struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
601 #endif
602 
603 	sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
604 	sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
605 	sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve;
606 	sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
607 	sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
608 	sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
609 	sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
610 	sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat;
611 	sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
612 	sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
613 	sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
614 	sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
615 #ifdef FILEMON_HAS_LINKAT
616 	sv_table[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
617 #endif
618 
619 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
620 	sv_table = ia32_freebsd_sysvec.sv_table;
621 
622 	sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
623 	sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
624 	sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_execve;
625 	sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
626 	sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
627 	sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
628 	sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
629 	sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat;
630 	sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
631 	sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
632 	sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
633 	sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
634 #ifdef FILEMON_HAS_LINKAT
635 	sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
636 #endif
637 #endif	/* COMPAT_ARCH32 */
638 }
639 
640 static void
641 filemon_wrapper_deinstall(void)
642 {
643 #if defined(__LP64__)
644 	struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
645 #else
646 	struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
647 #endif
648 
649 	sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
650 	sv_table[SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
651 	sv_table[SYS_execve].sy_call = (sy_call_t *)sys_execve;
652 	sv_table[SYS_fork].sy_call = (sy_call_t *)sys_fork;
653 	sv_table[SYS_open].sy_call = (sy_call_t *)sys_open;
654 	sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat;
655 	sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename;
656 	sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat;
657 	sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
658 	sv_table[SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
659 	sv_table[SYS_link].sy_call = (sy_call_t *)sys_link;
660 	sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
661 #ifdef FILEMON_HAS_LINKAT
662 	sv_table[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
663 #endif
664 
665 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
666 	sv_table = ia32_freebsd_sysvec.sv_table;
667 
668 	sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
669 	sv_table[FREEBSD32_SYS_exit].sy_call = (sy_call_t *)sys_sys_exit;
670 	sv_table[FREEBSD32_SYS_freebsd32_execve].sy_call = (sy_call_t *)freebsd32_execve;
671 	sv_table[FREEBSD32_SYS_fork].sy_call = (sy_call_t *)sys_fork;
672 	sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
673 	sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
674 	sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
675 	sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat;
676 	sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
677 	sv_table[FREEBSD32_SYS_vfork].sy_call = (sy_call_t *)sys_vfork;
678 	sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
679 	sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
680 #ifdef FILEMON_HAS_LINKAT
681 	sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
682 #endif
683 #endif	/* COMPAT_ARCH32 */
684 }
685