xref: /freebsd/sys/dev/filemon/filemon_wrapper.c (revision 1f4bcc459a76b7aa664f3fd557684cd0ba6da352)
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/imgact.h>
33 #include <sys/eventhandler.h>
34 #include <sys/sx.h>
35 #include <sys/vnode.h>
36 
37 #include "opt_compat.h"
38 
39 #if __FreeBSD_version > 800032
40 #define FILEMON_HAS_LINKAT
41 #endif
42 
43 #if __FreeBSD_version < 900044	/* r225617 (2011-09-16) failed to bump
44 				   __FreeBSD_version.  This really should
45 				   be based on "900045".  "900044" is r225469
46 				   (2011-09-10) so this code is broken for
47 				   9-CURRENT September 10th-16th. */
48 #define sys_chdir	chdir
49 #define sys_link	link
50 #define sys_open	open
51 #define sys_rename	rename
52 #define sys_stat	stat
53 #define sys_symlink	symlink
54 #define sys_unlink	unlink
55 #ifdef FILEMON_HAS_LINKAT
56 #define sys_linkat	linkat
57 #endif
58 #endif	/* __FreeBSD_version */
59 
60 static eventhandler_tag filemon_exec_tag;
61 static eventhandler_tag filemon_exit_tag;
62 static eventhandler_tag filemon_fork_tag;
63 
64 static void
65 filemon_output(struct filemon *filemon, char *msg, size_t len)
66 {
67 	struct uio auio;
68 	struct iovec aiov;
69 
70 	if (filemon->fp == NULL)
71 		return;
72 
73 	aiov.iov_base = msg;
74 	aiov.iov_len = len;
75 	auio.uio_iov = &aiov;
76 	auio.uio_iovcnt = 1;
77 	auio.uio_resid = len;
78 	auio.uio_segflg = UIO_SYSSPACE;
79 	auio.uio_rw = UIO_WRITE;
80 	auio.uio_td = curthread;
81 	auio.uio_offset = (off_t) -1;
82 
83 	bwillwrite();
84 
85 	fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
86 }
87 
88 static struct filemon *
89 filemon_pid_check(struct proc *p)
90 {
91 	struct filemon *filemon;
92 
93 	filemon_lock_read();
94 	if (TAILQ_EMPTY(&filemons_inuse)) {
95 		filemon_unlock_read();
96 		return (NULL);
97 	}
98 	sx_slock(&proctree_lock);
99 	while (p != initproc) {
100 		TAILQ_FOREACH(filemon, &filemons_inuse, link) {
101 			if (p == filemon->p) {
102 				sx_sunlock(&proctree_lock);
103 				filemon_filemon_lock(filemon);
104 				filemon_unlock_read();
105 				return (filemon);
106 			}
107 		}
108 		p = proc_realparent(p);
109 	}
110 	sx_sunlock(&proctree_lock);
111 	filemon_unlock_read();
112 	return (NULL);
113 }
114 
115 static int
116 filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
117 {
118 	int ret;
119 	size_t done;
120 	size_t len;
121 	struct filemon *filemon;
122 
123 	if ((ret = sys_chdir(td, uap)) == 0) {
124 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
125 			copyinstr(uap->path, filemon->fname1,
126 			    sizeof(filemon->fname1), &done);
127 
128 			len = snprintf(filemon->msgbufr,
129 			    sizeof(filemon->msgbufr), "C %d %s\n",
130 			    curproc->p_pid, filemon->fname1);
131 
132 			filemon_output(filemon, filemon->msgbufr, len);
133 
134 			/* Unlock the found filemon structure. */
135 			filemon_filemon_unlock(filemon);
136 		}
137 	}
138 
139 	return (ret);
140 }
141 
142 static void
143 filemon_event_process_exec(void *arg __unused, struct proc *p,
144     struct image_params *imgp)
145 {
146 	struct filemon *filemon;
147 	char *fullpath, *freepath;
148 	size_t len;
149 
150 	if ((filemon = filemon_pid_check(p)) != NULL) {
151 		fullpath = "<unknown>";
152 		freepath = NULL;
153 
154 		vn_fullpath(FIRST_THREAD_IN_PROC(p), imgp->vp, &fullpath,
155 		    &freepath);
156 
157 		len = snprintf(filemon->msgbufr,
158 		    sizeof(filemon->msgbufr), "E %d %s\n",
159 		    p->p_pid, fullpath);
160 
161 		filemon_output(filemon, filemon->msgbufr, len);
162 
163 		/* Unlock the found filemon structure. */
164 		filemon_filemon_unlock(filemon);
165 
166 		free(freepath, M_TEMP);
167 	}
168 }
169 
170 static int
171 filemon_wrapper_open(struct thread *td, struct open_args *uap)
172 {
173 	int ret;
174 	size_t done;
175 	size_t len;
176 	struct filemon *filemon;
177 
178 	if ((ret = sys_open(td, uap)) == 0) {
179 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
180 			copyinstr(uap->path, filemon->fname1,
181 			    sizeof(filemon->fname1), &done);
182 
183 			if (uap->flags & O_RDWR) {
184 				/*
185 				 * We'll get the W record below, but need
186 				 * to also output an R to distingish from
187 				 * O_WRONLY.
188 				 */
189 				len = snprintf(filemon->msgbufr,
190 				    sizeof(filemon->msgbufr), "R %d %s\n",
191 				    curproc->p_pid, filemon->fname1);
192 				filemon_output(filemon, filemon->msgbufr, len);
193 			}
194 
195 
196 			len = snprintf(filemon->msgbufr,
197 			    sizeof(filemon->msgbufr), "%c %d %s\n",
198 			    (uap->flags & O_ACCMODE) ? 'W':'R',
199 			    curproc->p_pid, filemon->fname1);
200 			filemon_output(filemon, filemon->msgbufr, len);
201 
202 			/* Unlock the found filemon structure. */
203 			filemon_filemon_unlock(filemon);
204 		}
205 	}
206 
207 	return (ret);
208 }
209 
210 static int
211 filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
212 {
213 	int ret;
214 	size_t done;
215 	size_t len;
216 	struct filemon *filemon;
217 
218 	if ((ret = sys_openat(td, uap)) == 0) {
219 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
220 			copyinstr(uap->path, filemon->fname1,
221 			    sizeof(filemon->fname1), &done);
222 
223 			filemon->fname2[0] = '\0';
224 			if (filemon->fname1[0] != '/' && uap->fd != AT_FDCWD) {
225 				/*
226 				 * rats - we cannot do too much about this.
227 				 * the trace should show a dir we read
228 				 * recently.. output an A record as a clue
229 				 * until we can do better.
230 				 */
231 				len = snprintf(filemon->msgbufr,
232 				    sizeof(filemon->msgbufr), "A %d %s\n",
233 				    curproc->p_pid, filemon->fname1);
234 				filemon_output(filemon, filemon->msgbufr, len);
235 			}
236 			if (uap->flag & O_RDWR) {
237 				/*
238 				 * We'll get the W record below, but need
239 				 * to also output an R to distingish from
240 				 * O_WRONLY.
241 				 */
242 				len = snprintf(filemon->msgbufr,
243 				    sizeof(filemon->msgbufr), "R %d %s%s\n",
244 				    curproc->p_pid, filemon->fname2, filemon->fname1);
245 				filemon_output(filemon, filemon->msgbufr, len);
246 			}
247 
248 
249 			len = snprintf(filemon->msgbufr,
250 			    sizeof(filemon->msgbufr), "%c %d %s%s\n",
251 			    (uap->flag & O_ACCMODE) ? 'W':'R',
252 			    curproc->p_pid, filemon->fname2, filemon->fname1);
253 			filemon_output(filemon, filemon->msgbufr, len);
254 
255 			/* Unlock the found filemon structure. */
256 			filemon_filemon_unlock(filemon);
257 		}
258 	}
259 
260 	return (ret);
261 }
262 
263 static int
264 filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
265 {
266 	int ret;
267 	size_t done;
268 	size_t len;
269 	struct filemon *filemon;
270 
271 	if ((ret = sys_rename(td, uap)) == 0) {
272 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
273 			copyinstr(uap->from, filemon->fname1,
274 			    sizeof(filemon->fname1), &done);
275 			copyinstr(uap->to, filemon->fname2,
276 			    sizeof(filemon->fname2), &done);
277 
278 			len = snprintf(filemon->msgbufr,
279 			    sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
280 			    curproc->p_pid, filemon->fname1, filemon->fname2);
281 
282 			filemon_output(filemon, filemon->msgbufr, len);
283 
284 			/* Unlock the found filemon structure. */
285 			filemon_filemon_unlock(filemon);
286 		}
287 	}
288 
289 	return (ret);
290 }
291 
292 static int
293 filemon_wrapper_link(struct thread *td, struct link_args *uap)
294 {
295 	int ret;
296 	size_t done;
297 	size_t len;
298 	struct filemon *filemon;
299 
300 	if ((ret = sys_link(td, uap)) == 0) {
301 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
302 			copyinstr(uap->path, filemon->fname1,
303 			    sizeof(filemon->fname1), &done);
304 			copyinstr(uap->link, filemon->fname2,
305 			    sizeof(filemon->fname2), &done);
306 
307 			len = snprintf(filemon->msgbufr,
308 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
309 			    curproc->p_pid, filemon->fname1, filemon->fname2);
310 
311 			filemon_output(filemon, filemon->msgbufr, len);
312 
313 			/* Unlock the found filemon structure. */
314 			filemon_filemon_unlock(filemon);
315 		}
316 	}
317 
318 	return (ret);
319 }
320 
321 static int
322 filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
323 {
324 	int ret;
325 	size_t done;
326 	size_t len;
327 	struct filemon *filemon;
328 
329 	if ((ret = sys_symlink(td, uap)) == 0) {
330 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
331 			copyinstr(uap->path, filemon->fname1,
332 			    sizeof(filemon->fname1), &done);
333 			copyinstr(uap->link, filemon->fname2,
334 			    sizeof(filemon->fname2), &done);
335 
336 			len = snprintf(filemon->msgbufr,
337 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
338 			    curproc->p_pid, filemon->fname1, filemon->fname2);
339 
340 			filemon_output(filemon, filemon->msgbufr, len);
341 
342 			/* Unlock the found filemon structure. */
343 			filemon_filemon_unlock(filemon);
344 		}
345 	}
346 
347 	return (ret);
348 }
349 
350 #ifdef FILEMON_HAS_LINKAT
351 static int
352 filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
353 {
354 	int ret;
355 	size_t done;
356 	size_t len;
357 	struct filemon *filemon;
358 
359 	if ((ret = sys_linkat(td, uap)) == 0) {
360 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
361 			copyinstr(uap->path1, filemon->fname1,
362 			    sizeof(filemon->fname1), &done);
363 			copyinstr(uap->path2, filemon->fname2,
364 			    sizeof(filemon->fname2), &done);
365 
366 			len = snprintf(filemon->msgbufr,
367 			    sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
368 			    curproc->p_pid, filemon->fname1, filemon->fname2);
369 
370 			filemon_output(filemon, filemon->msgbufr, len);
371 
372 			/* Unlock the found filemon structure. */
373 			filemon_filemon_unlock(filemon);
374 		}
375 	}
376 
377 	return (ret);
378 }
379 #endif
380 
381 static int
382 filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
383 {
384 	int ret;
385 	size_t done;
386 	size_t len;
387 	struct filemon *filemon;
388 
389 	if ((ret = sys_stat(td, uap)) == 0) {
390 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
391 			copyinstr(uap->path, filemon->fname1,
392 			    sizeof(filemon->fname1), &done);
393 
394 			len = snprintf(filemon->msgbufr,
395 			    sizeof(filemon->msgbufr), "S %d %s\n",
396 			    curproc->p_pid, filemon->fname1);
397 
398 			filemon_output(filemon, filemon->msgbufr, len);
399 
400 			/* Unlock the found filemon structure. */
401 			filemon_filemon_unlock(filemon);
402 		}
403 	}
404 
405 	return (ret);
406 }
407 
408 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
409 static int
410 filemon_wrapper_freebsd32_stat(struct thread *td,
411     struct freebsd32_stat_args *uap)
412 {
413 	int ret;
414 	size_t done;
415 	size_t len;
416 	struct filemon *filemon;
417 
418 	if ((ret = freebsd32_stat(td, uap)) == 0) {
419 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
420 			copyinstr(uap->path, filemon->fname1,
421 			    sizeof(filemon->fname1), &done);
422 
423 			len = snprintf(filemon->msgbufr,
424 			    sizeof(filemon->msgbufr), "S %d %s\n",
425 			    curproc->p_pid, filemon->fname1);
426 
427 			filemon_output(filemon, filemon->msgbufr, len);
428 
429 			/* Unlock the found filemon structure. */
430 			filemon_filemon_unlock(filemon);
431 		}
432 	}
433 
434 	return (ret);
435 }
436 #endif
437 
438 static void
439 filemon_event_process_exit(void *arg __unused, struct proc *p)
440 {
441 	size_t len;
442 	struct filemon *filemon;
443 	struct timeval now;
444 
445 	/* Get timestamp before locking. */
446 	getmicrotime(&now);
447 
448 	if ((filemon = filemon_pid_check(p)) != NULL) {
449 		len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
450 		    "X %d %d %d\n", p->p_pid, p->p_xexit, p->p_xsig);
451 
452 		filemon_output(filemon, filemon->msgbufr, len);
453 
454 		/* Check if the monitored process is about to exit. */
455 		if (filemon->p == p) {
456 			len = snprintf(filemon->msgbufr,
457 			    sizeof(filemon->msgbufr),
458 			    "# Stop %ju.%06ju\n# Bye bye\n",
459 			    (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
460 
461 			filemon_output(filemon, filemon->msgbufr, len);
462 			filemon->p = NULL;
463 		}
464 
465 		/* Unlock the found filemon structure. */
466 		filemon_filemon_unlock(filemon);
467 	}
468 }
469 
470 static int
471 filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
472 {
473 	int ret;
474 	size_t done;
475 	size_t len;
476 	struct filemon *filemon;
477 
478 	if ((ret = sys_unlink(td, uap)) == 0) {
479 		if ((filemon = filemon_pid_check(curproc)) != NULL) {
480 			copyinstr(uap->path, filemon->fname1,
481 			    sizeof(filemon->fname1), &done);
482 
483 			len = snprintf(filemon->msgbufr,
484 			    sizeof(filemon->msgbufr), "D %d %s\n",
485 			    curproc->p_pid, filemon->fname1);
486 
487 			filemon_output(filemon, filemon->msgbufr, len);
488 
489 			/* Unlock the found filemon structure. */
490 			filemon_filemon_unlock(filemon);
491 		}
492 	}
493 
494 	return (ret);
495 }
496 
497 static void
498 filemon_event_process_fork(void *arg __unused, struct proc *p1,
499     struct proc *p2, int flags __unused)
500 {
501 	size_t len;
502 	struct filemon *filemon;
503 
504 	if ((filemon = filemon_pid_check(p1)) != NULL) {
505 		len = snprintf(filemon->msgbufr,
506 		    sizeof(filemon->msgbufr), "F %d %d\n",
507 		    p1->p_pid, p2->p_pid);
508 
509 		filemon_output(filemon, filemon->msgbufr, len);
510 
511 		/* Unlock the found filemon structure. */
512 		filemon_filemon_unlock(filemon);
513 	}
514 }
515 
516 static void
517 filemon_wrapper_install(void)
518 {
519 #if defined(__LP64__)
520 	struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
521 #else
522 	struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
523 #endif
524 
525 	sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
526 	sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
527 	sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
528 	sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
529 	sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat;
530 	sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
531 	sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
532 	sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
533 #ifdef FILEMON_HAS_LINKAT
534 	sv_table[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
535 #endif
536 
537 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
538 	sv_table = ia32_freebsd_sysvec.sv_table;
539 
540 	sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
541 	sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
542 	sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
543 	sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
544 	sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat;
545 	sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
546 	sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
547 	sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
548 #ifdef FILEMON_HAS_LINKAT
549 	sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
550 #endif
551 #endif	/* COMPAT_ARCH32 */
552 
553 	filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec,
554 	    filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST);
555 	filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit,
556 	    filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST);
557 	filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork,
558 	    filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST);
559 }
560 
561 static void
562 filemon_wrapper_deinstall(void)
563 {
564 #if defined(__LP64__)
565 	struct sysent *sv_table = elf64_freebsd_sysvec.sv_table;
566 #else
567 	struct sysent *sv_table = elf32_freebsd_sysvec.sv_table;
568 #endif
569 
570 	sv_table[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
571 	sv_table[SYS_open].sy_call = (sy_call_t *)sys_open;
572 	sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat;
573 	sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename;
574 	sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat;
575 	sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
576 	sv_table[SYS_link].sy_call = (sy_call_t *)sys_link;
577 	sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
578 #ifdef FILEMON_HAS_LINKAT
579 	sv_table[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
580 #endif
581 
582 #if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
583 	sv_table = ia32_freebsd_sysvec.sv_table;
584 
585 	sv_table[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
586 	sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
587 	sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
588 	sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
589 	sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat;
590 	sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
591 	sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
592 	sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
593 #ifdef FILEMON_HAS_LINKAT
594 	sv_table[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
595 #endif
596 #endif	/* COMPAT_ARCH32 */
597 
598 	EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag);
599 	EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag);
600 	EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag);
601 }
602