secmodel_securelevel.c revision 1.26.2.1 1 /* $NetBSD: secmodel_securelevel.c,v 1.26.2.1 2013/02/08 23:04:26 riz 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.26.2.1 2013/02/08 23:04:26 riz 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 if (securelevel > 0)
279 result = KAUTH_RESULT_DENY;
280 break;
281
282 case KAUTH_SYSTEM_TIME:
283 switch (req) {
284 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
285 if (securelevel > 0)
286 result = KAUTH_RESULT_DENY;
287 break;
288
289 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
290 struct timespec *ts = arg1;
291 struct timespec *delta = arg2;
292
293 if (securelevel > 1 && time_wraps(ts, delta))
294 result = KAUTH_RESULT_DENY;
295
296 break;
297 }
298
299 default:
300 break;
301 }
302 break;
303
304 case KAUTH_SYSTEM_MODULE:
305 if (securelevel > 0)
306 result = KAUTH_RESULT_DENY;
307 break;
308
309 case KAUTH_SYSTEM_MOUNT:
310 switch (req) {
311 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
312 if (securelevel > 1)
313 result = KAUTH_RESULT_DENY;
314
315 break;
316
317 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
318 if (securelevel > 1) {
319 struct mount *mp = arg1;
320 u_long flags = (u_long)arg2;
321
322 /* Can only degrade from read/write to read-only. */
323 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
324 MNT_FORCE | MNT_UPDATE))
325 result = KAUTH_RESULT_DENY;
326 }
327
328 break;
329
330 default:
331 break;
332 }
333
334 break;
335
336 case KAUTH_SYSTEM_SYSCTL:
337 switch (req) {
338 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
339 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
340 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
341 if (securelevel > 0)
342 result = KAUTH_RESULT_DENY;
343 break;
344
345 default:
346 break;
347 }
348 break;
349
350 case KAUTH_SYSTEM_SETIDCORE:
351 if (securelevel > 0)
352 result = KAUTH_RESULT_DENY;
353 break;
354
355 case KAUTH_SYSTEM_DEBUG:
356 switch (req) {
357 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
358 if (securelevel > 0)
359 result = KAUTH_RESULT_DENY;
360 break;
361
362 default:
363 break;
364 }
365 break;
366
367 default:
368 break;
369 }
370
371 return (result);
372 }
373
374 /*
375 * kauth(9) listener
376 *
377 * Security model: Traditional NetBSD
378 * Scope: Process
379 * Responsibility: Securelevel
380 */
381 int
382 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action,
383 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
384 {
385 struct proc *p;
386 int result;
387
388 result = KAUTH_RESULT_DEFER;
389 p = arg0;
390
391 switch (action) {
392 case KAUTH_PROCESS_PROCFS: {
393 enum kauth_process_req req;
394
395 req = (enum kauth_process_req)arg2;
396 switch (req) {
397 case KAUTH_REQ_PROCESS_PROCFS_READ:
398 break;
399
400 case KAUTH_REQ_PROCESS_PROCFS_RW:
401 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
402 if ((p == initproc) && (securelevel > -1))
403 result = KAUTH_RESULT_DENY;
404
405 break;
406
407 default:
408 break;
409 }
410
411 break;
412 }
413
414 case KAUTH_PROCESS_PTRACE:
415 if ((p == initproc) && (securelevel > -1))
416 result = KAUTH_RESULT_DENY;
417
418 break;
419
420 case KAUTH_PROCESS_CORENAME:
421 if (securelevel > 1)
422 result = KAUTH_RESULT_DENY;
423 break;
424
425 default:
426 break;
427 }
428
429 return (result);
430 }
431
432 /*
433 * kauth(9) listener
434 *
435 * Security model: Traditional NetBSD
436 * Scope: Network
437 * Responsibility: Securelevel
438 */
439 int
440 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action,
441 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
442 {
443 int result;
444 enum kauth_network_req req;
445
446 result = KAUTH_RESULT_DEFER;
447 req = (enum kauth_network_req)arg0;
448
449 switch (action) {
450 case KAUTH_NETWORK_FIREWALL:
451 switch (req) {
452 case KAUTH_REQ_NETWORK_FIREWALL_FW:
453 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
454 if (securelevel > 1)
455 result = KAUTH_RESULT_DENY;
456 break;
457
458 default:
459 break;
460 }
461 break;
462
463 case KAUTH_NETWORK_FORWSRCRT:
464 if (securelevel > 0)
465 result = KAUTH_RESULT_DENY;
466 break;
467
468 default:
469 break;
470 }
471
472 return (result);
473 }
474
475 /*
476 * kauth(9) listener
477 *
478 * Security model: Traditional NetBSD
479 * Scope: Machdep
480 * Responsibility: Securelevel
481 */
482 int
483 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action,
484 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
485 {
486 int result;
487
488 result = KAUTH_RESULT_DEFER;
489
490 switch (action) {
491 case KAUTH_MACHDEP_IOPERM_SET:
492 case KAUTH_MACHDEP_IOPL:
493 if (securelevel > 0)
494 result = KAUTH_RESULT_DENY;
495 break;
496
497 case KAUTH_MACHDEP_UNMANAGEDMEM:
498 if (securelevel > 0)
499 result = KAUTH_RESULT_DENY;
500 break;
501
502 case KAUTH_MACHDEP_CPU_UCODE_APPLY:
503 if (securelevel > 1)
504 result = KAUTH_RESULT_DENY;
505 break;
506
507 default:
508 break;
509 }
510
511 return (result);
512 }
513
514 /*
515 * kauth(9) listener
516 *
517 * Security model: Traditional NetBSD
518 * Scope: Device
519 * Responsibility: Securelevel
520 */
521 int
522 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action,
523 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
524 {
525 int result;
526
527 result = KAUTH_RESULT_DEFER;
528
529 switch (action) {
530 case KAUTH_DEVICE_RAWIO_SPEC: {
531 struct vnode *vp;
532 enum kauth_device_req req;
533
534 req = (enum kauth_device_req)arg0;
535 vp = arg1;
536
537 KASSERT(vp != NULL);
538
539 /* Handle /dev/mem and /dev/kmem. */
540 if (iskmemvp(vp)) {
541 switch (req) {
542 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
543 break;
544
545 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
546 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
547 if (securelevel > 0)
548 result = KAUTH_RESULT_DENY;
549
550 break;
551
552 default:
553 break;
554 }
555
556 break;
557 }
558
559 switch (req) {
560 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
561 break;
562
563 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
564 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
565 int error;
566
567 error = rawdev_mounted(vp, NULL);
568
569 /* Not a disk. */
570 if (error == EINVAL)
571 break;
572
573 if (error && securelevel > 0)
574 result = KAUTH_RESULT_DENY;
575
576 if (securelevel > 1)
577 result = KAUTH_RESULT_DENY;
578
579 break;
580 }
581
582 default:
583 break;
584 }
585
586 break;
587 }
588
589 case KAUTH_DEVICE_RAWIO_PASSTHRU:
590 if (securelevel > 0) {
591 u_long bits;
592
593 bits = (u_long)arg0;
594
595 KASSERT(bits != 0);
596 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
597
598 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
599 result = KAUTH_RESULT_DENY;
600 }
601
602 break;
603
604 case KAUTH_DEVICE_GPIO_PINSET:
605 if (securelevel > 0)
606 result = KAUTH_RESULT_DENY;
607 break;
608
609 case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
610 if (securelevel > 0)
611 result = KAUTH_RESULT_DENY;
612 break;
613
614 default:
615 break;
616 }
617
618 return (result);
619 }
620
621 int
622 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
623 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
624 {
625 int result;
626
627 result = KAUTH_RESULT_DEFER;
628
629 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
630 (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
631 if (securelevel > 0)
632 result = KAUTH_RESULT_DENY;
633 }
634
635 return (result);
636 }
637
638