Module Name:    src
Committed By:   maxv
Date:           Mon Dec 23 06:45:38 UTC 2019

Modified Files:
        src/distrib/sets/lists/base: mi
        src/distrib/sets/lists/comp: mi
        src/distrib/sets/lists/man: mi
        src/etc: MAKEDEV.tmpl
        src/etc/mtree: NetBSD.dist.base
        src/share/man/man4: Makefile
        src/sys/arch/amd64/conf: ALL
        src/sys/arch/i386/conf: ALL
        src/sys/conf: files majors
        src/sys/dev: Makefile
        src/sys/modules: Makefile
        src/usr.sbin/makemandb: nostem.txt
Added Files:
        src/share/man/man4: filemon.4
        src/sys/dev/filemon: Makefile filemon.c filemon.h filemon_wrapper.c
            mknod-sh
        src/sys/modules/filemon: Makefile filemon.ioconf

Log Message:
Revert the removal of filemon.


To generate a diff of this commit:
cvs rdiff -u -r1.1223 -r1.1224 src/distrib/sets/lists/base/mi
cvs rdiff -u -r1.2298 -r1.2299 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.1666 -r1.1667 src/distrib/sets/lists/man/mi
cvs rdiff -u -r1.211 -r1.212 src/etc/MAKEDEV.tmpl
cvs rdiff -u -r1.207 -r1.208 src/etc/mtree/NetBSD.dist.base
cvs rdiff -u -r1.691 -r1.692 src/share/man/man4/Makefile
cvs rdiff -u -r0 -r1.21 src/share/man/man4/filemon.4
cvs rdiff -u -r1.133 -r1.134 src/sys/arch/amd64/conf/ALL
cvs rdiff -u -r1.477 -r1.478 src/sys/arch/i386/conf/ALL
cvs rdiff -u -r1.1247 -r1.1248 src/sys/conf/files
cvs rdiff -u -r1.91 -r1.92 src/sys/conf/majors
cvs rdiff -u -r1.42 -r1.43 src/sys/dev/Makefile
cvs rdiff -u -r0 -r1.3 src/sys/dev/filemon/Makefile \
    src/sys/dev/filemon/mknod-sh
cvs rdiff -u -r0 -r1.33 src/sys/dev/filemon/filemon.c
cvs rdiff -u -r0 -r1.11 src/sys/dev/filemon/filemon.h
cvs rdiff -u -r0 -r1.14 src/sys/dev/filemon/filemon_wrapper.c
cvs rdiff -u -r1.232 -r1.233 src/sys/modules/Makefile
cvs rdiff -u -r0 -r1.6 src/sys/modules/filemon/Makefile
cvs rdiff -u -r0 -r1.3 src/sys/modules/filemon/filemon.ioconf
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/makemandb/nostem.txt

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/mi
diff -u src/distrib/sets/lists/base/mi:1.1223 src/distrib/sets/lists/base/mi:1.1224
--- src/distrib/sets/lists/base/mi:1.1223	Wed Dec 18 07:37:17 2019
+++ src/distrib/sets/lists/base/mi	Mon Dec 23 06:45:36 2019
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1223 2019/12/18 07:37:17 maxv Exp $
+# $NetBSD: mi,v 1.1224 2019/12/23 06:45:36 maxv Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -1114,7 +1114,7 @@
 ./usr/include/dev/dmover			base-c-usr
 ./usr/include/dev/dtv				base-c-usr
 ./usr/include/dev/eisa				base-obsolete		obsolete
-./usr/include/dev/filemon			base-obsolete		obsolete
+./usr/include/dev/filemon			base-c-usr
 ./usr/include/dev/hdaudio			base-c-usr
 ./usr/include/dev/hdmicec			base-c-usr
 ./usr/include/dev/hid				base-c-usr

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2298 src/distrib/sets/lists/comp/mi:1.2299
--- src/distrib/sets/lists/comp/mi:1.2298	Wed Dec 18 07:37:17 2019
+++ src/distrib/sets/lists/comp/mi	Mon Dec 23 06:45:36 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2298 2019/12/18 07:37:17 maxv Exp $
+#	$NetBSD: mi,v 1.2299 2019/12/23 06:45:36 maxv Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -411,7 +411,7 @@
 ./usr/include/dev/eisa/eisadevs_data.h		comp-obsolete		obsolete
 ./usr/include/dev/eisa/eisareg.h		comp-obsolete		obsolete
 ./usr/include/dev/eisa/eisavar.h		comp-obsolete		obsolete
-./usr/include/dev/filemon/filemon.h		comp-obsolete		obsolete
+./usr/include/dev/filemon/filemon.h		comp-c-include
 ./usr/include/dev/fssvar.h			comp-c-include
 ./usr/include/dev/hdaudio/hdaudioio.h		comp-c-include
 ./usr/include/dev/hdaudio/hdaudioreg.h		comp-c-include

Index: src/distrib/sets/lists/man/mi
diff -u src/distrib/sets/lists/man/mi:1.1666 src/distrib/sets/lists/man/mi:1.1667
--- src/distrib/sets/lists/man/mi:1.1666	Wed Dec 18 07:37:17 2019
+++ src/distrib/sets/lists/man/mi	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1666 2019/12/18 07:37:17 maxv Exp $
+# $NetBSD: mi,v 1.1667 2019/12/23 06:45:37 maxv Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -1104,7 +1104,7 @@
 ./usr/share/man/cat4/fast_ipsec.0		man-obsolete		obsolete
 ./usr/share/man/cat4/fd.0			man-sys-catman		.cat
 ./usr/share/man/cat4/fea.0			man-sys-catman		.cat
-./usr/share/man/cat4/filemon.0			man-obsolete		obsolete
+./usr/share/man/cat4/filemon.0			man-sys-catman		.cat
 ./usr/share/man/cat4/finsio.0			man-sys-catman		.cat
 ./usr/share/man/cat4/flash.0			man-sys-catman		.cat
 ./usr/share/man/cat4/fms.0			man-sys-catman		.cat
@@ -4288,7 +4288,7 @@
 ./usr/share/man/html4/fast_ipsec.html		man-obsolete		obsolete
 ./usr/share/man/html4/fd.html			man-sys-htmlman		html
 ./usr/share/man/html4/fea.html			man-sys-htmlman		html
-./usr/share/man/html4/filemon.html		man-obsolete		obsolete
+./usr/share/man/html4/filemon.html		man-sys-htmlman		html
 ./usr/share/man/html4/finsio.html		man-sys-htmlman		html
 ./usr/share/man/html4/flash.html		man-sys-htmlman		html
 ./usr/share/man/html4/fms.html			man-sys-htmlman		html
@@ -7244,7 +7244,7 @@
 ./usr/share/man/man4/fast_ipsec.4		man-obsolete		obsolete
 ./usr/share/man/man4/fd.4			man-sys-man		.man
 ./usr/share/man/man4/fea.4			man-sys-man		.man
-./usr/share/man/man4/filemon.4			man-obsolete		obsolete
+./usr/share/man/man4/filemon.4			man-sys-man		.man
 ./usr/share/man/man4/finsio.4			man-sys-man		.man
 ./usr/share/man/man4/flash.4			man-sys-man		.man
 ./usr/share/man/man4/fms.4			man-sys-man		.man

Index: src/etc/MAKEDEV.tmpl
diff -u src/etc/MAKEDEV.tmpl:1.211 src/etc/MAKEDEV.tmpl:1.212
--- src/etc/MAKEDEV.tmpl:1.211	Wed Dec 18 07:37:17 2019
+++ src/etc/MAKEDEV.tmpl	Mon Dec 23 06:45:37 2019
@@ -1,5 +1,5 @@
 #!/bin/sh -
-#	$NetBSD: MAKEDEV.tmpl,v 1.211 2019/12/18 07:37:17 maxv Exp $
+#	$NetBSD: MAKEDEV.tmpl,v 1.212 2019/12/23 06:45:37 maxv Exp $
 #
 # Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -816,6 +816,7 @@ all)
 	makedev dk24 dk25 dk26 dk27 dk28 dk29 dk30 dk31
 	makedev ccd0 ccd1 ccd2 ccd3
 	makedev cgd0 cgd1 cgd2 cgd3
+	makedev filemon
 	makedev fss0 fss1 fss2 fss3
 	makedev md0 md1
 	makedev raid0 raid1 raid2 raid3 raid4 raid5 raid6 raid7
@@ -2181,6 +2182,10 @@ dtrace)
 	mkdev dtrace/dtrace c %dtrace_chr% 0 600
 	;;
 
+filemon)
+	mkdev filemon c %filemon_chr% 0 666
+	;;
+
 fw[0-9]*)
 	unit=${i#fw}
 	for j in 0 1 2 3

Index: src/etc/mtree/NetBSD.dist.base
diff -u src/etc/mtree/NetBSD.dist.base:1.207 src/etc/mtree/NetBSD.dist.base:1.208
--- src/etc/mtree/NetBSD.dist.base:1.207	Wed Dec 18 14:44:16 2019
+++ src/etc/mtree/NetBSD.dist.base	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: NetBSD.dist.base,v 1.207 2019/12/18 14:44:16 kamil Exp $
+#	$NetBSD: NetBSD.dist.base,v 1.208 2019/12/23 06:45:37 maxv Exp $
 #	@(#)4.4BSD.dist	8.1 (Berkeley) 6/13/93
 
 # Do not customize this file as it may be overwritten on upgrades.
@@ -121,6 +121,7 @@
 ./usr/include/dev/dm
 ./usr/include/dev/dmover
 ./usr/include/dev/dtv
+./usr/include/dev/filemon
 ./usr/include/dev/hdaudio
 ./usr/include/dev/hdmicec
 ./usr/include/dev/hid

Index: src/share/man/man4/Makefile
diff -u src/share/man/man4/Makefile:1.691 src/share/man/man4/Makefile:1.692
--- src/share/man/man4/Makefile:1.691	Wed Dec 18 07:37:18 2019
+++ src/share/man/man4/Makefile	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.691 2019/12/18 07:37:18 maxv Exp $
+#	$NetBSD: Makefile,v 1.692 2019/12/23 06:45:37 maxv Exp $
 #	@(#)Makefile	8.1 (Berkeley) 6/18/93
 
 MAN=	aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@@ -23,7 +23,7 @@ MAN=	aac.4 ac97.4 acardide.4 aceride.4 a
 	dmphy.4 dpt.4 dpti.4 drm.4 drum.4 drvctl.4 dtv.4 dtviic.4 dwctwo.4 \
 	eap.4 ebus.4 edc.4 elmc.4 emuxki.4 ena.4 envsys.4 ep.4 esh.4 \
 	esa.4 esiop.4 esm.4 eso.4 et.4 etphy.4 exphy.4 \
-	fd.4 finsio.4 flash.4 fpa.4 fms.4 fss.4 \
+	fd.4 filemon.4 finsio.4 flash.4 fpa.4 fms.4 fss.4 \
 	fujbp.4 full.4 fxp.4 \
 	gcscaudio.4 gem.4 genfb.4 gentbi.4 geodeide.4 \
 	glxtphy.4 gpib.4 gpio.4 gpioirq.4 gpiolock.4 gpiopps.4 gpiopwm.4 \

Index: src/sys/arch/amd64/conf/ALL
diff -u src/sys/arch/amd64/conf/ALL:1.133 src/sys/arch/amd64/conf/ALL:1.134
--- src/sys/arch/amd64/conf/ALL:1.133	Wed Dec 18 07:37:18 2019
+++ src/sys/arch/amd64/conf/ALL	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.133 2019/12/18 07:37:18 maxv Exp $
+# $NetBSD: ALL,v 1.134 2019/12/23 06:45:37 maxv Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.133 $"
+#ident		"ALL-$Revision: 1.134 $"
 
 maxusers	64		# estimated number of users
 
@@ -1675,6 +1675,8 @@ pseudo-device	bcsp			# BlueCore Serial P
 pseudo-device	btuart			# Bluetooth HCI UART (H4)
 pseudo-device	gpiosim		1	# GPIO simulator
 
+pseudo-device	filemon			# process monitor for make(1)
+
 # a pseudo device needed for Coda	# also needs CODA (above)
 pseudo-device	vcoda			# coda minicache <-> venus comm.
 

Index: src/sys/arch/i386/conf/ALL
diff -u src/sys/arch/i386/conf/ALL:1.477 src/sys/arch/i386/conf/ALL:1.478
--- src/sys/arch/i386/conf/ALL:1.477	Wed Dec 18 07:37:18 2019
+++ src/sys/arch/i386/conf/ALL	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.477 2019/12/18 07:37:18 maxv Exp $
+# $NetBSD: ALL,v 1.478 2019/12/23 06:45:37 maxv Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/i386/conf/std.i386"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.477 $"
+#ident		"ALL-$Revision: 1.478 $"
 
 maxusers	64		# estimated number of users
 
@@ -1799,6 +1799,8 @@ pseudo-device	bcsp			# BlueCore Serial P
 pseudo-device	btuart			# Bluetooth HCI UART (H4)
 pseudo-device	gpiosim		1	# GPIO simulator
 
+pseudo-device	filemon			# process monitor for make(1)
+
 # a pseudo device needed for Coda	# also needs CODA (above)
 pseudo-device	vcoda			# coda minicache <-> venus comm.
 

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1247 src/sys/conf/files:1.1248
--- src/sys/conf/files:1.1247	Thu Dec 19 00:23:57 2019
+++ src/sys/conf/files	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1247 2019/12/19 00:23:57 jakllsch Exp $
+#	$NetBSD: files,v 1.1248 2019/12/23 06:45:37 maxv Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20171118
@@ -1544,6 +1544,12 @@ include "net/files.net"
 device	joy
 file	dev/ic/joy.c			joy needs-flag
 
+# process monitor for make(1)
+# normally built as module
+defpseudo filemon
+file	dev/filemon/filemon.c		filemon
+file	dev/filemon/filemon_wrapper.c	filemon
+
 #
 # General Purpose Input/Output framework
 #

Index: src/sys/conf/majors
diff -u src/sys/conf/majors:1.91 src/sys/conf/majors:1.92
--- src/sys/conf/majors:1.91	Wed Dec 18 07:37:18 2019
+++ src/sys/conf/majors	Mon Dec 23 06:45:37 2019
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.91 2019/12/18 07:37:18 maxv Exp $
+# $NetBSD: majors,v 1.92 2019/12/23 06:45:37 maxv Exp $
 #
 # Device majors for Machine-Independent drivers.
 #
@@ -47,7 +47,7 @@ device-major npf       char 198		   npf
 device-major flash     char 199 block 199  flash
 device-major dtv       char 200		   dtv
 device-major iic       char 201		   iic
-#obsolete    filemon   char 202		   filemon
+device-major filemon   char 202		   filemon
 device-major iscsi     char 203		   iscsi
 device-major tpm       char 204		   tpm
 device-major mfi       char 205		   mfi

Index: src/sys/dev/Makefile
diff -u src/sys/dev/Makefile:1.42 src/sys/dev/Makefile:1.43
--- src/sys/dev/Makefile:1.42	Wed Dec 18 07:37:18 2019
+++ src/sys/dev/Makefile	Mon Dec 23 06:45:37 2019
@@ -1,6 +1,6 @@
-#	$NetBSD: Makefile,v 1.42 2019/12/18 07:37:18 maxv Exp $
+#	$NetBSD: Makefile,v 1.43 2019/12/23 06:45:37 maxv Exp $
 
-SUBDIR=	apm ata bluetooth dec dm dmover dtv hdaudio hdmicec hid hpc \
+SUBDIR=	apm ata bluetooth dec dm dmover dtv filemon hdaudio hdmicec hid hpc \
 	i2c i2o ic ieee1394 ir isa \
 	microcode ofw pci pckbport pcmcia pud putter raidframe sbus scsipi \
 	spi sun tc usb vme wscons

Index: src/sys/modules/Makefile
diff -u src/sys/modules/Makefile:1.232 src/sys/modules/Makefile:1.233
--- src/sys/modules/Makefile:1.232	Wed Dec 18 07:37:18 2019
+++ src/sys/modules/Makefile	Mon Dec 23 06:45:38 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.232 2019/12/18 07:37:18 maxv Exp $
+#	$NetBSD: Makefile,v 1.233 2019/12/23 06:45:38 maxv Exp $
 
 .include <bsd.own.mk>
 
@@ -54,6 +54,7 @@ SUBDIR+=	exec_script
 SUBDIR+=	fdesc
 SUBDIR+=	ffs
 SUBDIR+=	filecore
+SUBDIR+=	filemon
 SUBDIR+=	flash
 SUBDIR+=	fss
 SUBDIR+=	gpio

Index: src/usr.sbin/makemandb/nostem.txt
diff -u src/usr.sbin/makemandb/nostem.txt:1.3 src/usr.sbin/makemandb/nostem.txt:1.4
--- src/usr.sbin/makemandb/nostem.txt:1.3	Wed Dec 18 07:37:19 2019
+++ src/usr.sbin/makemandb/nostem.txt	Mon Dec 23 06:45:38 2019
@@ -1140,6 +1140,7 @@ fhstatvfs
 fhtovp
 fileassoc
 fileio
+filemon
 filt
 fincore
 fingerd

Added files:

Index: src/share/man/man4/filemon.4
diff -u /dev/null src/share/man/man4/filemon.4:1.21
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/share/man/man4/filemon.4	Mon Dec 23 06:45:37 2019
@@ -0,0 +1,248 @@
+.\"	$NetBSD: filemon.4,v 1.21 2019/12/23 06:45:37 maxv Exp $
+.\"
+.\" Copyright (c) 2011, Juniper Networks, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd January 6, 2016
+.Dt FILEMON 4
+.Os
+.Sh NAME
+.Nm filemon
+.Nd track interesting system calls
+.Sh SYNOPSIS
+.Cd "pseudo-device filemon"
+.Sh DESCRIPTION
+In normal situations,
+.Nm
+is not built-in to the kernel, and a call to open
+.Pa /dev/filemon
+will auto-load the
+.Nm
+module (see
+.Xr module 7
+for more details).
+.Pp
+(Although not recommended, the
+.Nm
+facility can be included in a kernel build by adding
+.Bd -literal -offset indent
+pseudo-device filemon
+.Ed
+.Pp
+to the kernel configuration file.)
+.Pp
+.Nm
+provides a means for tracking the successful system calls performed by
+a process and its descendants.
+It is used by
+.Xr make 1
+to track the activities of build scripts, for the purpose of automatically
+learning dependencies.
+.Pp
+The data captured by
+.Nm
+for the script
+.Bd -literal -offset indent
+n=`wc -l /etc/motd`; echo "int motd_lines = $n;" > foo.h.new
+cmp -s foo.h foo.h.new 2> /dev/null || mv foo.h.new foo.h
+.Ed
+.Pp
+looks like:
+.Bd -literal -offset indent
+# filemon version 4
+# Target pid 24291
+V 4
+E 29676 /bin/sh
+R 29676 /etc/ld.so.conf
+R 29676 /lib/libedit.so.2
+R 29676 /lib/libterminfo.so.1
+R 29676 /lib/libc.so.12
+F 29676 4899
+E 4899 /usr/bin/wc
+R 4899 /etc/ld.so.conf
+R 4899 /usr/lib/libc.so.12
+R 4899 /etc/motd
+X 4899 0
+W 29676 foo.h.new
+X 29676 0
+# Bye bye
+E 3250 /bin/sh
+R 3250 /etc/ld.so.conf
+R 3250 /lib/libedit.so.2
+R 3250 /lib/libterminfo.so.1
+R 3250 /lib/libc.so.12
+W 26673 /dev/null
+E 26673 /usr/bin/cmp
+R 26673 /etc/ld.so.conf
+R 26673 /usr/lib/libc.so.12
+X 26673 2
+E 576 /bin/mv
+R 576 /etc/ld.so.conf
+R 576 /lib/libc.so.12
+M 576 'foo.h.new' 'foo.h'
+X 576 0
+X 3250 0
+# Bye bye
+.Ed
+.Pp
+Most records follow the format:
+.Bd -literal -offset indent
+type pid data
+.Ed
+.Pp
+where
+.Ar type
+is one of the list below, and unless otherwise specified,
+.Ar data
+is a pathname.
+.Bl -tag -width Ds -offset indent
+.It Dv C
+.Xr chdir 2 .
+.It Dv D
+.Xr unlink 2 .
+.It Dv E
+.Xr exec 3 .
+.It Dv F
+.Xr fork 2 ,
+.Xr vfork 2 ;
+.Ar data
+is the process id of the child.
+.It Dv L
+.Xr link 2 ,
+.Xr symlink 2 ;
+.Ar data
+is two pathnames.
+.It Dv M
+.Xr rename 2 ;
+.Ar data
+is two pathnames.
+.It Dv R
+.Xr open 2
+for read or read-write.
+.It Dv W
+.Xr open 2
+for writing or read-write.
+.It Dv X
+.Xr exit 3 ;
+.Ar data
+is the exit status.
+.It Dv V
+indicates the version of
+.Nm .
+.El
+.Pp
+A
+.Nm
+instance is created by opening
+.Pa /dev/filemon .
+Then use
+.Fn ioctl filemon_fd FILEMON_SET_PID &pid
+to identify the target process to monitor, and
+.Fn ioctl filemon_fd FILEMON_SET_FD &output_fd
+to direct the event log to an already-opened output file.
+.Sh FILES
+.Bd -literal
+/dev/filemon
+.Ed
+.Sh EXAMPLES
+The following example demonstrates the basic usage of
+.Nm :
+.Pp
+.Bd -literal -offset indent
+#include <filemon.h>
+
+pid_t pid;
+int filemon_fd, temp_fd;
+int status;
+
+filemon_fd = open("/dev/filemon", O_RDWR);
+temp_fd = mkstemp("/tmp/filemon.XXXXXXX");
+/* give filemon the temp file to use */
+ioctl(filemon_fd, FILEMON_SET_FD, &temp_fd);
+/* children do not need these once they exec */
+fcntl(filemon_fd, F_SETFD, FD_CLOEXEC);
+fcntl(temp_fd, F_SETFD, FD_CLOEXEC);
+
+pid = fork();
+switch(pid) {
+ case -1:
+     err(1, "cannot fork");
+     break;
+ case 0:
+     pid = getpid();
+     /* tell filemon to monitor this process */
+     ioctl(filemon_fd, FILEMON_SET_PID, &pid);
+     execvp(...);
+     _exit(1);
+     break;
+ default:
+     status = wait();
+     close(filemon_fd);
+     lseek(temp_fd, SEEK_SET, 0);
+     /* read the captured syscalls from temp_fd */
+     close(temp_fd);
+     break;
+}
+.Ed
+.Pp
+The output of
+.Nm
+is intended to be simple to parse.
+It is possible to achieve almost equivalent results with
+.Xr dtrace 1
+though on many systems this requires elevated privileges.
+Also,
+.Xr ktrace 1
+can capture similar data, but records failed system calls as well as
+successful, and is thus more complex to post-process.
+.Sh HISTORY
+.Nm
+was contributed by Juniper Networks.
+.Sh SECURITY CONSIDERATIONS
+If the monitored process exits, and its pid gets reused,
+.Nm
+will continue to report events for the new process (and its
+descendants) without any authorization checks.
+.Pp
+Monitoring of a process enables the target process to write to the
+tracking process's file descriptor.
+.Sh RESTRICTIONS
+The
+.Nm
+facility can only be used to track processes running in the system's
+native emulation.
+Neither processes using any of the
+.Dv COMPAT_xxx
+compatibility layers nor
+any descendants of such processes can be tracked.
+.Pp
+If two processes are monitored, and one is a descendant of the other, events
+related to the descendant process and its further descendants are delivered
+only to the descendant process's monitor.
+If a process is being monitored by two instances of
+.Nm ,
+events will be delivered only to the first instance created (when
+.Pa /dev/filemon
+was opened), regardless of the order in which the monitoring processes
+called
+.Fn ioctl fd FILEMON_SET_PID pid .

Index: src/sys/dev/filemon/Makefile
diff -u /dev/null src/sys/dev/filemon/Makefile:1.3
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/dev/filemon/Makefile	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,8 @@
+#	$NetBSD: Makefile,v 1.3 2019/12/23 06:45:38 maxv Exp $
+
+INCSDIR= /usr/include/dev/filemon
+
+# Only install includes which are used by userland
+INCS=	filemon.h
+
+.include <bsd.kinc.mk>
Index: src/sys/dev/filemon/mknod-sh
diff -u /dev/null src/sys/dev/filemon/mknod-sh:1.3
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/dev/filemon/mknod-sh	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Note that filemon.kmod needs the 6.x version of modload.
+
+Error() {
+	echo "ERROR: $@" >&2; exit 1
+}
+
+major=`sysctl kern.drivers | tr ',' '\012' | sed -n '/filemon/s,.*\[\([0-9][0-9]*\).*,\1,p'`
+
+[ ${major:-0} -gt 0 ] || Error filemon not loaded
+dev=/dev/filemon
+
+if [ -c $dev ]; then
+   x=`'ls' -l $dev`
+   case "$x" in
+   *" $major,"*) exit 0;;
+   esac
+   rm -f $dev
+fi
+mknod -m 666 $dev c $major 0
+

Index: src/sys/dev/filemon/filemon.c
diff -u /dev/null src/sys/dev/filemon/filemon.c:1.33
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/dev/filemon/filemon.c	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,445 @@
+/*      $NetBSD: filemon.c,v 1.33 2019/12/23 06:45:38 maxv Exp $ */
+/*
+ * Copyright (c) 2010, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.33 2019/12/23 06:45:38 maxv Exp $");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/fcntl.h>
+#include <sys/rwlock.h>
+#include <sys/condvar.h>
+#include <sys/lwp.h>
+#include <sys/proc.h>
+#include <sys/kmem.h>
+#include <sys/syslog.h>
+#include <sys/kauth.h>
+
+#include "filemon.h"
+#include "ioconf.h"
+
+MODULE(MODULE_CLASS_DRIVER, filemon, NULL);
+
+static dev_type_open(filemon_open);
+
+struct cdevsw filemon_cdevsw = {
+	.d_open = filemon_open,
+	.d_close = noclose,
+	.d_read = noread,
+	.d_write = nowrite,
+	.d_ioctl = noioctl,
+	.d_stop = nostop,
+	.d_tty = notty,
+	.d_poll = nopoll,
+	.d_mmap = nommap,
+	.d_kqfilter = nokqfilter,
+	.d_discard = nodiscard,
+	.d_flag = D_MPSAFE
+};
+
+static int filemon_ioctl(struct file *, u_long, void *);
+static int filemon_close(struct file *);
+
+static const struct fileops filemon_fileops = {
+	.fo_name = "filemon",
+	.fo_ioctl = filemon_ioctl,
+	.fo_close = filemon_close,
+	.fo_read = fbadop_read,
+	.fo_write = fbadop_write,
+	.fo_fcntl = fnullop_fcntl,
+	.fo_poll = fnullop_poll,
+	.fo_stat = fbadop_stat,
+	.fo_kqfilter = fnullop_kqfilter,
+};
+
+static krwlock_t filemon_mtx;
+
+static TAILQ_HEAD(, filemon) filemons_inuse =
+	TAILQ_HEAD_INITIALIZER(filemons_inuse);
+
+#ifdef DEBUG
+static int logLevel = LOG_DEBUG;
+#endif
+
+void
+filemon_output(struct filemon * filemon, char *msg, size_t len)
+{
+	struct uio auio;
+	struct iovec aiov;
+
+	if (filemon->fm_fp == NULL)
+		return;
+
+	aiov.iov_base = msg;
+	aiov.iov_len = len;
+	auio.uio_iov = &aiov;
+	auio.uio_iovcnt = 1;
+	auio.uio_resid = len;
+	auio.uio_rw = UIO_WRITE;
+	auio.uio_offset = (off_t) - 1;
+	uio_setup_sysspace(&auio);
+
+#ifdef DEBUG
+	{
+		char *cp;
+		int x = 16;
+
+		cp = strchr(msg, '\n');
+		if (cp && cp - msg <= 16)
+			x = (cp - msg) - 2;
+		log(logLevel, "filemon_output:('%.*s%s'", x,
+		    (x < 16) ? "..." : "", msg);
+	}
+#endif
+	(*filemon->fm_fp->f_ops->fo_write) (filemon->fm_fp,
+	    &(filemon->fm_fp->f_offset),
+	    &auio, curlwp->l_cred, FOF_UPDATE_OFFSET);
+}
+
+void
+filemon_printf(struct filemon *filemon, const char *fmt, ...)
+{
+	size_t len;
+	va_list ap;
+
+	va_start(ap, fmt);
+	len = vsnprintf(filemon->fm_msgbufr, sizeof(filemon->fm_msgbufr),
+	    fmt, ap);
+	va_end(ap);
+	if (len > sizeof(filemon->fm_msgbufr))
+		len = sizeof(filemon->fm_msgbufr);
+	filemon_output(filemon, filemon->fm_msgbufr, len);
+}
+
+static void
+filemon_comment(struct filemon * filemon)
+{
+
+	filemon_printf(filemon, "# filemon version %d\n# Target pid %d\nV %d\n",
+	   FILEMON_VERSION, curproc->p_pid, FILEMON_VERSION);
+}
+
+
+static struct filemon *
+filemon_pid_check(struct proc * p)
+{
+	struct filemon *filemon;
+	struct proc * lp;
+
+	KASSERT(p != NULL);
+	if (!TAILQ_EMPTY(&filemons_inuse)) {
+		/*
+		 * make sure p cannot exit
+		 * until we have moved on to p_pptr
+		 */
+		rw_enter(&p->p_reflock, RW_READER);
+		while (p) {
+			TAILQ_FOREACH(filemon, &filemons_inuse, fm_link) {
+				if (p->p_pid == filemon->fm_pid) {
+					rw_exit(&p->p_reflock);
+					return (filemon);
+				}
+			}
+			lp = p;
+			p = p->p_pptr;
+
+			/* lock parent before releasing child */
+			if (p != NULL)
+				rw_enter(&p->p_reflock, RW_READER);
+			rw_exit(&lp->p_reflock);
+		}
+	}
+	return (NULL);
+}
+
+/*
+ * return exclusive access to a filemon struct
+ */
+struct filemon *
+filemon_lookup(struct proc * p)
+{
+	struct filemon *filemon;
+
+	rw_enter(&filemon_mtx, RW_READER);
+	filemon = filemon_pid_check(p);
+	if (filemon) {
+		rw_enter(&filemon->fm_mtx, RW_WRITER);
+	}
+	rw_exit(&filemon_mtx);
+	return filemon;
+}
+
+static struct filemon *
+filemon_fp_data(struct file * fp, int lck)
+{
+	struct filemon *filemon;
+	
+	rw_enter(&filemon_mtx, RW_READER);
+	filemon = fp->f_data;
+	if (filemon && lck) {
+		rw_enter(&filemon->fm_mtx, lck);
+	}
+	rw_exit(&filemon_mtx);
+	return filemon;
+}
+
+static int n_open = 0;
+
+static int
+filemon_open(dev_t dev, int oflags __unused, int mode __unused,
+    struct lwp * l __unused)
+{
+	struct filemon *filemon;
+	struct file *fp;
+	int error, fd;
+
+	/* falloc() will fill in the descriptor for us. */
+	if ((error = fd_allocfile(&fp, &fd)) != 0)
+		return error;
+
+	filemon = kmem_alloc(sizeof(struct filemon), KM_SLEEP);
+	rw_init(&filemon->fm_mtx);
+	filemon->fm_fp = NULL;
+	filemon->fm_pid = curproc->p_pid;
+
+	rw_enter(&filemon_mtx, RW_WRITER);
+	TAILQ_INSERT_TAIL(&filemons_inuse, filemon, fm_link);
+	n_open++;
+	rw_exit(&filemon_mtx);
+
+	return fd_clone(fp, fd, oflags, &filemon_fileops, filemon);
+}
+
+
+static int
+filemon_close(struct file * fp)
+{
+	struct filemon *filemon;
+
+#ifdef DEBUG
+	log(logLevel, "filemon_close()");
+#endif
+	/*
+	 * Follow the same lock order as filemon_lookup()
+	 * and filemon_fp_data() but hold exclusive access to
+	 * filemon_mtx until we are done.
+	 */
+	rw_enter(&filemon_mtx, RW_WRITER);
+	filemon = fp->f_data;
+	if (!filemon) {
+		rw_exit(&filemon_mtx);
+		return EBADF;
+	}
+	/* ensure that filemon_lookup() will now fail */
+	TAILQ_REMOVE(&filemons_inuse, filemon, fm_link);
+	n_open--;
+	/* ensure that filemon_fp_data() will now fail */
+	fp->f_data = NULL;
+
+	/*
+	 * once we have exclusive access, it should never be used again
+	 */
+	rw_enter(&filemon->fm_mtx, RW_WRITER);
+	if (filemon->fm_fp) {
+		closef(filemon->fm_fp);	/* release our reference */
+		filemon->fm_fp = NULL;
+	}
+	rw_exit(&filemon->fm_mtx);
+	rw_destroy(&filemon->fm_mtx);
+	kmem_free(filemon, sizeof(struct filemon));
+	rw_exit(&filemon_mtx);
+	return (0);
+}
+
+static int
+filemon_ioctl(struct file * fp, u_long cmd, void *data)
+{
+	int error = 0;
+	int fd;
+	struct filemon *filemon;
+	struct proc *tp;
+
+#ifdef DEBUG
+	log(logLevel, "filemon_ioctl(%lu)", cmd);
+#endif
+
+	/*
+	 * this ensures we cannot get filemon if it is closing.
+	 */
+	filemon = filemon_fp_data(fp, RW_WRITER);
+	if (!filemon)
+		return EBADF;
+
+	/* filemon_fp_data() has locked the entry - make sure to unlock! */
+
+	switch (cmd) {
+	case FILEMON_SET_FD:
+		/* Set the output file descriptor. */
+
+		/* First, release any current output file descriptor */
+		if (filemon->fm_fp)
+			closef(filemon->fm_fp);
+
+		/* Now set up the new one */
+		fd = *((int *) data);
+		if ((filemon->fm_fp = fd_getfile2(curproc, fd)) == NULL) {
+			error = EBADF;
+			break;
+		}
+		if ((filemon->fm_fp->f_flag & FWRITE) == 0) {
+			closef(filemon->fm_fp);
+			filemon->fm_fp = NULL;
+			return (EBADF);
+		}
+		/* Write the file header. */
+		filemon_comment(filemon);
+		break;
+
+	case FILEMON_SET_PID:
+		/* Set the monitored process ID - if allowed. */
+		mutex_enter(proc_lock);
+		tp = proc_find(*((pid_t *) data));
+		if (tp == NULL ||
+		    tp->p_emul != &emul_netbsd) {
+			error = ESRCH;
+			mutex_exit(proc_lock);
+			break;
+		}
+
+		error = kauth_authorize_process(curproc->p_cred,
+		    KAUTH_PROCESS_CANSEE, tp,
+		    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
+		if (!error) {
+			filemon->fm_pid = tp->p_pid;
+		}
+		mutex_exit(proc_lock);
+		break;
+
+	default:
+		error = EINVAL;
+		break;
+	}
+
+	rw_exit(&filemon->fm_mtx);
+	return (error);
+}
+
+static int
+filemon_load(void *dummy __unused)
+{
+	rw_init(&filemon_mtx);
+
+	/* Install the syscall wrappers. */
+	return filemon_wrapper_install();
+}
+
+/*
+ * If this gets called we are linked into the kernel
+ */
+void
+filemonattach(int num)
+{
+
+	/*
+	 * Don't call filemon_load() here - it will be called from
+	 * filemon_modcmd() during module initialization.
+	 */
+#if 0
+	filemon_load(NULL);
+#endif
+}
+
+
+static int
+filemon_unload(void)
+{
+	int error = 0;
+
+	rw_enter(&filemon_mtx, RW_WRITER);
+
+	if (TAILQ_FIRST(&filemons_inuse) != NULL)
+		error = EBUSY;
+	else {
+		/* Deinstall the syscall wrappers. */
+		error = filemon_wrapper_deinstall();
+	}
+	rw_exit(&filemon_mtx);
+
+	if (error == 0) {
+		rw_destroy(&filemon_mtx);
+	}
+	return (error);
+}
+
+static int
+filemon_modcmd(modcmd_t cmd, void *data)
+{
+	int error = 0;
+#ifdef _MODULE
+	int bmajor = -1;
+	int cmajor = -1;
+#endif
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+#ifdef DEBUG
+		logLevel = LOG_INFO;
+#endif
+
+		error = filemon_load(data);
+#ifdef _MODULE
+		if (!error)
+			error = devsw_attach("filemon", NULL, &bmajor,
+			    &filemon_cdevsw, &cmajor);
+#endif
+		break;
+
+	case MODULE_CMD_FINI:
+		error = filemon_unload();
+#ifdef _MODULE
+		if (!error)
+			error = devsw_detach(NULL, &filemon_cdevsw);
+#endif
+		break;
+
+	case MODULE_CMD_STAT:
+		log(LOG_INFO, "filemon: open=%d", n_open);
+		break;
+
+	default:
+		error = ENOTTY;
+		break;
+
+	}
+
+	return (error);
+}

Index: src/sys/dev/filemon/filemon.h
diff -u /dev/null src/sys/dev/filemon/filemon.h:1.11
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/dev/filemon/filemon.h	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,62 @@
+/* $NetBSD: filemon.h,v 1.11 2019/12/23 06:45:38 maxv Exp $ */
+/*
+ * Copyright (c) 2010, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef FILEMON_SET_FD
+
+#include <sys/ioccom.h>
+
+#ifndef _PATH_FILEMON
+#define _PATH_FILEMON "/dev/filemon"
+#endif
+#define FILEMON_SET_FD		_IOWR('S', 1, int)
+#define FILEMON_SET_PID		_IOWR('S', 2, pid_t)
+
+#define FILEMON_VERSION		5
+
+#ifdef _KERNEL
+struct filemon {
+	pid_t fm_pid;		/* The process ID being monitored. */
+	char fm_fname1[MAXPATHLEN];/* Temporary filename buffer. */
+	char fm_fname2[MAXPATHLEN];/* Temporary filename buffer. */
+	char fm_msgbufr[32 + 2 * MAXPATHLEN];	/* Output message buffer. */
+	struct file *fm_fp;	/* Output file pointer. */
+	krwlock_t fm_mtx;		/* Lock mutex for this filemon. */
+	TAILQ_ENTRY(filemon) fm_link;	/* Link into the in-use list. */
+};
+
+struct hijack { 
+	int hj_index; 
+	sy_call_t *hj_funcs[2];	/* [0] = original, [1] = hijack */ 
+}; 
+
+struct filemon * filemon_lookup(struct proc *);
+void filemon_output(struct filemon *, char *, size_t);
+int syscall_hijack(struct sysent *, const struct hijack *, bool);
+int filemon_wrapper_install(void);
+int  filemon_wrapper_deinstall(void);
+void filemon_printf(struct filemon *, const char *, ...) __printflike(2, 3);
+#endif
+
+#endif

Index: src/sys/dev/filemon/filemon_wrapper.c
diff -u /dev/null src/sys/dev/filemon/filemon_wrapper.c:1.14
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/dev/filemon/filemon_wrapper.c	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,456 @@
+/*	$NetBSD: filemon_wrapper.c,v 1.14 2019/12/23 06:45:38 maxv Exp $	*/
+
+/*
+ * Copyright (c) 2010, Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.14 2019/12/23 06:45:38 maxv Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/lwp.h>
+#include <sys/proc.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+#include "filemon.h"
+
+static int filemon_wrapper_chdir(struct lwp *, const struct sys_chdir_args *,
+				register_t *);
+static int filemon_wrapper_execve(struct lwp *, struct sys_execve_args *,
+				register_t *);
+static int filemon_wrapper_sys_exit(struct lwp *, struct sys_exit_args *,
+				register_t *);
+static int filemon_wrapper_fork(struct lwp *, const void *, register_t *);
+static int filemon_wrapper_link(struct lwp *, struct sys_link_args *,
+				register_t *);
+static int filemon_wrapper_open(struct lwp *, struct sys_open_args *,
+				register_t *);
+static int filemon_wrapper_openat(struct lwp *, struct sys_openat_args *,
+				register_t *);
+static int filemon_wrapper_rename(struct lwp *, struct sys_rename_args *,
+				register_t *);
+static int filemon_wrapper_symlink(struct lwp *, struct sys_symlink_args *,
+				register_t *);
+static int filemon_wrapper_unlink(struct lwp *, struct sys_unlink_args *,
+				register_t *);
+static int filemon_wrapper_vfork(struct lwp *, const void *, register_t *);
+
+const struct hijack filemon_hijack[] = {
+	{ SYS_chdir,
+	   { (sy_call_t *)sys_chdir,   (sy_call_t *)filemon_wrapper_chdir   } },
+	{ SYS_execve,
+	   { (sy_call_t *)sys_execve,  (sy_call_t *)filemon_wrapper_execve  } },
+	{ SYS_exit,
+	   { (sy_call_t *)sys_exit,    (sy_call_t *)filemon_wrapper_sys_exit } },
+	{ SYS_fork,
+	   { (sy_call_t *)sys_fork,    (sy_call_t *)filemon_wrapper_fork    } },
+	{ SYS_link,
+	   { (sy_call_t *)sys_link,    (sy_call_t *)filemon_wrapper_link    } },
+	{ SYS_open,
+	   { (sy_call_t *)sys_open,    (sy_call_t *)filemon_wrapper_open    } },
+	{ SYS_openat,
+	   { (sy_call_t *)sys_openat,  (sy_call_t *)filemon_wrapper_openat  } },
+	{ SYS_rename,
+	   { (sy_call_t *)sys_rename,  (sy_call_t *)filemon_wrapper_rename  } },
+	{ SYS_symlink,
+	   { (sy_call_t *)sys_symlink, (sy_call_t *)filemon_wrapper_symlink } },
+	{ SYS_unlink,
+	   { (sy_call_t *)sys_unlink,  (sy_call_t *)filemon_wrapper_unlink  } },
+	{ SYS_vfork,
+	   { (sy_call_t *)sys_vfork,   (sy_call_t *)filemon_wrapper_vfork   } },
+	{ -1, {NULL, NULL } }
+};
+
+int
+syscall_hijack(struct sysent *sv_table, const struct hijack *hj_pkg,
+		bool restore)
+{
+	int from, to;
+	const struct hijack *entry;
+
+	if (restore)		/* Which entry should currently match? */
+		from = 1;
+	else
+		from = 0;
+	to = 1 - from;		/* Which entry will we replace with? */
+
+	KASSERT(kernconfig_is_held());
+
+	/* First, make sure that all of the old values match */
+	for (entry = hj_pkg; entry->hj_index >= 0; entry++)
+		if (sv_table[entry->hj_index].sy_call != entry->hj_funcs[from])
+			break;
+
+	if (entry->hj_index >= 0)
+		return EBUSY;
+
+	/* Now replace the old values with the new ones */
+	for (entry = hj_pkg; entry->hj_index >= 0; entry++)
+		sv_table[entry->hj_index].sy_call = entry->hj_funcs[to];
+
+	return 0;
+}
+
+static int
+filemon_wrapper_chdir(struct lwp * l, const struct sys_chdir_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+	
+	if ((error = sys_chdir(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	filemon_printf(filemon, "C %d %s\n",
+	    curproc->p_pid, filemon->fm_fname1);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_execve(struct lwp * l, struct sys_execve_args * uap,
+    register_t * retval)
+{
+	char fname[MAXPATHLEN];
+	int error, cerror;
+	size_t done;
+	struct filemon *filemon;
+
+	cerror = copyinstr(SCARG(uap, path), fname, sizeof(fname), &done);
+
+	if ((error = sys_execve(l, uap, retval)) != EJUSTRETURN)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return EJUSTRETURN;
+
+	if (cerror)
+		goto out;
+
+	filemon_printf(filemon, "E %d %s\n", curproc->p_pid, fname);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return EJUSTRETURN;
+}
+
+
+static int
+filemon_wrapper_fork(struct lwp * l, const void *v, register_t * retval)
+{
+	int error;
+	struct filemon *filemon;
+
+	if ((error = sys_fork(l, v, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	filemon_printf(filemon, "F %d %ld\n", curproc->p_pid, (long) retval[0]);
+
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_vfork(struct lwp * l, const void *v, register_t * retval)
+{
+	int error;
+	struct filemon *filemon;
+
+	if ((error = sys_vfork(l, v, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	filemon_printf(filemon, "F %d %ld\n", curproc->p_pid, (long) retval[0]);
+
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static void
+filemon_flags(struct filemon * filemon, int f)
+{
+	if (f & O_RDWR) {
+		/* we want a separate R record */
+		filemon_printf(filemon, "R %d %s\n", curproc->p_pid,
+		    filemon->fm_fname1);
+	}
+
+	filemon_printf(filemon, "%c %d %s\n", (f & O_ACCMODE) ? 'W' : 'R',
+	    curproc->p_pid, filemon->fm_fname1);
+}
+
+static int
+filemon_wrapper_open(struct lwp * l, struct sys_open_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_open(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	filemon_flags(filemon, SCARG(uap, flags));
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_openat(struct lwp * l, struct sys_openat_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_openat(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	if (filemon->fm_fname1[0] != '/' && SCARG(uap, fd) != AT_FDCWD) {
+		/*
+		 * Rats we cannot just treat like open.
+		 * Output an 'A' record as a clue.
+		 */
+		filemon_printf(filemon, "A %d %s\n", curproc->p_pid,
+		    filemon->fm_fname1);
+	}
+
+	filemon_flags(filemon, SCARG(uap, oflags));
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_rename(struct lwp * l, struct sys_rename_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_rename(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, from), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	error = copyinstr(SCARG(uap, to), filemon->fm_fname2,
+	    sizeof(filemon->fm_fname2), &done);
+	if (error)
+		goto out;
+
+	filemon_printf(filemon, "M %d '%s' '%s'\n", curproc->p_pid,
+	    filemon->fm_fname1, filemon->fm_fname2);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_link(struct lwp * l, struct sys_link_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_link(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	error = copyinstr(SCARG(uap, link), filemon->fm_fname2,
+	    sizeof(filemon->fm_fname2), &done);
+	if (error)
+		goto out;
+
+	filemon_printf(filemon, "L %d '%s' '%s'\n", curproc->p_pid,
+	    filemon->fm_fname1, filemon->fm_fname2);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+static int
+filemon_wrapper_symlink(struct lwp * l, struct sys_symlink_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_symlink(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	error = copyinstr(SCARG(uap, link), filemon->fm_fname2,
+	    sizeof(filemon->fm_fname2), &done);
+	if (error)
+		goto out;
+
+	filemon_printf(filemon, "L %d '%s' '%s'\n", curproc->p_pid,
+	    filemon->fm_fname1, filemon->fm_fname2);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+
+static int
+filemon_wrapper_sys_exit(struct lwp * l, struct sys_exit_args * uap,
+    register_t * retval)
+{
+	struct filemon *filemon;
+
+	filemon = filemon_lookup(curproc);
+
+	if (filemon) {
+		filemon_printf(filemon, "X %d %d\n",
+		    curproc->p_pid, SCARG(uap, rval));
+
+		/* Check if the monitored process is about to exit. */
+		if (filemon->fm_pid == curproc->p_pid)
+			filemon_printf(filemon, "# Bye bye\n");
+
+		rw_exit(&filemon->fm_mtx);
+	}
+	return sys_exit(l, uap, retval);
+}
+
+static int
+filemon_wrapper_unlink(struct lwp * l, struct sys_unlink_args * uap,
+    register_t * retval)
+{
+	int error;
+	size_t done;
+	struct filemon *filemon;
+
+	if ((error = sys_unlink(l, uap, retval)) != 0)
+		return error;
+
+	filemon = filemon_lookup(curproc);
+	if (filemon == NULL)
+		return 0;
+
+	error = copyinstr(SCARG(uap, path), filemon->fm_fname1,
+	    sizeof(filemon->fm_fname1), &done);
+	if (error)
+		goto out;
+
+	filemon_printf(filemon, "D %d %s\n",
+	    curproc->p_pid, filemon->fm_fname1);
+out:
+	rw_exit(&filemon->fm_mtx);
+	return 0;
+}
+
+
+int
+filemon_wrapper_install(void)
+{
+	int error;
+	struct sysent *sv_table = emul_netbsd.e_sysent;
+
+	kernconfig_lock();
+	error = syscall_hijack(sv_table, filemon_hijack, false);
+	kernconfig_unlock();
+
+	return error;
+}
+
+int
+filemon_wrapper_deinstall(void)
+{
+	int error;
+	struct sysent *sv_table = emul_netbsd.e_sysent;
+
+	kernconfig_lock();
+	error = syscall_hijack(sv_table, filemon_hijack, true);
+	kernconfig_unlock();
+
+	return error;
+}

Index: src/sys/modules/filemon/Makefile
diff -u /dev/null src/sys/modules/filemon/Makefile:1.6
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/modules/filemon/Makefile	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,20 @@
+# $NetBSD: Makefile,v 1.6 2019/12/23 06:45:38 maxv Exp $
+
+.include "../Makefile.inc"
+
+.PATH: ${S}/dev/filemon
+
+KMOD = filemon
+IOCONF=	filemon.ioconf
+SRCS = filemon.c filemon_wrapper.c
+NOMAN = no
+
+COPTS.filemon_wrapper.c+=	${GCC_NO_CAST_FUNCTION_TYPE}
+
+# Due to security concerns, we don't install the filemon module.  We
+# do, however, want to keep building it to prevent bit-rot.  Define
+# an empty install target for this.
+
+kmodinstall:
+
+.include <bsd.kmodule.mk>

Index: src/sys/modules/filemon/filemon.ioconf
diff -u /dev/null src/sys/modules/filemon/filemon.ioconf:1.3
--- /dev/null	Mon Dec 23 06:45:38 2019
+++ src/sys/modules/filemon/filemon.ioconf	Mon Dec 23 06:45:38 2019
@@ -0,0 +1,7 @@
+#	$NetBSD: filemon.ioconf,v 1.3 2019/12/23 06:45:38 maxv Exp $
+
+ioconf		filemon
+
+include		"conf/files"
+
+pseudo-device   filemon

Reply via email to