1eb9aea5aSDavid E. O'Brien /*-
24d846d26SWarner 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>
36*e453e498SBrooks Davis #include <sys/stdarg.h>
37c849fda8SSimon J. Gerraty #include <sys/sx.h>
3866afa415SBryan Drewery #include <sys/sysent.h>
39f889a61aSBryan Drewery #include <sys/vnode.h>
40c849fda8SSimon J. Gerraty
41bc0d7285SBryan Drewery static void filemon_output_event(struct filemon *filemon, const char *fmt, ...)
42bc0d7285SBryan Drewery __printflike(2, 3);
43bc0d7285SBryan Drewery
44f889a61aSBryan Drewery static eventhandler_tag filemon_exec_tag;
4579d69913SBryan Drewery static eventhandler_tag filemon_exit_tag;
462f600962SBryan Drewery static eventhandler_tag filemon_fork_tag;
4779d69913SBryan Drewery
48eb9aea5aSDavid E. O'Brien static void
filemon_output(struct filemon * filemon,char * msg,size_t len)49eb9aea5aSDavid E. O'Brien filemon_output(struct filemon *filemon, char *msg, size_t len)
50eb9aea5aSDavid E. O'Brien {
51eb9aea5aSDavid E. O'Brien struct uio auio;
52eb9aea5aSDavid E. O'Brien struct iovec aiov;
534177d9f7SBryan Drewery int error;
54eb9aea5aSDavid E. O'Brien
55eb9aea5aSDavid E. O'Brien if (filemon->fp == NULL)
56eb9aea5aSDavid E. O'Brien return;
57eb9aea5aSDavid E. O'Brien
58eb9aea5aSDavid E. O'Brien aiov.iov_base = msg;
59eb9aea5aSDavid E. O'Brien aiov.iov_len = len;
60eb9aea5aSDavid E. O'Brien auio.uio_iov = &aiov;
61eb9aea5aSDavid E. O'Brien auio.uio_iovcnt = 1;
62eb9aea5aSDavid E. O'Brien auio.uio_resid = len;
63eb9aea5aSDavid E. O'Brien auio.uio_segflg = UIO_SYSSPACE;
64eb9aea5aSDavid E. O'Brien auio.uio_rw = UIO_WRITE;
65eb9aea5aSDavid E. O'Brien auio.uio_td = curthread;
66eb9aea5aSDavid E. O'Brien auio.uio_offset = (off_t) -1;
67eb9aea5aSDavid E. O'Brien
688a81693aSBryan Drewery if (filemon->fp->f_type == DTYPE_VNODE)
69eb9aea5aSDavid E. O'Brien bwillwrite();
70eb9aea5aSDavid E. O'Brien
717ae27ff9SBryan Drewery error = fo_write(filemon->fp, &auio, filemon->cred, 0, curthread);
72b7622235SBryan Drewery if (error != 0 && filemon->error == 0)
734177d9f7SBryan Drewery filemon->error = error;
74eb9aea5aSDavid E. O'Brien }
75eb9aea5aSDavid E. O'Brien
76bc0d7285SBryan Drewery static void
filemon_output_event(struct filemon * filemon,const char * fmt,...)77bc0d7285SBryan Drewery filemon_output_event(struct filemon *filemon, const char *fmt, ...)
78bc0d7285SBryan Drewery {
79bc0d7285SBryan Drewery va_list ap;
80bc0d7285SBryan Drewery size_t len;
81bc0d7285SBryan Drewery
82bc0d7285SBryan Drewery va_start(ap, fmt);
83bc0d7285SBryan Drewery len = vsnprintf(filemon->msgbufr, sizeof(filemon->msgbufr), fmt, ap);
84bc0d7285SBryan Drewery va_end(ap);
85bc0d7285SBryan Drewery /* The event is truncated but still worth logging. */
86bc0d7285SBryan Drewery if (len >= sizeof(filemon->msgbufr))
87bc0d7285SBryan Drewery len = sizeof(filemon->msgbufr) - 1;
88bc0d7285SBryan Drewery filemon_output(filemon, filemon->msgbufr, len);
89bc0d7285SBryan Drewery }
90bc0d7285SBryan Drewery
91eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_chdir(struct thread * td,struct chdir_args * uap)92eb9aea5aSDavid E. O'Brien filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
93eb9aea5aSDavid E. O'Brien {
949b511ce9SBryan Drewery int error, ret;
95eb9aea5aSDavid E. O'Brien struct filemon *filemon;
96eb9aea5aSDavid E. O'Brien
97eb9aea5aSDavid E. O'Brien if ((ret = sys_chdir(td, uap)) == 0) {
98e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
999b511ce9SBryan Drewery if ((error = copyinstr(uap->path, filemon->fname1,
1009b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
1019b511ce9SBryan Drewery filemon->error = error;
1029b511ce9SBryan Drewery goto copyfail;
1039b511ce9SBryan Drewery }
104eb9aea5aSDavid E. O'Brien
105bc0d7285SBryan Drewery filemon_output_event(filemon, "C %d %s\n",
106eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1);
1079b511ce9SBryan Drewery copyfail:
108e0d84b9eSBryan Drewery filemon_drop(filemon);
109eb9aea5aSDavid E. O'Brien }
110eb9aea5aSDavid E. O'Brien }
111eb9aea5aSDavid E. O'Brien
112eb9aea5aSDavid E. O'Brien return (ret);
113eb9aea5aSDavid E. O'Brien }
114eb9aea5aSDavid E. O'Brien
115f889a61aSBryan Drewery static void
filemon_event_process_exec(void * arg __unused,struct proc * p,struct image_params * imgp)116f889a61aSBryan Drewery filemon_event_process_exec(void *arg __unused, struct proc *p,
117f889a61aSBryan Drewery struct image_params *imgp)
118eb9aea5aSDavid E. O'Brien {
119eb9aea5aSDavid E. O'Brien struct filemon *filemon;
120eb9aea5aSDavid E. O'Brien
121e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p)) != NULL) {
122bc0d7285SBryan Drewery filemon_output_event(filemon, "E %d %s\n",
12323ae5cd7SBryan Drewery p->p_pid,
12423ae5cd7SBryan Drewery imgp->execpath != NULL ? imgp->execpath : "<unknown>");
125eb9aea5aSDavid E. O'Brien
126f14fbe72SBryan Drewery /* If the credentials changed then cease tracing. */
127f14fbe72SBryan Drewery if (imgp->newcred != NULL &&
128f14fbe72SBryan Drewery imgp->credential_setid &&
129cc426dd3SMateusz Guzik priv_check_cred(filemon->cred, PRIV_DEBUG_DIFFCRED) != 0) {
130f14fbe72SBryan Drewery /*
131f14fbe72SBryan Drewery * It may have changed to NULL already, but
132f14fbe72SBryan Drewery * will not be re-attached by anything else.
133f14fbe72SBryan Drewery */
134f14fbe72SBryan Drewery if (p->p_filemon != NULL) {
135f14fbe72SBryan Drewery KASSERT(p->p_filemon == filemon,
136f14fbe72SBryan Drewery ("%s: proc %p didn't have expected"
137f14fbe72SBryan Drewery " filemon %p", __func__, p, filemon));
138f14fbe72SBryan Drewery filemon_proc_drop(p);
139f14fbe72SBryan Drewery }
140f14fbe72SBryan Drewery }
141f14fbe72SBryan Drewery
142f14fbe72SBryan Drewery
143e0d84b9eSBryan Drewery filemon_drop(filemon);
144eb9aea5aSDavid E. O'Brien }
145eb9aea5aSDavid E. O'Brien }
146eb9aea5aSDavid E. O'Brien
1474d3cfa1dSBryan Drewery static void
_filemon_wrapper_openat(struct thread * td,const char * upath,int flags,int fd)14812e69f96SBrooks Davis _filemon_wrapper_openat(struct thread *td, const char *upath, int flags,
14912e69f96SBrooks Davis int fd)
150eb9aea5aSDavid E. O'Brien {
1519b511ce9SBryan Drewery int error;
1528536d1b7SBryan Drewery struct file *fp;
153eb9aea5aSDavid E. O'Brien struct filemon *filemon;
1548536d1b7SBryan Drewery char *atpath, *freepath;
1558536d1b7SBryan Drewery cap_rights_t rights;
156eb9aea5aSDavid E. O'Brien
157e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
1588536d1b7SBryan Drewery atpath = "";
1598536d1b7SBryan Drewery freepath = NULL;
1608536d1b7SBryan Drewery fp = NULL;
1618536d1b7SBryan Drewery
1629b511ce9SBryan Drewery if ((error = copyinstr(upath, filemon->fname1,
1639b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
1649b511ce9SBryan Drewery filemon->error = error;
1659b511ce9SBryan Drewery goto copyfail;
1669b511ce9SBryan Drewery }
167f859e956SSimon J. Gerraty
1684d3cfa1dSBryan Drewery if (filemon->fname1[0] != '/' && fd != AT_FDCWD) {
169f859e956SSimon J. Gerraty /*
170f859e956SSimon J. Gerraty * rats - we cannot do too much about this.
171f859e956SSimon J. Gerraty * the trace should show a dir we read
172f859e956SSimon J. Gerraty * recently.. output an A record as a clue
173f859e956SSimon J. Gerraty * until we can do better.
1748536d1b7SBryan Drewery * XXX: This may be able to come out with
1758536d1b7SBryan Drewery * the namecache lookup now.
176f859e956SSimon J. Gerraty */
177bc0d7285SBryan Drewery filemon_output_event(filemon, "A %d %s\n",
178f859e956SSimon J. Gerraty curproc->p_pid, filemon->fname1);
1798536d1b7SBryan Drewery /*
1808536d1b7SBryan Drewery * Try to resolve the path from the vnode using the
1818536d1b7SBryan Drewery * namecache. It may be inaccurate, but better
1828536d1b7SBryan Drewery * than nothing.
1838536d1b7SBryan Drewery */
1848536d1b7SBryan Drewery if (getvnode(td, fd,
1856b3a9a0fSMateusz Guzik cap_rights_init_one(&rights, CAP_LOOKUP), &fp) == 0) {
186feabaaf9SMateusz Guzik vn_fullpath(fp->f_vnode, &atpath, &freepath);
1878536d1b7SBryan Drewery }
188f859e956SSimon J. Gerraty }
1894d3cfa1dSBryan Drewery if (flags & O_RDWR) {
190f859e956SSimon J. Gerraty /*
191f859e956SSimon J. Gerraty * We'll get the W record below, but need
1924d3cfa1dSBryan Drewery * to also output an R to distinguish from
193f859e956SSimon J. Gerraty * O_WRONLY.
194f859e956SSimon J. Gerraty */
195bc0d7285SBryan Drewery filemon_output_event(filemon, "R %d %s%s%s\n",
1968536d1b7SBryan Drewery curproc->p_pid, atpath,
1978536d1b7SBryan Drewery atpath[0] != '\0' ? "/" : "", filemon->fname1);
198f859e956SSimon J. Gerraty }
199f859e956SSimon J. Gerraty
200bc0d7285SBryan Drewery filemon_output_event(filemon, "%c %d %s%s%s\n",
2014d3cfa1dSBryan Drewery (flags & O_ACCMODE) ? 'W':'R',
2028536d1b7SBryan Drewery curproc->p_pid, atpath,
2038536d1b7SBryan Drewery atpath[0] != '\0' ? "/" : "", filemon->fname1);
2049b511ce9SBryan Drewery copyfail:
205e0d84b9eSBryan Drewery filemon_drop(filemon);
2068536d1b7SBryan Drewery if (fp != NULL)
2078536d1b7SBryan Drewery fdrop(fp, td);
2088536d1b7SBryan Drewery free(freepath, M_TEMP);
209f859e956SSimon J. Gerraty }
210f859e956SSimon J. Gerraty }
211f859e956SSimon J. Gerraty
2124d3cfa1dSBryan Drewery static int
filemon_wrapper_open(struct thread * td,struct open_args * uap)2134d3cfa1dSBryan Drewery filemon_wrapper_open(struct thread *td, struct open_args *uap)
2144d3cfa1dSBryan Drewery {
2154d3cfa1dSBryan Drewery int ret;
2164d3cfa1dSBryan Drewery
2174d3cfa1dSBryan Drewery if ((ret = sys_open(td, uap)) == 0)
2184d3cfa1dSBryan Drewery _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD);
2194d3cfa1dSBryan Drewery
2204d3cfa1dSBryan Drewery return (ret);
2214d3cfa1dSBryan Drewery }
2224d3cfa1dSBryan Drewery
2234d3cfa1dSBryan Drewery static int
filemon_wrapper_openat(struct thread * td,struct openat_args * uap)2244d3cfa1dSBryan Drewery filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
2254d3cfa1dSBryan Drewery {
2264d3cfa1dSBryan Drewery int ret;
2274d3cfa1dSBryan Drewery
2284d3cfa1dSBryan Drewery if ((ret = sys_openat(td, uap)) == 0)
2294d3cfa1dSBryan Drewery _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd);
2304d3cfa1dSBryan Drewery
231f859e956SSimon J. Gerraty return (ret);
232f859e956SSimon J. Gerraty }
233f859e956SSimon J. Gerraty
234f859e956SSimon J. Gerraty static int
filemon_wrapper_rename(struct thread * td,struct rename_args * uap)235eb9aea5aSDavid E. O'Brien filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
236eb9aea5aSDavid E. O'Brien {
2379b511ce9SBryan Drewery int error, ret;
238eb9aea5aSDavid E. O'Brien struct filemon *filemon;
239eb9aea5aSDavid E. O'Brien
240eb9aea5aSDavid E. O'Brien if ((ret = sys_rename(td, uap)) == 0) {
241e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
2429b511ce9SBryan Drewery if (((error = copyinstr(uap->from, filemon->fname1,
2439b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) ||
2449b511ce9SBryan Drewery ((error = copyinstr(uap->to, filemon->fname2,
2459b511ce9SBryan Drewery sizeof(filemon->fname2), NULL)) != 0)) {
2469b511ce9SBryan Drewery filemon->error = error;
2479b511ce9SBryan Drewery goto copyfail;
2489b511ce9SBryan Drewery }
249eb9aea5aSDavid E. O'Brien
250bc0d7285SBryan Drewery filemon_output_event(filemon, "M %d '%s' '%s'\n",
251eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1, filemon->fname2);
2529b511ce9SBryan Drewery copyfail:
253e0d84b9eSBryan Drewery filemon_drop(filemon);
254eb9aea5aSDavid E. O'Brien }
255eb9aea5aSDavid E. O'Brien }
256eb9aea5aSDavid E. O'Brien
257eb9aea5aSDavid E. O'Brien return (ret);
258eb9aea5aSDavid E. O'Brien }
259eb9aea5aSDavid E. O'Brien
260d77f7e8cSBryan Drewery static void
_filemon_wrapper_link(struct thread * td,const char * upath1,const char * upath2)26112e69f96SBrooks Davis _filemon_wrapper_link(struct thread *td, const char *upath1,
26212e69f96SBrooks Davis const char *upath2)
263eb9aea5aSDavid E. O'Brien {
264eb9aea5aSDavid E. O'Brien struct filemon *filemon;
2659b511ce9SBryan Drewery int error;
266eb9aea5aSDavid E. O'Brien
267e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
2689b511ce9SBryan Drewery if (((error = copyinstr(upath1, filemon->fname1,
2699b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) ||
2709b511ce9SBryan Drewery ((error = copyinstr(upath2, filemon->fname2,
2719b511ce9SBryan Drewery sizeof(filemon->fname2), NULL)) != 0)) {
2729b511ce9SBryan Drewery filemon->error = error;
2739b511ce9SBryan Drewery goto copyfail;
2749b511ce9SBryan Drewery }
275eb9aea5aSDavid E. O'Brien
276bc0d7285SBryan Drewery filemon_output_event(filemon, "L %d '%s' '%s'\n",
277eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1, filemon->fname2);
2789b511ce9SBryan Drewery copyfail:
279e0d84b9eSBryan Drewery filemon_drop(filemon);
280eb9aea5aSDavid E. O'Brien }
281eb9aea5aSDavid E. O'Brien }
282eb9aea5aSDavid E. O'Brien
283d77f7e8cSBryan Drewery static int
filemon_wrapper_link(struct thread * td,struct link_args * uap)284d77f7e8cSBryan Drewery filemon_wrapper_link(struct thread *td, struct link_args *uap)
285d77f7e8cSBryan Drewery {
286d77f7e8cSBryan Drewery int ret;
287d77f7e8cSBryan Drewery
288d77f7e8cSBryan Drewery if ((ret = sys_link(td, uap)) == 0)
289d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path, uap->link);
290d77f7e8cSBryan Drewery
291eb9aea5aSDavid E. O'Brien return (ret);
292eb9aea5aSDavid E. O'Brien }
293eb9aea5aSDavid E. O'Brien
294eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_symlink(struct thread * td,struct symlink_args * uap)295eb9aea5aSDavid E. O'Brien filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
296eb9aea5aSDavid E. O'Brien {
297eb9aea5aSDavid E. O'Brien int ret;
298eb9aea5aSDavid E. O'Brien
299d77f7e8cSBryan Drewery if ((ret = sys_symlink(td, uap)) == 0)
300d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path, uap->link);
301eb9aea5aSDavid E. O'Brien
302eb9aea5aSDavid E. O'Brien return (ret);
303eb9aea5aSDavid E. O'Brien }
304eb9aea5aSDavid E. O'Brien
305eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_linkat(struct thread * td,struct linkat_args * uap)306eb9aea5aSDavid E. O'Brien filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
307eb9aea5aSDavid E. O'Brien {
308eb9aea5aSDavid E. O'Brien int ret;
309eb9aea5aSDavid E. O'Brien
310d77f7e8cSBryan Drewery if ((ret = sys_linkat(td, uap)) == 0)
311d77f7e8cSBryan Drewery _filemon_wrapper_link(td, uap->path1, uap->path2);
312eb9aea5aSDavid E. O'Brien
313eb9aea5aSDavid E. O'Brien return (ret);
314eb9aea5aSDavid E. O'Brien }
315eb9aea5aSDavid E. O'Brien
316eb9aea5aSDavid E. O'Brien static void
filemon_event_process_exit(void * arg __unused,struct proc * p)31779d69913SBryan Drewery filemon_event_process_exit(void *arg __unused, struct proc *p)
318eb9aea5aSDavid E. O'Brien {
319eb9aea5aSDavid E. O'Brien struct filemon *filemon;
320eb9aea5aSDavid E. O'Brien
321e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p)) != NULL) {
322bc0d7285SBryan Drewery filemon_output_event(filemon, "X %d %d %d\n",
323bc0d7285SBryan Drewery p->p_pid, p->p_xexit, p->p_xsig);
324eb9aea5aSDavid E. O'Brien
325e0d84b9eSBryan Drewery /*
326e0d84b9eSBryan Drewery * filemon_untrack_processes() may have dropped this p_filemon
327e0d84b9eSBryan Drewery * already while in filemon_proc_get() before acquiring the
328e0d84b9eSBryan Drewery * filemon lock.
329e0d84b9eSBryan Drewery */
330e0d84b9eSBryan Drewery KASSERT(p->p_filemon == NULL || p->p_filemon == filemon,
331e0d84b9eSBryan Drewery ("%s: p %p was attached while exiting, expected "
332e0d84b9eSBryan Drewery "filemon %p or NULL", __func__, p, filemon));
333e0d84b9eSBryan Drewery if (p->p_filemon == filemon)
334e0d84b9eSBryan Drewery filemon_proc_drop(p);
335eb9aea5aSDavid E. O'Brien
336e0d84b9eSBryan Drewery filemon_drop(filemon);
337eb9aea5aSDavid E. O'Brien }
338eb9aea5aSDavid E. O'Brien }
339eb9aea5aSDavid E. O'Brien
340eb9aea5aSDavid E. O'Brien static int
filemon_wrapper_unlink(struct thread * td,struct unlink_args * uap)341eb9aea5aSDavid E. O'Brien filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
342eb9aea5aSDavid E. O'Brien {
3439b511ce9SBryan Drewery int error, ret;
344eb9aea5aSDavid E. O'Brien struct filemon *filemon;
345eb9aea5aSDavid E. O'Brien
346eb9aea5aSDavid E. O'Brien if ((ret = sys_unlink(td, uap)) == 0) {
347e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(curproc)) != NULL) {
3489b511ce9SBryan Drewery if ((error = copyinstr(uap->path, filemon->fname1,
3499b511ce9SBryan Drewery sizeof(filemon->fname1), NULL)) != 0) {
3509b511ce9SBryan Drewery filemon->error = error;
3519b511ce9SBryan Drewery goto copyfail;
3529b511ce9SBryan Drewery }
353eb9aea5aSDavid E. O'Brien
354bc0d7285SBryan Drewery filemon_output_event(filemon, "D %d %s\n",
355eb9aea5aSDavid E. O'Brien curproc->p_pid, filemon->fname1);
3569b511ce9SBryan Drewery copyfail:
357e0d84b9eSBryan Drewery filemon_drop(filemon);
358eb9aea5aSDavid E. O'Brien }
359eb9aea5aSDavid E. O'Brien }
360eb9aea5aSDavid E. O'Brien
361eb9aea5aSDavid E. O'Brien return (ret);
362eb9aea5aSDavid E. O'Brien }
363eb9aea5aSDavid E. O'Brien
3642f600962SBryan Drewery static void
filemon_event_process_fork(void * arg __unused,struct proc * p1,struct proc * p2,int flags __unused)3652f600962SBryan Drewery filemon_event_process_fork(void *arg __unused, struct proc *p1,
366e95c55e5SBryan Drewery struct proc *p2, int flags __unused)
367eb9aea5aSDavid E. O'Brien {
368eb9aea5aSDavid E. O'Brien struct filemon *filemon;
369eb9aea5aSDavid E. O'Brien
370e0d84b9eSBryan Drewery if ((filemon = filemon_proc_get(p1)) != NULL) {
371bc0d7285SBryan Drewery filemon_output_event(filemon, "F %d %d\n",
3722f600962SBryan Drewery p1->p_pid, p2->p_pid);
373eb9aea5aSDavid E. O'Brien
374e0d84b9eSBryan Drewery /*
375e0d84b9eSBryan Drewery * filemon_untrack_processes() or
376e0d84b9eSBryan Drewery * filemon_ioctl(FILEMON_SET_PID) may have changed the parent's
377e0d84b9eSBryan Drewery * p_filemon while in filemon_proc_get() before acquiring the
378e0d84b9eSBryan Drewery * filemon lock. Only inherit if the parent is still traced by
379e0d84b9eSBryan Drewery * this filemon.
380e0d84b9eSBryan Drewery */
381e0d84b9eSBryan Drewery if (p1->p_filemon == filemon) {
382e0d84b9eSBryan Drewery PROC_LOCK(p2);
383e0d84b9eSBryan Drewery /*
384e0d84b9eSBryan Drewery * It may have been attached to already by a new
385e0d84b9eSBryan Drewery * filemon.
386e0d84b9eSBryan Drewery */
387e0d84b9eSBryan Drewery if (p2->p_filemon == NULL) {
388e0d84b9eSBryan Drewery p2->p_filemon = filemon_acquire(filemon);
389e0d84b9eSBryan Drewery ++filemon->proccnt;
390e0d84b9eSBryan Drewery }
391e0d84b9eSBryan Drewery PROC_UNLOCK(p2);
392e0d84b9eSBryan Drewery }
393e0d84b9eSBryan Drewery
394e0d84b9eSBryan Drewery filemon_drop(filemon);
395eb9aea5aSDavid E. O'Brien }
396eb9aea5aSDavid E. O'Brien }
397eb9aea5aSDavid E. O'Brien
398eb9aea5aSDavid E. O'Brien static void
filemon_wrapper_install(void)399eb9aea5aSDavid E. O'Brien filemon_wrapper_install(void)
400eb9aea5aSDavid E. O'Brien {
401eb9aea5aSDavid E. O'Brien
40266afa415SBryan Drewery sysent[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
40366afa415SBryan Drewery sysent[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
40466afa415SBryan Drewery sysent[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
40566afa415SBryan Drewery sysent[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
40666afa415SBryan Drewery sysent[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
40766afa415SBryan Drewery sysent[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
40866afa415SBryan Drewery sysent[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
40966afa415SBryan Drewery sysent[SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
410eb9aea5aSDavid E. O'Brien
4116c37a3d4SBryan Drewery #if defined(COMPAT_FREEBSD32)
41266afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
41366afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
41466afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
41566afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
41666afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
41766afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
41866afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
41966afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *) filemon_wrapper_linkat;
4206c37a3d4SBryan Drewery #endif /* COMPAT_FREEBSD32 */
42179d69913SBryan Drewery
422f889a61aSBryan Drewery filemon_exec_tag = EVENTHANDLER_REGISTER(process_exec,
423f889a61aSBryan Drewery filemon_event_process_exec, NULL, EVENTHANDLER_PRI_LAST);
42479d69913SBryan Drewery filemon_exit_tag = EVENTHANDLER_REGISTER(process_exit,
42579d69913SBryan Drewery filemon_event_process_exit, NULL, EVENTHANDLER_PRI_LAST);
4262f600962SBryan Drewery filemon_fork_tag = EVENTHANDLER_REGISTER(process_fork,
4272f600962SBryan Drewery filemon_event_process_fork, NULL, EVENTHANDLER_PRI_LAST);
428eb9aea5aSDavid E. O'Brien }
429eb9aea5aSDavid E. O'Brien
430eb9aea5aSDavid E. O'Brien static void
filemon_wrapper_deinstall(void)431eb9aea5aSDavid E. O'Brien filemon_wrapper_deinstall(void)
432eb9aea5aSDavid E. O'Brien {
433eb9aea5aSDavid E. O'Brien
43466afa415SBryan Drewery sysent[SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
43566afa415SBryan Drewery sysent[SYS_open].sy_call = (sy_call_t *)sys_open;
43666afa415SBryan Drewery sysent[SYS_openat].sy_call = (sy_call_t *)sys_openat;
43766afa415SBryan Drewery sysent[SYS_rename].sy_call = (sy_call_t *)sys_rename;
43866afa415SBryan Drewery sysent[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
43966afa415SBryan Drewery sysent[SYS_link].sy_call = (sy_call_t *)sys_link;
44066afa415SBryan Drewery sysent[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
44166afa415SBryan Drewery sysent[SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
442eb9aea5aSDavid E. O'Brien
4436c37a3d4SBryan Drewery #if defined(COMPAT_FREEBSD32)
44466afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_chdir].sy_call = (sy_call_t *)sys_chdir;
44566afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
44666afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
44766afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
44866afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
44966afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
45066afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
45166afa415SBryan Drewery freebsd32_sysent[FREEBSD32_SYS_linkat].sy_call = (sy_call_t *)sys_linkat;
4526c37a3d4SBryan Drewery #endif /* COMPAT_FREEBSD32 */
45379d69913SBryan Drewery
454f889a61aSBryan Drewery EVENTHANDLER_DEREGISTER(process_exec, filemon_exec_tag);
45579d69913SBryan Drewery EVENTHANDLER_DEREGISTER(process_exit, filemon_exit_tag);
4562f600962SBryan Drewery EVENTHANDLER_DEREGISTER(process_fork, filemon_fork_tag);
457eb9aea5aSDavid E. O'Brien }
458