No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / verified_exec.c
blob72987e99d9b3e00f2f7ecabff5e02450a9e955a3
1 /* $NetBSD: verified_exec.c,v 1.65 2009/05/12 14:16:35 cegger Exp $ */
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.
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.
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.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: verified_exec.c,v 1.65 2009/05/12 14:16:35 cegger Exp $");
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>
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
55 #include <prop/proplib.h>
57 void veriexecattach(device_t, device_t, void *);
58 static dev_type_open(veriexecopen);
59 static dev_type_close(veriexecclose);
60 static dev_type_ioctl(veriexecioctl);
62 struct veriexec_softc {
63 DEVPORT_DEVICE veriexec_dev;
66 #if defined(__FreeBSD__)
67 # define CDEV_MAJOR 216
68 # define BDEV_MAJOR -1
69 #endif
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
97 /* count of number of times device is open (we really only allow one open) */
98 static unsigned int veriexec_dev_usage = 0;
100 void
101 veriexecattach(DEVPORT_DEVICE *parent, DEVPORT_DEVICE *self, void *aux)
103 veriexec_dev_usage = 0;
106 static int
107 veriexecopen(dev_t dev, int flags, int fmt, struct lwp *l)
109 if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL))
110 return (EPERM);
112 if (veriexec_dev_usage > 0)
113 return(EBUSY);
115 veriexec_dev_usage++;
116 return (0);
119 static int
120 veriexecclose(dev_t dev, int flags, int fmt, struct lwp *l)
122 if (veriexec_dev_usage > 0)
123 veriexec_dev_usage--;
124 return (0);
127 static int
128 veriexec_delete(prop_dictionary_t dict, struct lwp *l)
130 struct vnode *vp;
131 const char *file;
132 int error;
134 if (!prop_dictionary_get_cstring_nocopy(dict, "file", &file))
135 return (EINVAL);
137 error = namei_simple_kernel(file, NSM_FOLLOW_NOEMULROOT, &vp);
138 if (error)
139 return (error);
141 /* XXX this should be done differently... */
142 if (vp->v_type == VREG)
143 error = veriexec_file_delete(l, vp);
144 else if (vp->v_type == VDIR)
145 error = veriexec_table_delete(l, vp->v_mount);
147 vrele(vp);
149 return (error);
152 static int
153 veriexec_query(prop_dictionary_t dict, prop_dictionary_t rdict, struct lwp *l)
155 struct vnode *vp;
156 const char *file;
157 int error;
159 if (!prop_dictionary_get_cstring_nocopy(dict, "file", &file))
160 return (EINVAL);
162 error = namei_simple_kernel(file, NSM_FOLLOW_NOEMULROOT, &vp);
163 if (error)
164 return (error);
166 error = veriexec_convert(vp, rdict);
168 vrele(vp);
170 return (error);
174 veriexecioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
176 extern int veriexec_strict;
177 struct plistref *plistref;
178 prop_dictionary_t dict;
179 int error = 0;
181 /* XXX This should be replaced with a kauth(9) request. */
182 switch (cmd) {
183 case VERIEXEC_TABLESIZE:
184 case VERIEXEC_LOAD:
185 case VERIEXEC_DELETE:
186 case VERIEXEC_FLUSH:
187 if (!(flags & FWRITE))
188 return (EPERM);
190 if (veriexec_strict > VERIEXEC_LEARNING) {
191 log(LOG_WARNING, "Veriexec: Strict mode, modifying "
192 "tables not permitted.\n");
194 return (EPERM);
197 break;
199 case VERIEXEC_QUERY:
200 case VERIEXEC_DUMP:
201 if (!(flags & FREAD))
202 return (EPERM);
204 break;
206 default:
207 /* Invalid operation. */
208 return (ENODEV);
211 plistref = (struct plistref *)data;
213 switch (cmd) {
214 case VERIEXEC_TABLESIZE:
215 /* Do nothing. Kept for binary compatibility. */
216 break;
218 case VERIEXEC_LOAD:
219 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
220 if (error)
221 break;
223 error = veriexec_file_add(l, dict);
224 prop_object_release(dict);
225 break;
227 case VERIEXEC_DELETE:
228 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
229 if (error)
230 break;
232 error = veriexec_delete(dict, l);
233 prop_object_release(dict);
234 break;
236 case VERIEXEC_QUERY: {
237 prop_dictionary_t rdict;
239 error = prop_dictionary_copyin_ioctl(plistref, cmd, &dict);
240 if (error)
241 return (error);
243 rdict = prop_dictionary_create();
244 if (rdict == NULL) {
245 prop_object_release(dict);
246 error = ENOMEM;
247 break;
250 error = veriexec_query(dict, rdict, l);
251 if (error == 0) {
252 error = prop_dictionary_copyout_ioctl(plistref, cmd,
253 rdict);
256 prop_object_release(rdict);
257 prop_object_release(dict);
259 break;
262 case VERIEXEC_DUMP: {
263 prop_array_t rarray;
265 rarray = prop_array_create();
266 if (rarray == NULL) {
267 error = ENOMEM;
268 break;
271 error = veriexec_dump(l, rarray);
272 if (error == 0) {
273 error = prop_array_copyout_ioctl(plistref, cmd,
274 rarray);
277 prop_object_release(rarray);
279 break;
282 case VERIEXEC_FLUSH:
283 error = veriexec_flush(l);
284 break;
286 default:
287 /* Invalid operation. */
288 error = ENODEV;
289 break;
292 return (error);
295 #if defined(__FreeBSD__)
296 static void
297 veriexec_drvinit(void *unused)
299 make_dev(&verifiedexec_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
300 "veriexec");
301 verifiedexecattach(0, 0, 0);
304 SYSINIT(veriexec, SI_SUB_PSEUDO, SI_ORDER_ANY, veriexec_drvinit, NULL);
305 #endif