secmodel_securelevel.c revision 1.29 1 /* $NetBSD: secmodel_securelevel.c,v 1.29 2013/01/28 00:51:30 jym Exp $ */
2 /*-
3 * Copyright (c) 2006 Elad Efrat <elad (at) NetBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * This file contains kauth(9) listeners needed to implement the traditional
31 * NetBSD securelevel.
32 *
33 * The securelevel is a system-global indication on what operations are
34 * allowed or not. It affects all users, including root.
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.29 2013/01/28 00:51:30 jym Exp $");
39
40 #ifdef _KERNEL_OPT
41 #include "opt_insecure.h"
42 #endif /* _KERNEL_OPT */
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/kauth.h>
47
48 #include <sys/conf.h>
49 #include <sys/mount.h>
50 #include <sys/sysctl.h>
51 #include <sys/vnode.h>
52 #include <sys/module.h>
53 #include <sys/timevar.h>
54
55 #include <miscfs/specfs/specdev.h>
56
57 #include <secmodel/secmodel.h>
58 #include <secmodel/securelevel/securelevel.h>
59
60 MODULE(MODULE_CLASS_SECMODEL, securelevel, NULL);
61
62 static int securelevel;
63
64 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device,
65 l_vnode;
66
67 static secmodel_t securelevel_sm;
68 static struct sysctllog *securelevel_sysctl_log;
69
70 /*
71 * Sysctl helper routine for securelevel. Ensures that the value only rises
72 * unless the caller is init.
73 */
74 int
75 secmodel_securelevel_sysctl(SYSCTLFN_ARGS)
76 {
77 int newsecurelevel, error;
78 struct sysctlnode node;
79
80 newsecurelevel = securelevel;
81 node = *rnode;
82 node.sysctl_data = &newsecurelevel;
83 error = sysctl_lookup(SYSCTLFN_CALL(&node));
84 if (error || newp == NULL)
85 return (error);
86
87 if ((newsecurelevel < securelevel) && (l->l_proc != initproc))
88 return (EPERM);
89
90 securelevel = newsecurelevel;
91
92 return (error);
93 }
94
95 void
96 sysctl_security_securelevel_setup(struct sysctllog **clog)
97 {
98 const struct sysctlnode *rnode, *rnode2;
99
100 sysctl_createv(clog, 0, NULL, &rnode,
101 CTLFLAG_PERMANENT,
102 CTLTYPE_NODE, "security", NULL,
103 NULL, 0, NULL, 0,
104 CTL_SECURITY, CTL_EOL);
105
106 sysctl_createv(clog, 0, &rnode, &rnode,
107 CTLFLAG_PERMANENT,
108 CTLTYPE_NODE, "models", NULL,
109 NULL, 0, NULL, 0,
110 CTL_CREATE, CTL_EOL);
111
112 /* Compatibility: security.models.bsd44 */
113 rnode2 = rnode;
114 sysctl_createv(clog, 0, &rnode2, &rnode2,
115 CTLFLAG_PERMANENT,
116 CTLTYPE_NODE, "bsd44", NULL,
117 NULL, 0, NULL, 0,
118 CTL_CREATE, CTL_EOL);
119
120 /* Compatibility: security.models.bsd44.securelevel */
121 sysctl_createv(clog, 0, &rnode2, NULL,
122 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
123 CTLTYPE_INT, "securelevel",
124 SYSCTL_DESCR("System security level"),
125 secmodel_securelevel_sysctl, 0, NULL, 0,
126 CTL_CREATE, CTL_EOL);
127
128 sysctl_createv(clog, 0, &rnode, &rnode,
129 CTLFLAG_PERMANENT,
130 CTLTYPE_NODE, "securelevel", NULL,
131 NULL, 0, NULL, 0,
132 CTL_CREATE, CTL_EOL);
133
134 sysctl_createv(clog, 0, &rnode, NULL,
135 CTLFLAG_PERMANENT,
136 CTLTYPE_STRING, "name", NULL,
137 NULL, 0, __UNCONST(SECMODEL_SECURELEVEL_NAME), 0,
138 CTL_CREATE, CTL_EOL);
139
140 sysctl_createv(clog, 0, &rnode, NULL,
141 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
142 CTLTYPE_INT, "securelevel",
143 SYSCTL_DESCR("System security level"),
144 secmodel_securelevel_sysctl, 0, NULL, 0,
145 CTL_CREATE, CTL_EOL);
146
147 /* Compatibility: kern.securelevel */
148 sysctl_createv(clog, 0, NULL, NULL,
149 CTLFLAG_PERMANENT,
150 CTLTYPE_NODE, "kern", NULL,
151 NULL, 0, NULL, 0,
152 CTL_KERN, CTL_EOL);
153
154 sysctl_createv(clog, 0, NULL, NULL,
155 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
156 CTLTYPE_INT, "securelevel",
157 SYSCTL_DESCR("System security level"),
158 secmodel_securelevel_sysctl, 0, NULL, 0,
159 CTL_KERN, KERN_SECURELVL, CTL_EOL);
160 }
161
162 void
163 secmodel_securelevel_init(void)
164 {
165 #ifdef INSECURE
166 securelevel = -1;
167 #else
168 securelevel = 0;
169 #endif /* INSECURE */
170 }
171
172 void
173 secmodel_securelevel_start(void)
174 {
175 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
176 secmodel_securelevel_system_cb, NULL);
177 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
178 secmodel_securelevel_process_cb, NULL);
179 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
180 secmodel_securelevel_network_cb, NULL);
181 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
182 secmodel_securelevel_machdep_cb, NULL);
183 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
184 secmodel_securelevel_device_cb, NULL);
185 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
186 secmodel_securelevel_vnode_cb, NULL);
187 }
188
189 void
190 secmodel_securelevel_stop(void)
191 {
192 kauth_unlisten_scope(l_system);
193 kauth_unlisten_scope(l_process);
194 kauth_unlisten_scope(l_network);
195 kauth_unlisten_scope(l_machdep);
196 kauth_unlisten_scope(l_device);
197 kauth_unlisten_scope(l_vnode);
198 }
199
200 static int
201 securelevel_eval(const char *what, void *arg, void *ret)
202 {
203 int error = 0;
204
205 if (strcasecmp(what, "is-securelevel-above") == 0) {
206 int level = (int)(uintptr_t)arg;
207 bool *bp = ret;
208
209 *bp = (securelevel > level);
210 } else {
211 error = ENOENT;
212 }
213
214 return error;
215 }
216
217 static int
218 securelevel_modcmd(modcmd_t cmd, void *arg)
219 {
220 int error = 0;
221
222 switch (cmd) {
223 case MODULE_CMD_INIT:
224 secmodel_securelevel_init();
225 error = secmodel_register(&securelevel_sm,
226 SECMODEL_SECURELEVEL_ID, SECMODEL_SECURELEVEL_NAME,
227 NULL, securelevel_eval, NULL);
228 if (error != 0)
229 printf("securelevel_modcmd::init: secmodel_register "
230 "returned %d\n", error);
231
232 secmodel_securelevel_start();
233 sysctl_security_securelevel_setup(&securelevel_sysctl_log);
234 break;
235
236 case MODULE_CMD_FINI:
237 sysctl_teardown(&securelevel_sysctl_log);
238 secmodel_securelevel_stop();
239
240 error = secmodel_deregister(securelevel_sm);
241 if (error != 0)
242 printf("securelevel_modcmd::fini: secmodel_deregister "
243 "returned %d\n", error);
244
245 break;
246
247 case MODULE_CMD_AUTOUNLOAD:
248 error = EPERM;
249 break;
250
251 default:
252 error = ENOTTY;
253 break;
254 }
255
256 return (error);
257 }
258
259 /*
260 * kauth(9) listener
261 *
262 * Security model: Traditional NetBSD
263 * Scope: System
264 * Responsibility: Securelevel
265 */
266 int
267 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action,
268 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
269 {
270 int result;
271 enum kauth_system_req req;
272
273 result = KAUTH_RESULT_DEFER;
274 req = (enum kauth_system_req)arg0;
275
276 switch (action) {
277 case KAUTH_SYSTEM_CHSYSFLAGS:
278 /* Deprecated. */
279 if (securelevel > 0)
280 result = KAUTH_RESULT_DENY;
281 break;
282
283 case KAUTH_SYSTEM_TIME:
284 switch (req) {
285 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
286 if (securelevel > 0)
287 result = KAUTH_RESULT_DENY;
288 break;
289
290 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
291 struct timespec *ts = arg1;
292 struct timespec *delta = arg2;
293
294 if (securelevel > 1 && time_wraps(ts, delta))
295 result = KAUTH_RESULT_DENY;
296
297 break;
298 }
299
300 default:
301 break;
302 }
303 break;
304
305 case KAUTH_SYSTEM_MAP_VA_ZERO:
306 if (securelevel > 0)
307 result = KAUTH_RESULT_DENY;
308 break;
309
310 case KAUTH_SYSTEM_MODULE:
311 if (securelevel > 0)
312 result = KAUTH_RESULT_DENY;
313 break;
314
315 case KAUTH_SYSTEM_MOUNT:
316 switch (req) {
317 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
318 if (securelevel > 1)
319 result = KAUTH_RESULT_DENY;
320
321 break;
322
323 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
324 if (securelevel > 1) {
325 struct mount *mp = arg1;
326 u_long flags = (u_long)arg2;
327
328 /* Can only degrade from read/write to read-only. */
329 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
330 MNT_FORCE | MNT_UPDATE))
331 result = KAUTH_RESULT_DENY;
332 }
333
334 break;
335
336 default:
337 break;
338 }
339
340 break;
341
342 case KAUTH_SYSTEM_SYSCTL:
343 switch (req) {
344 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
345 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
346 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
347 if (securelevel > 0)
348 result = KAUTH_RESULT_DENY;
349 break;
350
351 default:
352 break;
353 }
354 break;
355
356 case KAUTH_SYSTEM_SETIDCORE:
357 if (securelevel > 0)
358 result = KAUTH_RESULT_DENY;
359 break;
360
361 case KAUTH_SYSTEM_DEBUG:
362 switch (req) {
363 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
364 if (securelevel > 0)
365 result = KAUTH_RESULT_DENY;
366 break;
367
368 default:
369 break;
370 }
371 break;
372
373 default:
374 break;
375 }
376
377 return (result);
378 }
379
380 /*
381 * kauth(9) listener
382 *
383 * Security model: Traditional NetBSD
384 * Scope: Process
385 * Responsibility: Securelevel
386 */
387 int
388 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action,
389 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
390 {
391 struct proc *p;
392 int result;
393
394 result = KAUTH_RESULT_DEFER;
395 p = arg0;
396
397 switch (action) {
398 case KAUTH_PROCESS_PROCFS: {
399 enum kauth_process_req req;
400
401 req = (enum kauth_process_req)arg2;
402 switch (req) {
403 case KAUTH_REQ_PROCESS_PROCFS_READ:
404 break;
405
406 case KAUTH_REQ_PROCESS_PROCFS_RW:
407 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
408 if ((p == initproc) && (securelevel > -1))
409 result = KAUTH_RESULT_DENY;
410
411 break;
412
413 default:
414 break;
415 }
416
417 break;
418 }
419
420 case KAUTH_PROCESS_PTRACE:
421 if ((p == initproc) && (securelevel > -1))
422 result = KAUTH_RESULT_DENY;
423
424 break;
425
426 case KAUTH_PROCESS_CORENAME:
427 if (securelevel > 1)
428 result = KAUTH_RESULT_DENY;
429 break;
430
431 default:
432 break;
433 }
434
435 return (result);
436 }
437
438 /*
439 * kauth(9) listener
440 *
441 * Security model: Traditional NetBSD
442 * Scope: Network
443 * Responsibility: Securelevel
444 */
445 int
446 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action,
447 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
448 {
449 int result;
450 enum kauth_network_req req;
451
452 result = KAUTH_RESULT_DEFER;
453 req = (enum kauth_network_req)arg0;
454
455 switch (action) {
456 case KAUTH_NETWORK_FIREWALL:
457 switch (req) {
458 case KAUTH_REQ_NETWORK_FIREWALL_FW:
459 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
460 if (securelevel > 1)
461 result = KAUTH_RESULT_DENY;
462 break;
463
464 default:
465 break;
466 }
467 break;
468
469 case KAUTH_NETWORK_FORWSRCRT:
470 if (securelevel > 0)
471 result = KAUTH_RESULT_DENY;
472 break;
473
474 default:
475 break;
476 }
477
478 return (result);
479 }
480
481 /*
482 * kauth(9) listener
483 *
484 * Security model: Traditional NetBSD
485 * Scope: Machdep
486 * Responsibility: Securelevel
487 */
488 int
489 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action,
490 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
491 {
492 int result;
493
494 result = KAUTH_RESULT_DEFER;
495
496 switch (action) {
497 case KAUTH_MACHDEP_IOPERM_SET:
498 case KAUTH_MACHDEP_IOPL:
499 if (securelevel > 0)
500 result = KAUTH_RESULT_DENY;
501 break;
502
503 case KAUTH_MACHDEP_UNMANAGEDMEM:
504 if (securelevel > 0)
505 result = KAUTH_RESULT_DENY;
506 break;
507
508 case KAUTH_MACHDEP_CPU_UCODE_APPLY:
509 if (securelevel > 1)
510 result = KAUTH_RESULT_DENY;
511 break;
512
513 default:
514 break;
515 }
516
517 return (result);
518 }
519
520 /*
521 * kauth(9) listener
522 *
523 * Security model: Traditional NetBSD
524 * Scope: Device
525 * Responsibility: Securelevel
526 */
527 int
528 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action,
529 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
530 {
531 int result;
532
533 result = KAUTH_RESULT_DEFER;
534
535 switch (action) {
536 case KAUTH_DEVICE_RAWIO_SPEC: {
537 struct vnode *vp;
538 enum kauth_device_req req;
539
540 req = (enum kauth_device_req)arg0;
541 vp = arg1;
542
543 KASSERT(vp != NULL);
544
545 /* Handle /dev/mem and /dev/kmem. */
546 if (iskmemvp(vp)) {
547 switch (req) {
548 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
549 break;
550
551 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
552 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
553 if (securelevel > 0)
554 result = KAUTH_RESULT_DENY;
555
556 break;
557
558 default:
559 break;
560 }
561
562 break;
563 }
564
565 switch (req) {
566 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
567 break;
568
569 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
570 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
571 int error;
572
573 error = rawdev_mounted(vp, NULL);
574
575 /* Not a disk. */
576 if (error == EINVAL)
577 break;
578
579 if (error && securelevel > 0)
580 result = KAUTH_RESULT_DENY;
581
582 if (securelevel > 1)
583 result = KAUTH_RESULT_DENY;
584
585 break;
586 }
587
588 default:
589 break;
590 }
591
592 break;
593 }
594
595 case KAUTH_DEVICE_RAWIO_PASSTHRU:
596 if (securelevel > 0) {
597 u_long bits;
598
599 bits = (u_long)arg0;
600
601 KASSERT(bits != 0);
602 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
603
604 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
605 result = KAUTH_RESULT_DENY;
606 }
607
608 break;
609
610 case KAUTH_DEVICE_GPIO_PINSET:
611 if (securelevel > 0)
612 result = KAUTH_RESULT_DENY;
613 break;
614
615 case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
616 if (securelevel > 0)
617 result = KAUTH_RESULT_DENY;
618 break;
619
620 default:
621 break;
622 }
623
624 return (result);
625 }
626
627 int
628 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
629 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
630 {
631 int result;
632
633 result = KAUTH_RESULT_DEFER;
634
635 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
636 (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
637 if (securelevel > 0)
638 result = KAUTH_RESULT_DENY;
639 }
640
641 return (result);
642 }
643
644