4 * Copyright (c) 2011-2013, 2015, 2019 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>
49 #include <sys/queue.h>
50 #include <sys/vnode.h>
52 #include <security/mac_veriexec/mac_veriexec.h>
53 #include <security/mac_veriexec/mac_veriexec_internal.h>
55 #include "veriexec_ioctl.h"
58 * We need a mutex while updating lists etc.
60 extern struct mtx ve_mutex;
63 * Handle the ioctl for the device
66 verifiedexecioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
67 int flags, struct thread *td)
71 struct verified_exec_label_params *lparams;
72 struct verified_exec_params *params;
76 * These commands are considered safe requests for anyone who has
77 * permission to access to device node.
80 case VERIEXEC_GETSTATE:
82 int *ip = (int *)data;
85 *ip = mac_veriexec_get_state();
97 * Anything beyond this point is considered dangerous, so we need to
98 * only allow processes that have kmem write privs to do them.
100 * MAC/veriexec will grant kmem write privs to "trusted" processes.
102 error = priv_check(td, PRIV_KMEM_WRITE);
106 lparams = (struct verified_exec_label_params *)data;
107 if (cmd == VERIEXEC_LABEL_LOAD)
108 params = &lparams->params;
110 params = (struct verified_exec_params *)data;
113 case VERIEXEC_ACTIVE:
115 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
116 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE);
119 mtx_unlock(&ve_mutex);
121 case VERIEXEC_DEBUG_ON:
124 int *ip = (int *)data;
126 mac_veriexec_debug++;
129 mac_veriexec_debug = *ip;
130 *ip = mac_veriexec_debug;
133 mtx_unlock(&ve_mutex);
135 case VERIEXEC_DEBUG_OFF:
136 mac_veriexec_debug = 0;
138 case VERIEXEC_ENFORCE:
140 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
141 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE |
142 VERIEXEC_STATE_ENFORCE);
145 mtx_unlock(&ve_mutex);
147 case VERIEXEC_GETVERSION:
149 int *ip = (int *)data;
152 *ip = MAC_VERIEXEC_VERSION;
159 mac_veriexec_set_state(VERIEXEC_STATE_LOCKED);
160 mtx_unlock(&ve_mutex);
163 if (prison0.pr_securelevel > 0)
164 return (EPERM); /* no updates when secure */
167 case VERIEXEC_LABEL_LOAD:
168 case VERIEXEC_SIGNED_LOAD:
170 * If we use a loader that will only use a
171 * digitally signed hash list - which it verifies.
172 * We can load fingerprints provided veriexec is not locked.
174 if (prison0.pr_securelevel > 0 &&
175 !mac_veriexec_in_state(VERIEXEC_STATE_LOADED)) {
177 * If securelevel has been raised and we
178 * do not have any fingerprints loaded,
179 * it would dangerous to do so now.
183 if (mac_veriexec_in_state(VERIEXEC_STATE_LOCKED))
188 int override = (cmd != VERIEXEC_LOAD);
191 * Get the attributes for the file name passed
192 * stash the file's device id and inode number
193 * along with it's fingerprint in a list for
197 * FreeBSD seems to copy the args to kernel space
199 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE,
201 if ((error = vn_open(&nid, &flags, 0, NULL)) != 0)
204 error = VOP_GETATTR(nid.ni_vp, &vattr, td->td_ucred);
206 mac_veriexec_set_fingerprint_status(nid.ni_vp,
207 FINGERPRINT_INVALID);
208 VOP_UNLOCK(nid.ni_vp);
209 (void) vn_close(nid.ni_vp, FREAD, td->td_ucred,
215 * If the file is on a "verified" filesystem
216 * someone may be playing games.
218 if ((nid.ni_vp->v_mount->mnt_flag &
224 * invalidate the node fingerprint status
225 * which will have been set in the vn_open
226 * and would always be FINGERPRINT_NOTFOUND
228 mac_veriexec_set_fingerprint_status(nid.ni_vp,
229 FINGERPRINT_INVALID);
230 VOP_UNLOCK(nid.ni_vp);
231 (void) vn_close(nid.ni_vp, FREAD, td->td_ucred, td);
232 if (params->flags & VERIEXEC_LABEL)
233 labellen = strnlen(lparams->label,
234 sizeof(lparams->label) - 1) + 1;
237 error = mac_veriexec_metadata_add_file(
238 ((params->flags & VERIEXEC_FILE) != 0),
239 vattr.va_fsid, vattr.va_fileid, vattr.va_gen,
241 (params->flags & VERIEXEC_LABEL) ?
242 lparams->label : NULL, labellen,
243 params->flags, params->fp_type, override);
245 mac_veriexec_set_state(VERIEXEC_STATE_LOADED);
246 mtx_unlock(&ve_mutex);
255 struct cdevsw veriexec_cdevsw = {
256 .d_version = D_VERSION,
257 .d_ioctl = verifiedexecioctl,
258 .d_name = "veriexec",
262 veriexec_drvinit(void *unused __unused)
265 make_dev(&veriexec_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "veriexec");
268 SYSINIT(veriexec, SI_SUB_PSEUDO, SI_ORDER_ANY, veriexec_drvinit, NULL);
269 MODULE_DEPEND(veriexec, mac_veriexec, 1, 1, 1);