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