secmodel_keylock.c revision 1.5.12.2 1 /* $NetBSD: secmodel_keylock.c,v 1.5.12.2 2014/05/22 11:41:17 yamt Exp $ */
2 /*-
3 * Copyright (c) 2009 Marc Balmer <marc (at) msys.ch>
4 * Copyright (c) 2006 Elad Efrat <elad (at) NetBSD.org>
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 * 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.
17 *
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.
28 */
29
30 /*
31 * This file contains kauth(9) listeners needed to implement an experimental
32 * keylock based security scheme.
33 *
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.
36 *
37 * Rules:
38 *
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
41 *
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.
45 *
46 * - If the lock is in the lowest position, assume the system is locked and
47 * forbid most actions.
48 *
49 * - If the lock is in the highest position, assume the system to be open and
50 * forbid nothing.
51 *
52 * - If the security.models.keylock.order sysctl is set to a value != 0,
53 * reverse this order.
54 */
55
56 #include <sys/cdefs.h>
57 __KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.5.12.2 2014/05/22 11:41:17 yamt Exp $");
58
59 #include <sys/types.h>
60 #include <sys/param.h>
61 #include <sys/kauth.h>
62
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>
68
69 #include <dev/keylock.h>
70
71 #include <miscfs/specfs/specdev.h>
72
73 #include <secmodel/secmodel.h>
74 #include <secmodel/keylock/keylock.h>
75
76 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device;
77
78 static secmodel_t keylock_sm;
79
80 SYSCTL_SETUP(sysctl_security_keylock_setup,
81 "sysctl security keylock setup")
82 {
83 const struct sysctlnode *rnode;
84
85 sysctl_createv(clog, 0, NULL, &rnode,
86 CTLFLAG_PERMANENT,
87 CTLTYPE_NODE, "models", NULL,
88 NULL, 0, NULL, 0,
89 CTL_SECURITY, CTL_CREATE, CTL_EOL);
90
91 sysctl_createv(clog, 0, &rnode, &rnode,
92 CTLFLAG_PERMANENT,
93 CTLTYPE_NODE, "keylock",
94 SYSCTL_DESCR("Keylock security model"),
95 NULL, 0, NULL, 0,
96 CTL_CREATE, CTL_EOL);
97
98 sysctl_createv(clog, 0, &rnode, NULL,
99 CTLFLAG_PERMANENT,
100 CTLTYPE_STRING, "name", NULL,
101 NULL, 0, __UNCONST("Keylock"), 0,
102 CTL_CREATE, CTL_EOL);
103 }
104
105 void
106 secmodel_keylock_init(void)
107 {
108 int error = secmodel_register(&keylock_sm,
109 "org.netbsd.secmodel.keylock",
110 "NetBSD Security Model: Keylock", NULL, NULL, NULL);
111 if (error != 0)
112 printf("secmodel_keylock_init: secmodel_register "
113 "returned %d\n", error);
114 }
115
116 void
117 secmodel_keylock_start(void)
118 {
119 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
120 secmodel_keylock_system_cb, NULL);
121 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
122 secmodel_keylock_process_cb, NULL);
123 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
124 secmodel_keylock_network_cb, NULL);
125 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
126 secmodel_keylock_machdep_cb, NULL);
127 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
128 secmodel_keylock_device_cb, NULL);
129 }
130
131 void
132 secmodel_keylock_stop(void)
133 {
134 int error;
135
136 kauth_unlisten_scope(l_system);
137 kauth_unlisten_scope(l_process);
138 kauth_unlisten_scope(l_network);
139 kauth_unlisten_scope(l_machdep);
140 kauth_unlisten_scope(l_device);
141
142 error = secmodel_deregister(keylock_sm);
143 if (error != 0)
144 printf("secmodel_keylock_stop: secmodel_deregister "
145 "returned %d\n", error);
146 }
147
148 /*
149 * kauth(9) listener
150 *
151 * Security model: Multi-position keylock
152 * Scope: System
153 * Responsibility: Keylock
154 */
155 int
156 secmodel_keylock_system_cb(kauth_cred_t cred,
157 kauth_action_t action, void *cookie, void *arg0, void *arg1,
158 void *arg2, void *arg3)
159 {
160 int result;
161 enum kauth_system_req req;
162 int kstate;
163
164 kstate = keylock_state();
165 if (kstate == KEYLOCK_ABSENT)
166 return KAUTH_RESULT_DEFER;
167 else if (kstate == KEYLOCK_TAMPER)
168 return KAUTH_RESULT_DENY;
169
170 result = KAUTH_RESULT_DEFER;
171 req = (enum kauth_system_req)arg0;
172
173 switch (action) {
174 case KAUTH_SYSTEM_CHSYSFLAGS:
175 if (kstate == KEYLOCK_CLOSE)
176 result = KAUTH_RESULT_DENY;
177 break;
178
179 case KAUTH_SYSTEM_TIME:
180 switch (req) {
181 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
182 if (kstate == KEYLOCK_CLOSE)
183 result = KAUTH_RESULT_DENY;
184 break;
185
186 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
187 struct timespec *ts = arg1;
188 struct timespec *delta = arg2;
189
190 if (keylock_position() > 1 && time_wraps(ts, delta))
191 result = KAUTH_RESULT_DENY;
192 break;
193 }
194 default:
195 break;
196 }
197 break;
198
199 case KAUTH_SYSTEM_MODULE:
200 if (kstate == KEYLOCK_CLOSE)
201 result = KAUTH_RESULT_DENY;
202 break;
203
204 case KAUTH_SYSTEM_MOUNT:
205 switch (req) {
206 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
207 if (kstate == KEYLOCK_CLOSE)
208 result = KAUTH_RESULT_DENY;
209
210 break;
211
212 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
213 if (kstate == KEYLOCK_CLOSE) {
214 struct mount *mp = arg1;
215 u_long flags = (u_long)arg2;
216
217 /*
218 * Can only degrade from read/write to
219 * read-only.
220 */
221 if (flags != (mp->mnt_flag | MNT_RDONLY |
222 MNT_RELOAD | MNT_FORCE | MNT_UPDATE))
223 result = KAUTH_RESULT_DENY;
224 }
225 break;
226 default:
227 break;
228 }
229
230 break;
231
232 case KAUTH_SYSTEM_SYSCTL:
233 switch (req) {
234 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
235 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
236 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
237 if (kstate == KEYLOCK_CLOSE)
238 result = KAUTH_RESULT_DENY;
239 break;
240 default:
241 break;
242 }
243 break;
244
245 case KAUTH_SYSTEM_SETIDCORE:
246 if (kstate == KEYLOCK_CLOSE)
247 result = KAUTH_RESULT_DENY;
248 break;
249
250 case KAUTH_SYSTEM_DEBUG:
251 switch (req) {
252 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
253 if (kstate == KEYLOCK_CLOSE)
254 result = KAUTH_RESULT_DENY;
255 break;
256 default:
257 break;
258 }
259 break;
260 }
261
262 return result;
263 }
264
265 /*
266 * kauth(9) listener
267 *
268 * Security model: Multi-position keylock
269 * Scope: Process
270 * Responsibility: Keylock
271 */
272 int
273 secmodel_keylock_process_cb(kauth_cred_t cred,
274 kauth_action_t action, void *cookie, void *arg0,
275 void *arg1, void *arg2, void *arg3)
276 {
277 struct proc *p;
278 int result, kstate;
279
280 kstate = keylock_state();
281 if (kstate == KEYLOCK_ABSENT)
282 return KAUTH_RESULT_DEFER;
283 else if (kstate == KEYLOCK_TAMPER)
284 return KAUTH_RESULT_DENY;
285
286 result = KAUTH_RESULT_DEFER;
287 p = arg0;
288
289 switch (action) {
290 case KAUTH_PROCESS_PROCFS: {
291 enum kauth_process_req req;
292
293 req = (enum kauth_process_req)arg2;
294 switch (req) {
295 case KAUTH_REQ_PROCESS_PROCFS_READ:
296 break;
297
298 case KAUTH_REQ_PROCESS_PROCFS_RW:
299 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
300 if ((p == initproc) && (kstate != KEYLOCK_OPEN))
301 result = KAUTH_RESULT_DENY;
302
303 break;
304 default:
305 break;
306 }
307
308 break;
309 }
310
311 case KAUTH_PROCESS_PTRACE:
312 if ((p == initproc) && (kstate != KEYLOCK_OPEN))
313 result = KAUTH_RESULT_DENY;
314
315 break;
316
317 case KAUTH_PROCESS_CORENAME:
318 if (kstate == KEYLOCK_CLOSE)
319 result = KAUTH_RESULT_DENY;
320 break;
321 }
322 return result;
323 }
324
325 /*
326 * kauth(9) listener
327 *
328 * Security model: Multi-position keylock
329 * Scope: Network
330 * Responsibility: Keylock
331 */
332 int
333 secmodel_keylock_network_cb(kauth_cred_t cred,
334 kauth_action_t action, void *cookie, void *arg0,
335 void *arg1, void *arg2, void *arg3)
336 {
337 int result, kstate;
338 enum kauth_network_req req;
339
340 kstate = keylock_state();
341 if (kstate == KEYLOCK_ABSENT)
342 return KAUTH_RESULT_DEFER;
343 else if (kstate == KEYLOCK_TAMPER)
344 return KAUTH_RESULT_DENY;
345
346 result = KAUTH_RESULT_DEFER;
347 req = (enum kauth_network_req)arg0;
348
349 switch (action) {
350 case KAUTH_NETWORK_FIREWALL:
351 switch (req) {
352 case KAUTH_REQ_NETWORK_FIREWALL_FW:
353 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
354 if (kstate == KEYLOCK_CLOSE)
355 result = KAUTH_RESULT_DENY;
356 break;
357
358 default:
359 break;
360 }
361 break;
362
363 case KAUTH_NETWORK_FORWSRCRT:
364 if (kstate != KEYLOCK_OPEN)
365 result = KAUTH_RESULT_DENY;
366 break;
367 }
368
369 return result;
370 }
371
372 /*
373 * kauth(9) listener
374 *
375 * Security model: Multi-position keylock
376 * Scope: Machdep
377 * Responsibility: Keylock
378 */
379 int
380 secmodel_keylock_machdep_cb(kauth_cred_t cred,
381 kauth_action_t action, void *cookie, void *arg0,
382 void *arg1, void *arg2, void *arg3)
383 {
384 int result, kstate;
385
386 kstate = keylock_state();
387 if (kstate == KEYLOCK_ABSENT)
388 return KAUTH_RESULT_DEFER;
389 else if (kstate == KEYLOCK_TAMPER)
390 return KAUTH_RESULT_DENY;
391
392 result = KAUTH_RESULT_DEFER;
393
394 switch (action) {
395 case KAUTH_MACHDEP_IOPERM_SET:
396 case KAUTH_MACHDEP_IOPL:
397 if (kstate != KEYLOCK_OPEN)
398 result = KAUTH_RESULT_DENY;
399 break;
400
401 case KAUTH_MACHDEP_UNMANAGEDMEM:
402 if (kstate != KEYLOCK_OPEN)
403 result = KAUTH_RESULT_DENY;
404 break;
405 }
406
407 return result;
408 }
409
410 /*
411 * kauth(9) listener
412 *
413 * Security model: Multi-position keylock
414 * Scope: Device
415 * Responsibility: Keylock
416 */
417 int
418 secmodel_keylock_device_cb(kauth_cred_t cred,
419 kauth_action_t action, void *cookie, void *arg0,
420 void *arg1, void *arg2, void *arg3)
421 {
422 int result, kstate, error;
423
424 kstate = keylock_state();
425 if (kstate == KEYLOCK_ABSENT)
426 return KAUTH_RESULT_DEFER;
427 else if (kstate == KEYLOCK_TAMPER)
428 return KAUTH_RESULT_DENY;
429
430 result = KAUTH_RESULT_DEFER;
431
432 switch (action) {
433 case KAUTH_DEVICE_RAWIO_SPEC: {
434 struct vnode *vp;
435 enum kauth_device_req req;
436
437 req = (enum kauth_device_req)arg0;
438 vp = arg1;
439
440 KASSERT(vp != NULL);
441
442 /* Handle /dev/mem and /dev/kmem. */
443 if (iskmemvp(vp)) {
444 switch (req) {
445 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
446 break;
447
448 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
449 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
450 if (kstate != KEYLOCK_OPEN)
451 result = KAUTH_RESULT_DENY;
452 break;
453 default:
454 break;
455 }
456 break;
457 }
458
459 switch (req) {
460 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
461 break;
462
463 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
464 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
465 error = rawdev_mounted(vp, NULL);
466
467 if (error == EINVAL)
468 break;
469
470 if (error && (kstate != KEYLOCK_OPEN))
471 break;
472
473 if (kstate == KEYLOCK_CLOSE)
474 result = KAUTH_RESULT_DENY;
475
476 break;
477 default:
478 break;
479 }
480 break;
481 }
482
483 case KAUTH_DEVICE_RAWIO_PASSTHRU:
484 if (kstate != KEYLOCK_OPEN) {
485 u_long bits;
486
487 bits = (u_long)arg0;
488
489 KASSERT(bits != 0);
490 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL)
491 == 0);
492
493 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
494 result = KAUTH_RESULT_DENY;
495 }
496 break;
497
498 case KAUTH_DEVICE_GPIO_PINSET:
499 if (kstate != KEYLOCK_OPEN)
500 result = KAUTH_RESULT_DENY;
501 break;
502 default:
503 break;
504 }
505 return result;
506 }
507