1 /*
2 * $FreeBSD$
3 *
4 * Copyright (c) 2011-2013, 2015, Juniper Networks, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 *
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
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/buf.h>
33 #include <sys/conf.h>
34 #include <sys/errno.h>
35 #include <sys/fcntl.h>
36 #include <sys/file.h>
37 #include <sys/filedesc.h>
38 #include <sys/ioccom.h>
39 #include <sys/jail.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.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>
47 #include <sys/proc.h>
48 #include <sys/queue.h>
49 #include <sys/vnode.h>
50
51 #include <security/mac_veriexec/mac_veriexec.h>
52 #include <security/mac_veriexec/mac_veriexec_internal.h>
53
54 #include "veriexec_ioctl.h"
55
56 /*
57 * We need a mutex while updating lists etc.
58 */
59 extern struct mtx ve_mutex;
60
61 /*
62 * Handle the ioctl for the device
63 */
64 static int
65 verifiedexecioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
66 int flags, struct thread *td)
67 {
68 struct nameidata nid;
69 struct vattr vattr;
70 struct verified_exec_params *params;
71 int error = 0;
72
73 params = (struct verified_exec_params *)data;
74 switch (cmd) {
75 case VERIEXEC_ACTIVE:
76 mtx_lock(&ve_mutex);
77 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
78 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE);
79 else
80 error = EINVAL;
81 mtx_unlock(&ve_mutex);
82 break;
83 case VERIEXEC_DEBUG_ON:
84 mtx_lock(&ve_mutex);
85 {
86 int *ip = (int *)data;
87
88 mac_veriexec_debug++;
89 if (ip) {
90 if (*ip > 0)
91 mac_veriexec_debug = *ip;
92 *ip = mac_veriexec_debug;
93 }
94 }
95 mtx_unlock(&ve_mutex);
96 break;
97 case VERIEXEC_DEBUG_OFF:
98 mac_veriexec_debug = 0;
99 break;
100 case VERIEXEC_ENFORCE:
101 mtx_lock(&ve_mutex);
102 if (mac_veriexec_in_state(VERIEXEC_STATE_LOADED))
103 mac_veriexec_set_state(VERIEXEC_STATE_ACTIVE |
104 VERIEXEC_STATE_ENFORCE);
105 else
106 error = EINVAL;
107 mtx_unlock(&ve_mutex);
108 break;
109 case VERIEXEC_GETSTATE:
110 {
111 int *ip = (int *)data;
112
113 if (ip)
114 *ip = mac_veriexec_get_state();
115 else
116 error = EINVAL;
117 }
118 break;
119 case VERIEXEC_LOCK:
120 mtx_lock(&ve_mutex);
121 mac_veriexec_set_state(VERIEXEC_STATE_LOCKED);
122 mtx_unlock(&ve_mutex);
123 break;
124 case VERIEXEC_LOAD:
125 if (prison0.pr_securelevel > 0)
126 return (EPERM); /* no updates when secure */
127
128 /* FALLTHROUGH */
129 case VERIEXEC_SIGNED_LOAD:
130 /*
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.
134 */
135 if (prison0.pr_securelevel > 0 &&
136 !mac_veriexec_in_state(VERIEXEC_STATE_LOADED)) {
137 /*
138 * If securelevel has been raised and we
139 * do not have any fingerprints loaded,
140 * it would dangerous to do so now.
141 */
142 return (EPERM);
143 }
144 if (mac_veriexec_in_state(VERIEXEC_STATE_LOCKED))
145 error = EPERM;
146 else {
147 int flags = FREAD;
148 int override = (cmd == VERIEXEC_SIGNED_LOAD);
149
150 /*
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
154 * exec to use later.
155 */
156 /*
157 * FreeBSD seems to copy the args to kernel space
158 */
159 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE,
160 params->file, td);
161 if ((error = vn_open(&nid, &flags, 0, NULL)) != 0)
162 return (error);
163
164 error = VOP_GETATTR(nid.ni_vp, &vattr, td->td_ucred);
165 if (error != 0) {
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,
170 td);
171 return (error);
172 }
173 if (override) {
174 /*
175 * If the file is on a "verified" filesystem
176 * someone may be playing games.
177 */
178 if ((nid.ni_vp->v_mount->mnt_flag &
179 MNT_VERIFIED) != 0)
180 override = 0;
181 }
182
183 /*
184 * invalidate the node fingerprint status
185 * which will have been set in the vn_open
186 * and would always be FINGERPRINT_NOTFOUND
187 */
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);
192
193 mtx_lock(&ve_mutex);
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);
199
200 mac_veriexec_set_state(VERIEXEC_STATE_LOADED);
201 mtx_unlock(&ve_mutex);
202 }
203 break;
204 default:
205 error = ENODEV;
206 }
207 return (error);
208 }
209
210 struct cdevsw veriexec_cdevsw = {
211 .d_version = D_VERSION,
212 .d_ioctl = verifiedexecioctl,
213 .d_name = "veriexec",
214 };
215
216 static void
217 veriexec_drvinit(void *unused __unused)
218 {
219
220 make_dev(&veriexec_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "veriexec");
221 }
222
223 SYSINIT(veriexec, SI_SUB_PSEUDO, SI_ORDER_ANY, veriexec_drvinit, NULL);
224 MODULE_DEPEND(veriexec, mac_veriexec, 1, 1, 1);
Cache object: b28e81fe0bbd285bcdc2a8daf280139f
|