Revert the removal of filemon.
This commit is contained in:
parent
0c3f769417
commit
87107185b5
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 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 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 \
|
||||
|
|
|
@ -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 .
|
|
@ -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 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.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 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.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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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
|
|
@ -1140,6 +1140,7 @@ fhstatvfs
|
|||
fhtovp
|
||||
fileassoc
|
||||
fileio
|
||||
filemon
|
||||
filt
|
||||
fincore
|
||||
fingerd
|
||||
|
|
Loading…
Reference in New Issue