1 /* $NetBSD: verified_exec.c,v 1.63.22.1 2008/12/18 00:56:27 snj Exp $ */
2
3 /*-
4 * Copyright (c) 2005, 2006 Elad Efrat <elad@NetBSD.org>
5 * Copyright (c) 2005, 2006 Brett Lymn <blymn@NetBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the authors may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.63.22.1 2008/12/18 00:56:27 snj Exp $");
33
34 #include <sys/param.h>
35 #include <sys/errno.h>
36 #include <sys/conf.h>
37 #include <sys/vnode.h>
38 #include <sys/fcntl.h>
39 #include <sys/namei.h>
40 #include <sys/verified_exec.h>
41 #include <sys/kauth.h>
42 #include <sys/syslog.h>
43 #include <sys/proc.h>
44
45 #ifdef __FreeBSD__
46 #include <sys/kernel.h>
47 #include <sys/device_port.h>
48 #include <sys/ioccom.h>
49 #else
50 #include <sys/ioctl.h>
51 #include <sys/device.h>
52 #define DEVPORT_DEVICE struct device
53 #endif
54
55 #include <prop/proplib.h>
56
57 void veriexecattach(struct device *, struct device *, void *);
58 static dev_type_open(veriexecopen);
59 static dev_type_close(veriexecclose);
60 static dev_type_ioctl(veriexecioctl);
61
62 struct veriexec_softc {
63 DEVPORT_DEVICE veriexec_dev;
64 };
65
66 #if defined(__FreeBSD__)
67 # define CDEV_MAJOR 216
68 # define BDEV_MAJOR -1
69 #endif
70
71 const struct cdevsw veriexec_cdevsw = {
72 veriexecopen,
73 veriexecclose,
74 noread,
75 nowrite,
76 veriexecioctl,
77 #ifdef __NetBSD__
78 nostop,
79 notty,
80 #endif
81 nopoll,
82 nommap,
83 #if defined(__NetBSD__)
84 nokqfilter,
85 D_OTHER,
86 #elif defined(__FreeBSD__)
87 nostrategy,
88 "veriexec",
89 CDEV_MAJOR,
90 nodump,
91 nopsize,
92 0, /* flags */
93 BDEV_MAJOR
94 #endif
95 };
96
97 /* count of number of times device is open (we really only allow one open) */
98 static unsigned int veriexec_dev_usage = 0;
99
100 void
101 veriexecattach(DEVPORT_DEVICE *parent, DEVPORT_DEVICE *self, void *aux)
102 {
103 veriexec_dev_usage = 0;
104 }
105
106 static int
107 veriexecopen(dev_t dev, int flags, int fmt, struct lwp *l)
108 {
109 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL))
110 return (EPERM);
111
112 if (veriexec_dev_usage > 0)
113 return(EBUSY);
114
115 veriexec_dev_usage++;
116 return (0);
117 }
118
119 static int
120 veriexecclose(dev_t dev, int flags, int fmt, struct lwp *l)
121 {
122 if (veriexec_dev_usage > 0)
123 veriexec_dev_usage--;
124 return (0);
125 }
126
127 static int
128 veriexec_delete(prop_dictionary_t dict, struct lwp *l)
129 {
130 struct nameidata nid;
131 const char *file;
132 int error;
133
134 if (!prop_dictionary_get_cstring_nocopy(dict, "file", &file))
135 return (EINVAL);
136
137 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, file);
138 error = namei(&nid);
139 if (error)
140 return (error);
141
142 /* XXX this should be done differently... */
143 if (nid.ni_vp->v_type == VREG)
144 error = veriexec_file_delete(l, nid.ni_vp);
145 else if (nid.ni_vp->v_type == VDIR)
146 error = veriexec_table_delete(l, nid.ni_vp->v_mount);
147
148 vrele(nid.ni_vp);
149
150 return (error);
151 }
152
153 static int
154 veriexec_query(prop_dictionary_t dict, prop_dictionary_t rdict, struct lwp *l)
155 {
156 struct nameidata nid;
157 const char *file;
158 int error;
159
160 if (!prop_dictionary_get_cstring_nocopy(dict, "file", &file))
161 return (EINVAL);
162
163 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, file);
164 error = namei(&nid);
165 if (error)
166 return (error);
167
168 error = veriexec_convert(nid.ni_vp, rdict);
169
170 vrele(nid.ni_vp);
171
172 return (error);
173 }
174
175 int
176 veriexecioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
177 {
178 extern int veriexec_strict;
179 struct plistref *plistref;
180 prop_dictionary_t dict;
181 int error = 0;
182
183 /* XXX This should be replaced with a kauth(9) request. */
184 switch (cmd) {
185 case VERIEXEC_TABLESIZE:
186 case VERIEXEC_LOAD:
187 case VERIEXEC_DELETE:
188 case VERIEXEC_FLUSH:
189 if (!(flags & FWRITE))
190 return (EPERM);
191
192 if (veriexec_strict > VERIEXEC_LEARNING) {
193 log(LOG_WARNING, "Veriexec: Strict mode, modifying "
194 "tables not permitted.\n");
195
196 return (EPERM);
197 }
198
199 break;
200
201 case VERIEXEC_QUERY:
202 case VERIEXEC_DUMP:
203 if (!(flags & FREAD))
204 return (EPERM);
205
206 break;
207
208 default:
209 /* Invalid operation. */
210 return (ENODEV);
211 }
212
213 plistref = (struct plistref *)data;
214
215 switch (cmd) {
216 case VERIEXEC_TABLESIZE:
217 /* Do nothing. Kept for binary compatibility. */
218 break;
219
220 case VERIEXEC_LOAD:
221 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
222 if (error)
223 break;
224
225 error = veriexec_file_add(l, dict);
226 prop_object_release(dict);
227 break;
228
229 case VERIEXEC_DELETE:
230 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
231 if (error)
232 break;
233
234 error = veriexec_delete(dict, l);
235 prop_object_release(dict);
236 break;
237
238 case VERIEXEC_QUERY: {
239 prop_dictionary_t rdict;
240
241 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
242 if (error)
243 return (error);
244
245 rdict = prop_dictionary_create();
246 if (rdict == NULL) {
247 prop_object_release(dict);
248 error = ENOMEM;
249 break;
250 }
251
252 error = veriexec_query(dict, rdict, l);
253 if (error == 0) {
254 error = prop_dictionary_copyout_ioctl(plistref, cmd,
255 rdict);
256 }
257
258 prop_object_release(rdict);
259 prop_object_release(dict);
260
261 break;
262 }
263
264 case VERIEXEC_DUMP: {
265 prop_array_t rarray;
266
267 rarray = prop_array_create();
268 if (rarray == NULL) {
269 error = ENOMEM;
270 break;
271 }
272
273 error = veriexec_dump(l, rarray);
274 if (error == 0) {
275 error = prop_array_copyout_ioctl(plistref, cmd,
276 rarray);
277 }
278
279 prop_object_release(rarray);
280
281 break;
282 }
283
284 case VERIEXEC_FLUSH:
285 error = veriexec_flush(l);
286 break;
287
288 default:
289 /* Invalid operation. */
290 error = ENODEV;
291 break;
292 }
293
294 return (error);
295 }
296
297 #if defined(__FreeBSD__)
298 static void
299 veriexec_drvinit(void *unused)
300 {
301 make_dev(&verifiedexec_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
302 "veriexec");
303 verifiedexecattach(0, 0, 0);
304 }
305
306 SYSINIT(veriexec, SI_SUB_PSEUDO, SI_ORDER_ANY, veriexec_drvinit, NULL);
307 #endif
Cache object: c375dd4cbf90a64ebda6935ef170f3f7
|