4 * Copyright (c) 2011-2013, 2015, Juniper Networks, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
34 #include <sys/errno.h>
35 #include <sys/fcntl.h>
37 #include <sys/filedesc.h>
38 #include <sys/ioccom.h>
40 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mdioctl.h>
44 #include <sys/mount.h>
45 #include <sys/mutex.h>
46 #include <sys/namei.h>
48 #include <sys/queue.h>
49 #include <sys/vnode.h>
51 #include <security/mac_veriexec/mac_veriexec.h>
52 #include <security/mac_veriexec/mac_veriexec_internal.h>
54 #include "veriexec_ioctl.h"
57 * We need a mutex while updating lists etc.
59 extern struct mtx ve_mutex;
62 * Handle the ioctl for the device
65 verifiedexecioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
66 int flags, struct thread *td)
70 struct verified_exec_params *params;
73 params = (struct verified_exec_params *)data;
77 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
78 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE);
81 mtx_unlock(&ve_mutex);
83 case VERIEXEC_DEBUG_ON:
86 int *ip = (int *)data;
91 mac_veriexec_debug = *ip;
92 *ip = mac_veriexec_debug;
95 mtx_unlock(&ve_mutex);
97 case VERIEXEC_DEBUG_OFF:
98 mac_veriexec_debug = 0;
100 case VERIEXEC_ENFORCE:
102 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
103 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE |
104 VERIEXEC_STATE_ENFORCE);
107 mtx_unlock(&ve_mutex);
109 case VERIEXEC_GETSTATE:
111 int *ip = (int *)data;
114 *ip = mac_veriexec_get_state();
121 mac_veriexec_set_state(VERIEXEC_STATE_LOCKED);
122 mtx_unlock(&ve_mutex);
125 if (prison0.pr_securelevel > 0)
126 return (EPERM); /* no updates when secure */
129 case VERIEXEC_SIGNED_LOAD:
131 * If we use a loader that will only use a
132 * digitally signed hash list - which it verifies.
133 * We can load fingerprints provided veriexec is not locked.
135 if (prison0.pr_securelevel > 0 &&
136 !mac_veriexec_in_state(VERIEXEC_STATE_LOADED)) {
138 * If securelevel has been raised and we
139 * do not have any fingerprints loaded,
140 * it would dangerous to do so now.
144 if (mac_veriexec_in_state(VERIEXEC_STATE_LOCKED))
148 int override = (cmd == VERIEXEC_SIGNED_LOAD);
151 * Get the attributes for the file name passed
152 * stash the file's device id and inode number
153 * along with it's fingerprint in a list for
157 * FreeBSD seems to copy the args to kernel space
159 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE,
161 if ((error = vn_open(&nid, &flags, 0, NULL)) != 0)
164 error = VOP_GETATTR(nid.ni_vp, &vattr, td->td_ucred);
166 mac_veriexec_set_fingerprint_status(nid.ni_vp,
167 FINGERPRINT_INVALID);
168 VOP_UNLOCK(nid.ni_vp, 0);
169 (void) vn_close(nid.ni_vp, FREAD, td->td_ucred,
175 * If the file is on a "verified" filesystem
176 * someone may be playing games.
178 if ((nid.ni_vp->v_mount->mnt_flag &
184 * invalidate the node fingerprint status
185 * which will have been set in the vn_open
186 * and would always be FINGERPRINT_NOTFOUND
188 mac_veriexec_set_fingerprint_status(nid.ni_vp,
189 FINGERPRINT_INVALID);
190 VOP_UNLOCK(nid.ni_vp, 0);
191 (void) vn_close(nid.ni_vp, FREAD, td->td_ucred, td);
194 error = mac_veriexec_metadata_add_file(
195 ((params->flags & VERIEXEC_FILE) != 0),
196 vattr.va_fsid, vattr.va_fileid, vattr.va_gen,
197 params->fingerprint, params->flags,
198 params->fp_type, override);
200 mac_veriexec_set_state(VERIEXEC_STATE_LOADED);
201 mtx_unlock(&ve_mutex);
210 struct cdevsw veriexec_cdevsw = {
211 .d_version = D_VERSION,
212 .d_ioctl = verifiedexecioctl,
213 .d_name = "veriexec",
217 veriexec_drvinit(void *unused __unused)
220 make_dev(&veriexec_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "veriexec");
223 SYSINIT(veriexec, SI_SUB_PSEUDO, SI_ORDER_ANY, veriexec_drvinit, NULL);
224 MODULE_DEPEND(veriexec, mac_veriexec, 1, 1, 1);