No empty .Rs/.Re
[netbsd-mini2440.git] / sys / secmodel / keylock / secmodel_keylock.c
bloba5717cbbcc8d450266894d75924941ae5f2f4e4a
1 /* $NetBSD: secmodel_keylock.c,v 1.4 2009/10/06 04:28:10 elad Exp $ */
2 /*-
3 * Copyright (c) 2009 Marc Balmer <marc@msys.ch>
4 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
5 * All rights reserved.
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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * This file contains kauth(9) listeners needed to implement an experimental
32 * keylock based security scheme.
34 * The position of the keylock is a system-global indication on what
35 * operations are allowed or not. It affects all users, including root.
37 * Rules:
39 * - If the number of possible keylock positions is 0, assume there is no
40 * keylock present, do not dissallow any action, i.e. do nothing
42 * - If the number of possible keylock positions is greater than 0, but the
43 * current lock position is 0, assume tampering with the lock and forbid
44 * all actions.
46 * - If the lock is in the lowest position, assume the system is locked and
47 * forbid most actions.
49 * - If the lock is in the highest position, assume the system to be open and
50 * forbid nothing.
52 * - If the security.models.keylock.order sysctl is set to a value != 0,
53 * reverse this order.
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.4 2009/10/06 04:28:10 elad Exp $");
59 #include <sys/types.h>
60 #include <sys/param.h>
61 #include <sys/kauth.h>
63 #include <sys/conf.h>
64 #include <sys/mount.h>
65 #include <sys/sysctl.h>
66 #include <sys/vnode.h>
67 #include <sys/timevar.h>
69 #include <dev/keylock.h>
71 #include <miscfs/specfs/specdev.h>
73 #include <secmodel/keylock/keylock.h>
75 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device;
77 SYSCTL_SETUP(sysctl_security_keylock_setup,
78 "sysctl security keylock setup")
80 const struct sysctlnode *rnode;
82 sysctl_createv(clog, 0, NULL, &rnode,
83 CTLFLAG_PERMANENT,
84 CTLTYPE_NODE, "security", NULL,
85 NULL, 0, NULL, 0,
86 CTL_SECURITY, CTL_EOL);
88 sysctl_createv(clog, 0, &rnode, &rnode,
89 CTLFLAG_PERMANENT,
90 CTLTYPE_NODE, "models", NULL,
91 NULL, 0, NULL, 0,
92 CTL_CREATE, CTL_EOL);
94 sysctl_createv(clog, 0, &rnode, &rnode,
95 CTLFLAG_PERMANENT,
96 CTLTYPE_NODE, "keylock",
97 SYSCTL_DESCR("Keylock security model"),
98 NULL, 0, NULL, 0,
99 CTL_CREATE, CTL_EOL);
101 sysctl_createv(clog, 0, &rnode, NULL,
102 CTLFLAG_PERMANENT,
103 CTLTYPE_STRING, "name", NULL,
104 NULL, 0, __UNCONST("Keylock"), 0,
105 CTL_CREATE, CTL_EOL);
108 void
109 secmodel_keylock_init(void)
113 void
114 secmodel_keylock_start(void)
116 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
117 secmodel_keylock_system_cb, NULL);
118 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
119 secmodel_keylock_process_cb, NULL);
120 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
121 secmodel_keylock_network_cb, NULL);
122 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
123 secmodel_keylock_machdep_cb, NULL);
124 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
125 secmodel_keylock_device_cb, NULL);
128 void
129 secmodel_keylock_stop(void)
131 kauth_unlisten_scope(l_system);
132 kauth_unlisten_scope(l_process);
133 kauth_unlisten_scope(l_network);
134 kauth_unlisten_scope(l_machdep);
135 kauth_unlisten_scope(l_device);
139 * kauth(9) listener
141 * Security model: Multi-position keylock
142 * Scope: System
143 * Responsibility: Keylock
146 secmodel_keylock_system_cb(kauth_cred_t cred,
147 kauth_action_t action, void *cookie, void *arg0, void *arg1,
148 void *arg2, void *arg3)
150 int result;
151 enum kauth_system_req req;
152 int kstate;
154 kstate = keylock_state();
155 if (kstate == KEYLOCK_ABSENT)
156 return KAUTH_RESULT_DEFER;
157 else if (kstate == KEYLOCK_TAMPER)
158 return KAUTH_RESULT_DENY;
160 result = KAUTH_RESULT_DEFER;
161 req = (enum kauth_system_req)arg0;
163 switch (action) {
164 case KAUTH_SYSTEM_CHSYSFLAGS:
165 if (kstate == KEYLOCK_CLOSE)
166 result = KAUTH_RESULT_DENY;
167 break;
169 case KAUTH_SYSTEM_TIME:
170 switch (req) {
171 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
172 if (kstate == KEYLOCK_CLOSE)
173 result = KAUTH_RESULT_DENY;
174 break;
176 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
177 struct timespec *ts = arg1;
178 struct timespec *delta = arg2;
180 if (keylock_position() > 1 && time_wraps(ts, delta))
181 result = KAUTH_RESULT_DENY;
182 break;
184 default:
185 break;
187 break;
189 case KAUTH_SYSTEM_MODULE:
190 if (kstate == KEYLOCK_CLOSE)
191 result = KAUTH_RESULT_DENY;
192 break;
194 case KAUTH_SYSTEM_MOUNT:
195 switch (req) {
196 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
197 if (kstate == KEYLOCK_CLOSE)
198 result = KAUTH_RESULT_DENY;
200 break;
202 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
203 if (kstate == KEYLOCK_CLOSE) {
204 struct mount *mp = arg1;
205 u_long flags = (u_long)arg2;
208 * Can only degrade from read/write to
209 * read-only.
211 if (flags != (mp->mnt_flag | MNT_RDONLY |
212 MNT_RELOAD | MNT_FORCE | MNT_UPDATE))
213 result = KAUTH_RESULT_DENY;
215 break;
216 default:
217 break;
220 break;
222 case KAUTH_SYSTEM_SYSCTL:
223 switch (req) {
224 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
225 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
226 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
227 if (kstate == KEYLOCK_CLOSE)
228 result = KAUTH_RESULT_DENY;
229 break;
230 default:
231 break;
233 break;
235 case KAUTH_SYSTEM_SETIDCORE:
236 if (kstate == KEYLOCK_CLOSE)
237 result = KAUTH_RESULT_DENY;
238 break;
240 case KAUTH_SYSTEM_DEBUG:
241 switch (req) {
242 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
243 if (kstate == KEYLOCK_CLOSE)
244 result = KAUTH_RESULT_DENY;
245 break;
246 default:
247 break;
249 break;
252 return result;
256 * kauth(9) listener
258 * Security model: Multi-position keylock
259 * Scope: Process
260 * Responsibility: Keylock
263 secmodel_keylock_process_cb(kauth_cred_t cred,
264 kauth_action_t action, void *cookie, void *arg0,
265 void *arg1, void *arg2, void *arg3)
267 struct proc *p;
268 int result, kstate;
270 kstate = keylock_state();
271 if (kstate == KEYLOCK_ABSENT)
272 return KAUTH_RESULT_DEFER;
273 else if (kstate == KEYLOCK_TAMPER)
274 return KAUTH_RESULT_DENY;
276 result = KAUTH_RESULT_DEFER;
277 p = arg0;
279 switch (action) {
280 case KAUTH_PROCESS_PROCFS: {
281 enum kauth_process_req req;
283 req = (enum kauth_process_req)arg2;
284 switch (req) {
285 case KAUTH_REQ_PROCESS_PROCFS_READ:
286 break;
288 case KAUTH_REQ_PROCESS_PROCFS_RW:
289 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
290 if ((p == initproc) && (kstate != KEYLOCK_OPEN))
291 result = KAUTH_RESULT_DENY;
293 break;
294 default:
295 break;
298 break;
301 case KAUTH_PROCESS_PTRACE:
302 if ((p == initproc) && (kstate != KEYLOCK_OPEN))
303 result = KAUTH_RESULT_DENY;
305 break;
307 case KAUTH_PROCESS_CORENAME:
308 if (kstate == KEYLOCK_CLOSE)
309 result = KAUTH_RESULT_DENY;
310 break;
312 return result;
316 * kauth(9) listener
318 * Security model: Multi-position keylock
319 * Scope: Network
320 * Responsibility: Keylock
323 secmodel_keylock_network_cb(kauth_cred_t cred,
324 kauth_action_t action, void *cookie, void *arg0,
325 void *arg1, void *arg2, void *arg3)
327 int result, kstate;
328 enum kauth_network_req req;
330 kstate = keylock_state();
331 if (kstate == KEYLOCK_ABSENT)
332 return KAUTH_RESULT_DEFER;
333 else if (kstate == KEYLOCK_TAMPER)
334 return KAUTH_RESULT_DENY;
336 result = KAUTH_RESULT_DEFER;
337 req = (enum kauth_network_req)arg0;
339 switch (action) {
340 case KAUTH_NETWORK_FIREWALL:
341 switch (req) {
342 case KAUTH_REQ_NETWORK_FIREWALL_FW:
343 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
344 if (kstate == KEYLOCK_CLOSE)
345 result = KAUTH_RESULT_DENY;
346 break;
348 default:
349 break;
351 break;
353 case KAUTH_NETWORK_FORWSRCRT:
354 if (kstate != KEYLOCK_OPEN)
355 result = KAUTH_RESULT_DENY;
356 break;
359 return result;
363 * kauth(9) listener
365 * Security model: Multi-position keylock
366 * Scope: Machdep
367 * Responsibility: Keylock
370 secmodel_keylock_machdep_cb(kauth_cred_t cred,
371 kauth_action_t action, void *cookie, void *arg0,
372 void *arg1, void *arg2, void *arg3)
374 int result, kstate;
376 kstate = keylock_state();
377 if (kstate == KEYLOCK_ABSENT)
378 return KAUTH_RESULT_DEFER;
379 else if (kstate == KEYLOCK_TAMPER)
380 return KAUTH_RESULT_DENY;
382 result = KAUTH_RESULT_DEFER;
384 switch (action) {
385 case KAUTH_MACHDEP_IOPERM_SET:
386 case KAUTH_MACHDEP_IOPL:
387 if (kstate != KEYLOCK_OPEN)
388 result = KAUTH_RESULT_DENY;
389 break;
391 case KAUTH_MACHDEP_UNMANAGEDMEM:
392 if (kstate != KEYLOCK_OPEN)
393 result = KAUTH_RESULT_DENY;
394 break;
397 return result;
401 * kauth(9) listener
403 * Security model: Multi-position keylock
404 * Scope: Device
405 * Responsibility: Keylock
408 secmodel_keylock_device_cb(kauth_cred_t cred,
409 kauth_action_t action, void *cookie, void *arg0,
410 void *arg1, void *arg2, void *arg3)
412 int result, kstate, error;
414 kstate = keylock_state();
415 if (kstate == KEYLOCK_ABSENT)
416 return KAUTH_RESULT_DEFER;
417 else if (kstate == KEYLOCK_TAMPER)
418 return KAUTH_RESULT_DENY;
420 result = KAUTH_RESULT_DEFER;
422 switch (action) {
423 case KAUTH_DEVICE_RAWIO_SPEC: {
424 struct vnode *vp;
425 enum kauth_device_req req;
427 req = (enum kauth_device_req)arg0;
428 vp = arg1;
430 KASSERT(vp != NULL);
432 /* Handle /dev/mem and /dev/kmem. */
433 if (iskmemvp(vp)) {
434 switch (req) {
435 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
436 break;
438 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
439 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
440 if (kstate != KEYLOCK_OPEN)
441 result = KAUTH_RESULT_DENY;
442 break;
443 default:
444 break;
446 break;
449 switch (req) {
450 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
451 break;
453 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
454 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
455 error = rawdev_mounted(vp, NULL);
457 if (error == EINVAL)
458 break;
460 if (error && (kstate != KEYLOCK_OPEN))
461 break;
463 if (kstate == KEYLOCK_CLOSE)
464 result = KAUTH_RESULT_DENY;
466 break;
467 default:
468 break;
470 break;
473 case KAUTH_DEVICE_RAWIO_PASSTHRU:
474 if (kstate != KEYLOCK_OPEN) {
475 u_long bits;
477 bits = (u_long)arg0;
479 KASSERT(bits != 0);
480 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL)
481 == 0);
483 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
484 result = KAUTH_RESULT_DENY;
486 break;
488 case KAUTH_DEVICE_GPIO_PINSET:
489 if (kstate != KEYLOCK_OPEN)
490 result = KAUTH_RESULT_DENY;
491 break;
492 default:
493 break;
495 return result;