Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/filemon Be a bit more paranoid about hijacking (and ...



details:   https://anonhg.NetBSD.org/src/rev/797a4fa36ad7
branches:  trunk
changeset: 811978:797a4fa36ad7
user:      pgoyette <pgoyette%NetBSD.org@localhost>
date:      Wed Nov 25 07:34:49 2015 +0000

description:
Be a bit more paranoid about hijacking (and restoring) syscall function
pointers.  Ensure that we have the correct "old" values before setting
new values, for both "intall" and "deinstall".

XXX This is NOT intended to encourage additional cases of hijacking!  If
XXX some other hijack feature ever gets committed, this code should be
XXX moved to (most likely) kern/kern_syscall.c.

diffstat:

 sys/dev/filemon/filemon.c         |   15 ++--
 sys/dev/filemon/filemon.h         |   10 ++-
 sys/dev/filemon/filemon_wrapper.c |  121 +++++++++++++++++++++++++++++--------
 3 files changed, 109 insertions(+), 37 deletions(-)

diffs (239 lines):

diff -r 8c5d4684d660 -r 797a4fa36ad7 sys/dev/filemon/filemon.c
--- a/sys/dev/filemon/filemon.c Wed Nov 25 07:06:19 2015 +0000
+++ b/sys/dev/filemon/filemon.c Wed Nov 25 07:34:49 2015 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: filemon.c,v 1.21 2015/11/24 01:05:50 pgoyette Exp $ */
+/*      $NetBSD: filemon.c,v 1.22 2015/11/25 07:34:49 pgoyette Exp $ */
 /*
  * Copyright (c) 2010, Juniper Networks, Inc.
  *
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.21 2015/11/24 01:05:50 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filemon.c,v 1.22 2015/11/25 07:34:49 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -340,13 +340,13 @@
        return (error);
 }
 
-static void
+static int
 filemon_load(void *dummy __unused)
 {
        rw_init(&filemon_mtx);
 
        /* Install the syscall wrappers. */
-       filemon_wrapper_install();
+       return filemon_wrapper_install();
 }
 
 /*
@@ -400,9 +400,10 @@
                logLevel = LOG_INFO;
 #endif
 
-               filemon_load(data);
-               error = devsw_attach("filemon", NULL, &bmajor,
-                   &filemon_cdevsw, &cmajor);
+               error = filemon_load(data);
+               if (!error)
+                       error = devsw_attach("filemon", NULL, &bmajor,
+                           &filemon_cdevsw, &cmajor);
                break;
 
        case MODULE_CMD_FINI:
diff -r 8c5d4684d660 -r 797a4fa36ad7 sys/dev/filemon/filemon.h
--- a/sys/dev/filemon/filemon.h Wed Nov 25 07:06:19 2015 +0000
+++ b/sys/dev/filemon/filemon.h Wed Nov 25 07:34:49 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: filemon.h,v 1.7 2015/09/06 06:01:00 dholland Exp $ */
+/* $NetBSD: filemon.h,v 1.8 2015/11/25 07:34:49 pgoyette Exp $ */
 /*
  * Copyright (c) 2010, Juniper Networks, Inc.
  *
@@ -47,9 +47,15 @@
        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);
-void filemon_wrapper_install(void);
+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
diff -r 8c5d4684d660 -r 797a4fa36ad7 sys/dev/filemon/filemon_wrapper.c
--- a/sys/dev/filemon/filemon_wrapper.c Wed Nov 25 07:06:19 2015 +0000
+++ b/sys/dev/filemon/filemon_wrapper.c Wed Nov 25 07:34:49 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: filemon_wrapper.c,v 1.10 2015/11/23 00:47:43 pgoyette Exp $    */
+/*     $NetBSD: filemon_wrapper.c,v 1.11 2015/11/25 07:34:49 pgoyette Exp $    */
 
 /*
  * Copyright (c) 2010, Juniper Networks, Inc.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.10 2015/11/23 00:47:43 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filemon_wrapper.c,v 1.11 2015/11/25 07:34:49 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -39,6 +39,83 @@
 
 #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 void 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)
@@ -322,6 +399,7 @@
                rw_exit(&filemon->fm_mtx);
        }
        sys_exit(l, uap, retval);
+       /* NOT REACHED */
 }
 
 static int
@@ -352,41 +430,28 @@
 }
 
 
-void
+int
 filemon_wrapper_install(void)
 {
+       int error;
        struct sysent *sv_table = emul_netbsd.e_sysent;
 
-       sv_table[SYS_chdir].sy_call = (sy_call_t *) filemon_wrapper_chdir;
-       sv_table[SYS_execve].sy_call = (sy_call_t *) filemon_wrapper_execve;
-       sv_table[SYS_exit].sy_call = (sy_call_t *) filemon_wrapper_sys_exit;
-       sv_table[SYS_fork].sy_call = (sy_call_t *) filemon_wrapper_fork;
-       sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
-       sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
-       sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
-       sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
-       sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
-       sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
-       sv_table[SYS_vfork].sy_call = (sy_call_t *) filemon_wrapper_vfork;
+       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;
 
-       if (sv_table[SYS_chdir].sy_call != (sy_call_t *) filemon_wrapper_chdir)
-           return EBUSY;
-       sv_table[SYS_chdir].sy_call = (sy_call_t *) sys_chdir;
-       sv_table[SYS_execve].sy_call = (sy_call_t *) sys_execve;
-       sv_table[SYS_exit].sy_call = (sy_call_t *) sys_exit;
-       sv_table[SYS_fork].sy_call = (sy_call_t *) sys_fork;
-       sv_table[SYS_link].sy_call = (sy_call_t *) sys_link;
-       sv_table[SYS_open].sy_call = (sy_call_t *) sys_open;
-       sv_table[SYS_openat].sy_call = (sy_call_t *) sys_openat;
-       sv_table[SYS_rename].sy_call = (sy_call_t *) sys_rename;
-       sv_table[SYS_symlink].sy_call = (sy_call_t *) sys_symlink;
-       sv_table[SYS_unlink].sy_call = (sy_call_t *) sys_unlink;
-       sv_table[SYS_vfork].sy_call = (sy_call_t *) sys_vfork;
-       return 0;
+       kernconfig_lock();
+       error = syscall_hijack(sv_table, filemon_hijack, true);
+       kernconfig_unlock();
+
+       return error;
 }



Home | Main Index | Thread Index | Old Index