Remove filemon(4).
Discussed on tech-kern: https://mail-index.NetBSD.org/tech-kern/2020/01/13/msg025938.html This was never (intentionally) enabled by default, and the design has some shortcomings. You can get mostly the same results with ktrace, as in usr.bin/make/filemon/filemon_ktrace.c which is now used instead of filemon for make's meta mode. If applications require higher performance than ktrace, or nesting that ktrace doesn't support, we might consider adding something back into the vfs system calls themselves, without hijacking the syscall table. (Might want a more reliable output format too, e.g. one that can handle newlines in file names.)
This commit is contained in:
parent
b8bc1cd703
commit
08a157de6e
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1225 2020/01/19 06:55:22 thorpej Exp $
|
||||
# $NetBSD: mi,v 1.1226 2020/01/19 20:41:17 riastradh 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-c-usr
|
||||
./usr/include/dev/filemon base-obsolete obsolete
|
||||
./usr/include/dev/hdaudio base-c-usr
|
||||
./usr/include/dev/hdmicec base-c-usr
|
||||
./usr/include/dev/hid base-c-usr
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.2303 2020/01/19 20:00:36 thorpej Exp $
|
||||
# $NetBSD: mi,v 1.2304 2020/01/19 20:41:17 riastradh 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-c-include
|
||||
./usr/include/dev/filemon/filemon.h comp-obsolete obsolete
|
||||
./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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: mi,v 1.1673 2020/01/19 20:00:36 thorpej Exp $
|
||||
# $NetBSD: mi,v 1.1674 2020/01/19 20:41:17 riastradh Exp $
|
||||
#
|
||||
# Note: don't delete entries from here - mark them as "obsolete" instead.
|
||||
#
|
||||
@ -1105,7 +1105,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-sys-catman .cat
|
||||
./usr/share/man/cat4/filemon.0 man-obsolete obsolete
|
||||
./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
|
||||
@ -4289,7 +4289,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-sys-htmlman html
|
||||
./usr/share/man/html4/filemon.html man-obsolete obsolete
|
||||
./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
|
||||
@ -7245,7 +7245,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-sys-man .man
|
||||
./usr/share/man/man4/filemon.4 man-obsolete obsolete
|
||||
./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
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: MAKEDEV.tmpl,v 1.212 2019/12/23 06:45:37 maxv Exp $
|
||||
# $NetBSD: MAKEDEV.tmpl,v 1.213 2020/01/19 20:41:18 riastradh Exp $
|
||||
#
|
||||
# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
@ -816,7 +816,6 @@ 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
|
||||
@ -2182,10 +2181,6 @@ 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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: NetBSD.dist.base,v 1.208 2019/12/23 06:45:37 maxv Exp $
|
||||
# $NetBSD: NetBSD.dist.base,v 1.209 2020/01/19 20:41:18 riastradh Exp $
|
||||
# @(#)4.4BSD.dist 8.1 (Berkeley) 6/13/93
|
||||
|
||||
# Do not customize this file as it may be overwritten on upgrades.
|
||||
@ -121,7 +121,6 @@
|
||||
./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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.697 2020/01/19 20:00:35 thorpej Exp $
|
||||
# $NetBSD: Makefile,v 1.698 2020/01/19 20:41:18 riastradh 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 acphy.4 \
|
||||
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 filemon.4 finsio.4 flash.4 fpa.4 fms.4 fss.4 \
|
||||
fd.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 \
|
||||
|
@ -1,248 +0,0 @@
|
||||
.\" $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 .
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: ALL,v 1.139 2020/01/19 20:00:37 thorpej Exp $
|
||||
# $NetBSD: ALL,v 1.140 2020/01/19 20:41:18 riastradh 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.139 $"
|
||||
#ident "ALL-$Revision: 1.140 $"
|
||||
|
||||
maxusers 64 # estimated number of users
|
||||
|
||||
@ -1667,8 +1667,6 @@ pseudo-device bcsp # BlueCore Serial Protocol
|
||||
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.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: ALL,v 1.483 2020/01/19 20:00:37 thorpej Exp $
|
||||
# $NetBSD: ALL,v 1.484 2020/01/19 20:41:18 riastradh 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.483 $"
|
||||
#ident "ALL-$Revision: 1.484 $"
|
||||
|
||||
maxusers 64 # estimated number of users
|
||||
|
||||
@ -1789,8 +1789,6 @@ pseudo-device bcsp # BlueCore Serial Protocol
|
||||
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.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files,v 1.1251 2020/01/19 20:00:37 thorpej Exp $
|
||||
# $NetBSD: files,v 1.1252 2020/01/19 20:41:18 riastradh Exp $
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
version 20171118
|
||||
@ -1530,12 +1530,6 @@ 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
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: majors,v 1.92 2019/12/23 06:45:37 maxv Exp $
|
||||
# $NetBSD: majors,v 1.93 2020/01/19 20:41:18 riastradh 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
|
||||
device-major filemon char 202 filemon
|
||||
# char 202, formerly filemon
|
||||
device-major iscsi char 203 iscsi
|
||||
device-major tpm char 204 tpm
|
||||
device-major mfi char 205 mfi
|
||||
|
@ -1,6 +1,6 @@
|
||||
# $NetBSD: Makefile,v 1.43 2019/12/23 06:45:37 maxv Exp $
|
||||
# $NetBSD: Makefile,v 1.44 2020/01/19 20:41:18 riastradh Exp $
|
||||
|
||||
SUBDIR= apm ata bluetooth dec dm dmover dtv filemon hdaudio hdmicec hid hpc \
|
||||
SUBDIR= apm ata bluetooth dec dm dmover dtv 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
|
||||
|
@ -1,8 +0,0 @@
|
||||
# $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>
|
@ -1,445 +0,0 @@
|
||||
/* $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);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/* $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
|
@ -1,456 +0,0 @@
|
||||
/* $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;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#!/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
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.235 2020/01/19 01:25:08 thorpej Exp $
|
||||
# $NetBSD: Makefile,v 1.236 2020/01/19 20:41:19 riastradh Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
@ -54,7 +54,6 @@ SUBDIR+= exec_script
|
||||
SUBDIR+= fdesc
|
||||
SUBDIR+= ffs
|
||||
SUBDIR+= filecore
|
||||
SUBDIR+= filemon
|
||||
SUBDIR+= flash
|
||||
SUBDIR+= fss
|
||||
SUBDIR+= gpio
|
||||
|
@ -1,20 +0,0 @@
|
||||
# $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>
|
@ -1,7 +0,0 @@
|
||||
# $NetBSD: filemon.ioconf,v 1.3 2019/12/23 06:45:38 maxv Exp $
|
||||
|
||||
ioconf filemon
|
||||
|
||||
include "conf/files"
|
||||
|
||||
pseudo-device filemon
|
Loading…
Reference in New Issue
Block a user