1eb9aea5aSDavid E. O'Brien /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4eb9aea5aSDavid E. O'Brien * Copyright (c) 2011, David E. O'Brien.
5eb9aea5aSDavid E. O'Brien * Copyright (c) 2009-2011, Juniper Networks, Inc.
6e0d84b9eSBryan Drewery * Copyright (c) 2015-2016, EMC Corp.
7eb9aea5aSDavid E. O'Brien * All rights reserved.
8eb9aea5aSDavid E. O'Brien *
9eb9aea5aSDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
10eb9aea5aSDavid E. O'Brien * modification, are permitted provided that the following conditions
11eb9aea5aSDavid E. O'Brien * are met:
12eb9aea5aSDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
13eb9aea5aSDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
14eb9aea5aSDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
15eb9aea5aSDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
16eb9aea5aSDavid E. O'Brien * documentation and/or other materials provided with the distribution.
17eb9aea5aSDavid E. O'Brien *
18eb9aea5aSDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND
19eb9aea5aSDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20eb9aea5aSDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21eb9aea5aSDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE
22eb9aea5aSDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23eb9aea5aSDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24eb9aea5aSDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25eb9aea5aSDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26eb9aea5aSDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27eb9aea5aSDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28eb9aea5aSDavid E. O'Brien * SUCH DAMAGE.
29eb9aea5aSDavid E. O'Brien */
30eb9aea5aSDavid E. O'Brien
31eb9aea5aSDavid E. O'Brien #include <sys/cdefs.h>
3279d69913SBryan Drewery #include <sys/eventhandler.h>
338536d1b7SBryan Drewery #include <sys/filedesc.h>
348536d1b7SBryan Drewery #include <sys/imgact.h>
35f14fbe72SBryan Drewery #include <sys/priv.h>
36c849fda8SSimon J. Gerraty #include <sys/sx.h>
3766afa415SBryan Drewery #include <sys/sysent.h>
38f889a61aSBryan Drewery #include <sys/vnode.h>
39c849fda8SSimon J. Gerraty
40bc0d7285SBryan Drewery #include <machine/stdarg.h>
41bc0d7285SBryan Drewery
42bc0d7285SBryan Drewery static void filemon_output_event(struct filemon *filemon, const char *fmt, ...)
43bc0d7285SBryan Drewery __printflike(2, 3);
44bc0d7285SBryan Drewery
45f889a61aSBryan Drewery static eventhandler_tag filemon_exec_tag;
4679d69913SBryan Drewery static eventhandler_tag filemon_exit_tag;
472f600962SBryan Drewery static eventhandler_tag filemon_fork_tag;
4879d69913SBryan Drewery
49eb9aea5aSDavid E. O'Brien static void
filemon_output(struct filemon * filemon,char * msg,size_t len)50eb9aea5aSDavid E. O'Brien filemon_output(struct filemon *filemon, char *msg, size_t len)
51eb9aea5aSDavid E. O'Brien {
52eb9aea5aSDavid E. O'Brien struct uio auio;
53eb9aea5aSDavid E. O'Brien struct iovec aiov;
544177d9f7SBryan Drewery int error;
55eb9aea5aSDavid E. O'Brien
56eb9aea5aSDavid E. O'Brien if (filemon->fp == NULL)
57eb9aea5aSDavid E. O'Brien return;
58eb9aea5aSDavid E. O'Brien
59eb9aea5aSDavid E. O'Brien aiov.iov_base = msg;
60eb9aea5aSDavid E. O'Brien aiov.iov_len = len;
61eb9aea5aSDavid E. O'Brien auio.uio_iov = &aiov;
62eb9aea5aSDavid E. O'Brien auio.uio_iovcnt = 1;
63eb9aea5aSDavid E. O'Brien auio.uio_resid = len;
64eb9aea5aSDavid E. O'Brien auio.uio_segflg = UIO_SYSSPACE;
65eb9aea5aSDavid E. O'Brien auio.uio_rw = UIO_WRITE;
66eb9aea5aSDavid E. O'Brien auio.uio_td = curthread;
67eb9aea5aSDavid E. O'Brien auio.uio_offset = (off_t) -1;
68eb9aea5aSDavid E. O'Brien
698a81693aSBryan Drewery if (filemon->fp->f_type == DTYPE_VNODE)
70eb9aea5aSDavid E. O'Brien bwillwrite();
71eb9aea5aSDavid E. O'Brien
727ae27ff9SBryan Drewery error = fo_write(filemon->fp, &auio, filemon->cred, 0, curthread);
73b7622235SBryan Drewery if (error != 0 && filemon->error == 0)
744177d9f7SBryan Drewery filemon->error = error;
75eb9aea5aSDavid E. O'Brien }
76eb9aea5aSDavid E. O'Brien
77bc0d7285SBryan Drewery static void
filemon_output_event(struct filemon * filemon,const char * fmt,...)78bc0d7285SBryan Drewery filemon_output_event(struct filemon *filemon, const char *fmt, ...)
79bc0d7285SBryan Drewery {
80bc0d7285SBryan Drewery va_list ap;
81bc0d7285SBryan Drewery size_t len;
82bc0d7285SBryan Drewery
83bc0d7285SBryan Drewery va_start(ap, fmt);
84bc0d7285SBryan Drewery len = vsnprintf(filemon->msgbufr, sizeof(filemon->msgbufr), fmt, ap);
85bc0d7285SBryan Drewery va_end(ap);
86bc0d7285SBryan Drewery /* The event is truncated but still worth logging. */
87bc0d7285SBryan Drewery if (len >= sizeof(filemon->msgbufr))
88bc0d7285SBryan Drewery len = sizeof(filemon->msgbufr) - 1;
89bc0d7285SBryan Drewery filemon_output(filemon, filemon->msgbufr, len);
90bc0d7285SBryan Drewery }
91bc0d7285SBryan Drewery
92eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_chdir(struct thread * td,struct chdir_args * uap)93eb9aea5aSDavid E. O'Brien filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
94eb9aea5aSDavid E. O'Brien {
959b511ce9SBryan Drewery int error, ret;
96eb9aea5aSDavid E. O'Brien struct filemon *filemon;
97eb9aea5aSDavid E. O'Brien
98eb9aea5aSDavid E. O'Brien if ((ret = sys_chdir(td, uap)) == 0) {
99e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
1009b511ce9SBryan Drewery if ((error = copyinstr(uap->path, filemon->fname1,
1019b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
1029b511ce9SBryan Drewery filemon->error = error;
1039b511ce9SBryan Drewery goto copyfail;
1049b511ce9SBryan Drewery }
105eb9aea5aSDavid E. O'Brien
106bc0d7285SBryan Drewery filemon_output_event(filemon, "C %d %s\n",
107eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1);
1089b511ce9SBryan Drewery copyfail:
109e0d84b9eSBryan Drewery filemon_drop(filemon);
110eb9aea5aSDavid E. O'Brien }
111eb9aea5aSDavid E. O'Brien }
112eb9aea5aSDavid E. O'Brien
113eb9aea5aSDavid E. O'Brien return (ret);
114eb9aea5aSDavid E. O'Brien }
115eb9aea5aSDavid E. O'Brien
116f889a61aSBryan Drewery static void
filemon_event_process_exec(void * arg __unused,struct proc * p,struct image_params * imgp)117f889a61aSBryan Drewery filemon_event_process_exec(void *arg __unused, struct proc *p,
118f889a61aSBryan Drewery struct image_params *imgp)
119eb9aea5aSDavid E. O'Brien {
120eb9aea5aSDavid E. O'Brien struct filemon *filemon;
121eb9aea5aSDavid E. O'Brien
122e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p)) != NULL) {
123bc0d7285SBryan Drewery filemon_output_event(filemon, "E %d %s\n",
12423ae5cd7SBryan Drewery p->p_pid,
12523ae5cd7SBryan Drewery imgp->execpath != NULL ? imgp->execpath : "<unknown>");
126eb9aea5aSDavid E. O'Brien
127f14fbe72SBryan Drewery /* If the credentials changed then cease tracing. */
128f14fbe72SBryan Drewery if (imgp->newcred != NULL &&
129f14fbe72SBryan Drewery imgp->credential_setid &&
130cc426dd3SMateusz Guzik priv_check_cred(filemon->cred, PRIV_DEBUG_DIFFCRED) != 0) {
131f14fbe72SBryan Drewery /*
132f14fbe72SBryan Drewery * It may have changed to NULL already, but
133f14fbe72SBryan Drewery * will not be re-attached by anything else.
134f14fbe72SBryan Drewery */
135f14fbe72SBryan Drewery if (p->p_filemon != NULL) {
136f14fbe72SBryan Drewery KASSERT(p->p_filemon == filemon,
137f14fbe72SBryan Drewery ("%s: proc %p didn't have expected"
138f14fbe72SBryan Drewery " filemon %p", __func__, p, filemon));
139f14fbe72SBryan Drewery filemon_proc_drop(p);
140f14fbe72SBryan Drewery }
141f14fbe72SBryan Drewery }
142f14fbe72SBryan Drewery
143f14fbe72SBryan Drewery
144e0d84b9eSBryan Drewery filemon_drop(filemon);
145eb9aea5aSDavid E. O'Brien }
146eb9aea5aSDavid E. O'Brien }
147eb9aea5aSDavid E. O'Brien
1484d3cfa1dSBryan Drewery static void
_filemon_wrapper_openat(struct thread * td,const char * upath,int flags,int fd)14912e69f96SBrooks Davis _filemon_wrapper_openat(struct thread *td, const char *upath, int flags,
15012e69f96SBrooks Davis int fd)
151eb9aea5aSDavid E. O'Brien {
1529b511ce9SBryan Drewery int error;
1538536d1b7SBryan Drewery struct file *fp;
154eb9aea5aSDavid E. O'Brien struct filemon *filemon;
1558536d1b7SBryan Drewery char *atpath, *freepath;
1568536d1b7SBryan Drewery cap_rights_t rights;
157eb9aea5aSDavid E. O'Brien
158e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
1598536d1b7SBryan Drewery atpath = "";
1608536d1b7SBryan Drewery freepath = NULL;
1618536d1b7SBryan Drewery fp = NULL;
1628536d1b7SBryan Drewery
1639b511ce9SBryan Drewery if ((error = copyinstr(upath, filemon->fname1,
1649b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
1659b511ce9SBryan Drewery filemon->error = error;
1669b511ce9SBryan Drewery goto copyfail;
1679b511ce9SBryan Drewery }
168f859e956SSimon J. Gerraty
1694d3cfa1dSBryan Drewery if (filemon->fname1[0] != '/' && fd != AT_FDCWD) {
170f859e956SSimon J. Gerraty /*
171f859e956SSimon J. Gerraty * rats - we cannot do too much about this.
172f859e956SSimon J. Gerraty * the trace should show a dir we read
173f859e956SSimon J. Gerraty * recently.. output an A record as a clue
174f859e956SSimon J. Gerraty * until we can do better.
1758536d1b7SBryan Drewery * XXX: This may be able to come out with
1768536d1b7SBryan Drewery * the namecache lookup now.
177f859e956SSimon J. Gerraty */
178bc0d7285SBryan Drewery filemon_output_event(filemon, "A %d %s\n",
179f859e956SSimon J. Gerraty curproc->p_pid, filemon->fname1);
1808536d1b7SBryan Drewery /*
1818536d1b7SBryan Drewery * Try to resolve the path from the vnode using the
1828536d1b7SBryan Drewery * namecache. It may be inaccurate, but better
1838536d1b7SBryan Drewery * than nothing.
1848536d1b7SBryan Drewery */
1858536d1b7SBryan Drewery if (getvnode(td, fd,
1866b3a9a0fSMateusz Guzik cap_rights_init_one(&rights, CAP_LOOKUP), &fp) == 0) {
187feabaaf9SMateusz Guzik vn_fullpath(fp->f_vnode, &atpath, &freepath);
1888536d1b7SBryan Drewery }
189f859e956SSimon J. Gerraty }
1904d3cfa1dSBryan Drewery if (flags & O_RDWR) {
191f859e956SSimon J. Gerraty /*
192f859e956SSimon J. Gerraty * We'll get the W record below, but need
1934d3cfa1dSBryan Drewery * to also output an R to distinguish from
194f859e956SSimon J. Gerraty * O_WRONLY.
195f859e956SSimon J. Gerraty */
196bc0d7285SBryan Drewery filemon_output_event(filemon, "R %d %s%s%s\n",
1978536d1b7SBryan Drewery curproc->p_pid, atpath,
1988536d1b7SBryan Drewery atpath[0] != '\0' ? "/" : "", filemon->fname1);
199f859e956SSimon J. Gerraty }
200f859e956SSimon J. Gerraty
201bc0d7285SBryan Drewery filemon_output_event(filemon, "%c %d %s%s%s\n",
2024d3cfa1dSBryan Drewery (flags & O_ACCMODE) ? 'W':'R',
2038536d1b7SBryan Drewery curproc->p_pid, atpath,
2048536d1b7SBryan Drewery atpath[0] != '\0' ? "/" : "", filemon->fname1);
2059b511ce9SBryan Drewery copyfail:
206e0d84b9eSBryan Drewery filemon_drop(filemon);
2078536d1b7SBryan Drewery if (fp != NULL)
2088536d1b7SBryan Drewery fdrop(fp, td);
2098536d1b7SBryan Drewery free(freepath, M_TEMP);
210f859e956SSimon J. Gerraty }
211f859e956SSimon J. Gerraty }
212f859e956SSimon J. Gerraty
2134d3cfa1dSBryan Drewery static int
filemon_wrapper_open(struct thread * td,struct open_args * uap)2144d3cfa1dSBryan Drewery filemon_wrapper_open(struct thread *td, struct open_args *uap)
2154d3cfa1dSBryan Drewery {
2164d3cfa1dSBryan Drewery int ret;
2174d3cfa1dSBryan Drewery
2184d3cfa1dSBryan Drewery if ((ret = sys_open(td, uap)) == 0)
2194d3cfa1dSBryan Drewery _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD);
2204d3cfa1dSBryan Drewery
2214d3cfa1dSBryan Drewery return (ret);
2224d3cfa1dSBryan Drewery }
2234d3cfa1dSBryan Drewery
2244d3cfa1dSBryan Drewery static int
filemon_wrapper_openat(struct thread * td,struct openat_args * uap)2254d3cfa1dSBryan Drewery filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
2264d3cfa1dSBryan Drewery {
2274d3cfa1dSBryan Drewery int ret;
2284d3cfa1dSBryan Drewery
2294d3cfa1dSBryan Drewery if ((ret = sys_openat(td, uap)) == 0)
2304d3cfa1dSBryan Drewery _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd);
2314d3cfa1dSBryan Drewery
232f859e956SSimon J. Gerraty return (ret);
233f859e956SSimon J. Gerraty }
234f859e956SSimon J. Gerraty
235f859e956SSimon J. Gerraty static int
filemon_wrapper_rename(struct thread * td,struct rename_args * uap)236eb9aea5aSDavid E. O'Brien filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
237eb9aea5aSDavid E. O'Brien {
2389b511ce9SBryan Drewery int error, ret;
239eb9aea5aSDavid E. O'Brien struct filemon *filemon;
240eb9aea5aSDavid E. O'Brien
241eb9aea5aSDavid E. O'Brien if ((ret = sys_rename(td, uap)) == 0) {
242e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
2439b511ce9SBryan Drewery if (((error = copyinstr(uap->from, filemon->fname1,
2449b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) ||
2459b511ce9SBryan Drewery ((error = copyinstr(uap->to, filemon->fname2,
2469b511ce9SBryan Drewery sizeof(filemon->fname2), NULL)) != 0)) {
2479b511ce9SBryan Drewery filemon->error = error;
2489b511ce9SBryan Drewery goto copyfail;
2499b511ce9SBryan Drewery }
250eb9aea5aSDavid E. O'Brien
251bc0d7285SBryan Drewery filemon_output_event(filemon, "M %d '%s' '%s'\n",
252eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1, filemon->fname2);
2539b511ce9SBryan Drewery copyfail:
254e0d84b9eSBryan Drewery filemon_drop(filemon);
255eb9aea5aSDavid E. O'Brien }
256eb9aea5aSDavid E. O'Brien }
257eb9aea5aSDavid E. O'Brien
258eb9aea5aSDavid E. O'Brien return (ret);
259eb9aea5aSDavid E. O'Brien }
260eb9aea5aSDavid E. O'Brien
261d77f7e8cSBryan Drewery static void
_filemon_wrapper_link(struct thread * td,const char * upath1,const char * upath2)26212e69f96SBrooks Davis _filemon_wrapper_link(struct thread *td, const char *upath1,
26312e69f96SBrooks Davis const char *upath2)
264eb9aea5aSDavid E. O'Brien {
265eb9aea5aSDavid E. O'Brien struct filemon *filemon;
2669b511ce9SBryan Drewery int error;
267eb9aea5aSDavid E. O'Brien
268e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
2699b511ce9SBryan Drewery if (((error = copyinstr(upath1, filemon->fname1,
2709b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) ||
2719b511ce9SBryan Drewery ((error = copyinstr(upath2, filemon->fname2,
2729b511ce9SBryan Drewery sizeof(filemon->fname2), NULL)) != 0)) {
2739b511ce9SBryan Drewery filemon->error = error;
2749b511ce9SBryan Drewery goto copyfail;
2759b511ce9SBryan Drewery }
276eb9aea5aSDavid E. O'Brien
277bc0d7285SBryan Drewery filemon_output_event(filemon, "L %d '%s' '%s'\n",
278eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1, filemon->fname2);
2799b511ce9SBryan Drewery copyfail:
280e0d84b9eSBryan Drewery filemon_drop(filemon);
281eb9aea5aSDavid E. O'Brien }
282eb9aea5aSDavid E. O'Brien }
283eb9aea5aSDavid E. O'Brien
284d77f7e8cSBryan Drewery static int
filemon_wrapper_link(struct thread * td,struct link_args * uap)285d77f7e8cSBryan Drewery filemon_wrapper_link(struct thread *td, struct link_args *uap)
286d77f7e8cSBryan Drewery {
287d77f7e8cSBryan Drewery int ret;
288d77f7e8cSBryan Drewery
289d77f7e8cSBryan Drewery if ((ret = sys_link(td, uap)) == 0)
290d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path, uap->link);
291d77f7e8cSBryan Drewery
292eb9aea5aSDavid E. O'Brien return (ret);
293eb9aea5aSDavid E. O'Brien }
294eb9aea5aSDavid E. O'Brien
295eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_symlink(struct thread * td,struct symlink_args * uap)296eb9aea5aSDavid E. O'Brien filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
297eb9aea5aSDavid E. O'Brien {
298eb9aea5aSDavid E. O'Brien int ret;
299eb9aea5aSDavid E. O'Brien
300d77f7e8cSBryan Drewery if ((ret = sys_symlink(td, uap)) == 0)
301d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path, uap->link);
302eb9aea5aSDavid E. O'Brien
303eb9aea5aSDavid E. O'Brien return (ret);
304eb9aea5aSDavid E. O'Brien }
305eb9aea5aSDavid E. O'Brien
306eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_linkat(struct thread * td,struct linkat_args * uap)307eb9aea5aSDavid E. O'Brien filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
308eb9aea5aSDavid E. O'Brien {
309eb9aea5aSDavid E. O'Brien int ret;
310eb9aea5aSDavid E. O'Brien
311d77f7e8cSBryan Drewery if ((ret = sys_linkat(td, uap)) == 0)
312d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path1, uap->path2);
313eb9aea5aSDavid E. O'Brien
314eb9aea5aSDavid E. O'Brien return (ret);
315eb9aea5aSDavid E. O'Brien }
316eb9aea5aSDavid E. O'Brien
317eb9aea5aSDavid E. O'Brien static void
filemon_event_process_exit(void * arg __unused,struct proc * p)31879d69913SBryan Drewery filemon_event_process_exit(void *arg __unused, struct proc *p)
319eb9aea5aSDavid E. O'Brien {
320eb9aea5aSDavid E. O'Brien struct filemon *filemon;
321eb9aea5aSDavid E. O'Brien
322e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p)) != NULL) {
323bc0d7285SBryan Drewery filemon_output_event(filemon, "X %d %d %d\n",
324bc0d7285SBryan Drewery p->p_pid, p->p_xexit, p->p_xsig);
325eb9aea5aSDavid E. O'Brien
326e0d84b9eSBryan Drewery /*
327e0d84b9eSBryan Drewery * filemon_untrack_processes() may have dropped this p_filemon
328e0d84b9eSBryan Drewery * already while in filemon_proc_get() before acquiring the
329e0d84b9eSBryan Drewery * filemon lock.
330e0d84b9eSBryan Drewery */
331e0d84b9eSBryan Drewery KASSERT(p->p_filemon == NULL || p->p_filemon == filemon,
332e0d84b9eSBryan Drewery ("%s: p %p was attached while exiting, expected "
333e0d84b9eSBryan Drewery "filemon %p or NULL", __func__, p, filemon));
334e0d84b9eSBryan Drewery if (p->p_filemon == filemon)
335e0d84b9eSBryan Drewery filemon_proc_drop(p);
336eb9aea5aSDavid E. O'Brien
337e0d84b9eSBryan Drewery filemon_drop(filemon);
338eb9aea5aSDavid E. O'Brien }
339eb9aea5aSDavid E. O'Brien }
340eb9aea5aSDavid E. O'Brien
341eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_unlink(struct thread * td,struct unlink_args * uap)342eb9aea5aSDavid E. O'Brien filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
343eb9aea5aSDavid E. O'Brien {
3449b511ce9SBryan Drewery int error, ret;
345eb9aea5aSDavid E. O'Brien struct filemon *filemon;
346eb9aea5aSDavid E. O'Brien
347eb9aea5aSDavid E. O'Brien if ((ret = sys_unlink(td, uap)) == 0) {
348e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
3499b511ce9SBryan Drewery if ((error = copyinstr(uap->path, filemon->fname1,
3509b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
3519b511ce9SBryan Drewery filemon->error = error;
3529b511ce9SBryan Drewery goto copyfail;
3539b511ce9SBryan Drewery }
354eb9aea5aSDavid E. O'Brien
355bc0d7285SBryan Drewery filemon_output_event(filemon, "D %d %s\n",
356eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1);
3579b511ce9SBryan Drewery copyfail:
358e0d84b9eSBryan Drewery filemon_drop(filemon);
359eb9aea5aSDavid E. O'Brien }
360eb9aea5aSDavid E. O'Brien }
361eb9aea5aSDavid E. O'Brien
362eb9aea5aSDavid E. O'Brien return (ret);
363eb9aea5aSDavid E. O'Brien }
364eb9aea5aSDavid E. O'Brien
3652f600962SBryan Drewery static void
filemon_event_process_fork(void * arg __unused,struct proc * p1,struct proc * p2,int flags __unused)3662f600962SBryan Drewery filemon_event_process_fork(void *arg __unused, struct proc *p1,
367e95c55e5SBryan Drewery struct proc *p2, int flags __unused)
368eb9aea5aSDavid E. O'Brien {
369eb9aea5aSDavid E. O'Brien struct filemon *filemon;
370eb9aea5aSDavid E. O'Brien
371e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p1)) != NULL) {
372bc0d7285SBryan Drewery filemon_output_event(filemon, "F %d %d\n",
3732f600962SBryan Drewery p1->p_pid, p2->p_pid);
374eb9aea5aSDavid E. O'Brien
375e0d84b9eSBryan Drewery /*
376e0d84b9eSBryan Drewery * filemon_untrack_processes() or
377e0d84b9eSBryan Drewery * filemon_ioctl(FILEMON_SET_PID) may have changed the parent's
378e0d84b9eSBryan Drewery * p_filemon while in filemon_proc_get() before acquiring the
379e0d84b9eSBryan Drewery * filemon lock. Only inherit if the parent is still traced by
380e0d84b9eSBryan Drewery * this filemon.
381e0d84b9eSBryan Drewery */
382e0d84b9eSBryan Drewery if (p1->p_filemon == filemon) {
383e0d84b9eSBryan Drewery PROC_LOCK(p2);
384e0d84b9eSBryan Drewery /*
385e0d84b9eSBryan Drewery * It may have been attached to already by a new
386e0d84b9eSBryan Drewery * filemon.
387e0d84b9eSBryan Drewery */
388e0d84b9eSBryan Drewery if (p2->p_filemon == NULL) {
389e0d84b9eSBryan Drewery p2->p_filemon = filemon_acquire(filemon);
390e0d84b9eSBryan Drewery ++filemon->proccnt;
391e0d84b9eSBryan Drewery }
392e0d84b9eSBryan Drewery PROC_UNLOCK(p2);
393e0d84b9eSBryan Drewery }
394e0d84b9eSBryan Drewery
395e0d84b9eSBryan Drewery filemon_drop(filemon);
396eb9aea5aSDavid E. O'Brien }
397eb9aea5aSDavid E. O'Brien }
398eb9aea5aSDavid E. O'Brien
399eb9aea5aSDavid E. O'Brien static void
filemon_wrapper_install(void)400eb9aea5aSDavid E. O'Brien filemon_wrapper_install(void)
401eb9aea5aSDavid E. O'Brien {
402eb9aea5aSDavid E. O'Brien
40366afa415SBryan Drewery sysent[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
40466afa415SBryan Drewery sysent[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
40566afa415SBryan Drewery sysent[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
40666afa415SBryan Drewery sysent[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
40766afa415SBryan Drewery sysent[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
40866afa415SBryan Drewery sysent[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
40966afa415SBryan Drewery sysent[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
41066afa415SBryan Drewery sysent[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
411eb9aea5aSDavid E. O'Brien
4126c37a3d4SBryan Drewery #if defined(COMPAT_FREEBSD32)
41366afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
41466afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
41566afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
41666afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
41766afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
41866afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
41966afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
42066afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
4216c37a3d4SBryan Drewery #endif /* COMPAT_FREEBSD32 */
42279d69913SBryan Drewery
423f889a61aSBryan Drewery filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec,
424f889a61aSBryan Drewery filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST);
42579d69913SBryan Drewery filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit,
42679d69913SBryan Drewery filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST);
4272f600962SBryan Drewery filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork,
4282f600962SBryan Drewery filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST);
429eb9aea5aSDavid E. O'Brien }
430eb9aea5aSDavid E. O'Brien
431eb9aea5aSDavid E. O'Brien static void
filemon_wrapper_deinstall(void)432eb9aea5aSDavid E. O'Brien filemon_wrapper_deinstall(void)
433eb9aea5aSDavid E. O'Brien {
434eb9aea5aSDavid E. O'Brien
43566afa415SBryan Drewery sysent[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
43666afa415SBryan Drewery sysent[SYS_open].sy_call = (sy_call_t *)sys_open;
43766afa415SBryan Drewery sysent[SYS_openat].sy_call = (sy_call_t *)sys_openat;
43866afa415SBryan Drewery sysent[SYS_rename].sy_call = (sy_call_t *)sys_rename;
43966afa415SBryan Drewery sysent[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
44066afa415SBryan Drewery sysent[SYS_link].sy_call = (sy_call_t *)sys_link;
44166afa415SBryan Drewery sysent[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
44266afa415SBryan Drewery sysent[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
443eb9aea5aSDavid E. O'Brien
4446c37a3d4SBryan Drewery #if defined(COMPAT_FREEBSD32)
44566afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
44666afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
44766afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
44866afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
44966afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
45066afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
45166afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
45266afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
4536c37a3d4SBryan Drewery #endif /* COMPAT_FREEBSD32 */
45479d69913SBryan Drewery
455f889a61aSBryan Drewery EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag);
45679d69913SBryan Drewery EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag);
4572f600962SBryan Drewery EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag);
458eb9aea5aSDavid E. O'Brien }
459