xref: /netbsd-src/sys/secmodel/securelevel/secmodel_securelevel.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /* $NetBSD: secmodel_securelevel.c,v 1.31 2018/04/26 18:54:09 alnsn Exp $ */
2 /*-
3  * Copyright (c) 2006 Elad Efrat <elad@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.31 2018/04/26 18:54:09 alnsn 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, "models", NULL,
103 		       NULL, 0, NULL, 0,
104 		       CTL_SECURITY, CTL_CREATE, CTL_EOL);
105 
106 	/* Compatibility: security.models.bsd44 */
107 	rnode2 = rnode;
108 	sysctl_createv(clog, 0, &rnode2, &rnode2,
109 		       CTLFLAG_PERMANENT,
110 		       CTLTYPE_NODE, "bsd44", NULL,
111 		       NULL, 0, NULL, 0,
112 		       CTL_CREATE, CTL_EOL);
113 
114         /* Compatibility: security.models.bsd44.securelevel */
115 	sysctl_createv(clog, 0, &rnode2, NULL,
116 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
117 		       CTLTYPE_INT, "securelevel",
118 		       SYSCTL_DESCR("System security level"),
119 		       secmodel_securelevel_sysctl, 0, NULL, 0,
120 		       CTL_CREATE, CTL_EOL);
121 
122 	sysctl_createv(clog, 0, &rnode, &rnode,
123 		       CTLFLAG_PERMANENT,
124 		       CTLTYPE_NODE, "securelevel", NULL,
125 		       NULL, 0, NULL, 0,
126 		       CTL_CREATE, CTL_EOL);
127 
128 	sysctl_createv(clog, 0, &rnode, NULL,
129 		       CTLFLAG_PERMANENT,
130 		       CTLTYPE_STRING, "name", NULL,
131 		       NULL, 0, __UNCONST(SECMODEL_SECURELEVEL_NAME), 0,
132 		       CTL_CREATE, CTL_EOL);
133 
134 	sysctl_createv(clog, 0, &rnode, NULL,
135 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
136 		       CTLTYPE_INT, "securelevel",
137 		       SYSCTL_DESCR("System security level"),
138 		       secmodel_securelevel_sysctl, 0, NULL, 0,
139 		       CTL_CREATE, CTL_EOL);
140 
141 	/* Compatibility: kern.securelevel */
142 
143 	sysctl_createv(clog, 0, NULL, NULL,
144 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
145 		       CTLTYPE_INT, "securelevel",
146 		       SYSCTL_DESCR("System security level"),
147 		       secmodel_securelevel_sysctl, 0, NULL, 0,
148 		       CTL_KERN, KERN_SECURELVL, CTL_EOL);
149 }
150 
151 void
152 secmodel_securelevel_init(void)
153 {
154 #ifdef INSECURE
155 	securelevel = -1;
156 #else
157 	securelevel = 0;
158 #endif /* INSECURE */
159 }
160 
161 void
162 secmodel_securelevel_start(void)
163 {
164 	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
165 	    secmodel_securelevel_system_cb, NULL);
166 	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
167 	    secmodel_securelevel_process_cb, NULL);
168 	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
169 	    secmodel_securelevel_network_cb, NULL);
170 	l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
171 	    secmodel_securelevel_machdep_cb, NULL);
172 	l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
173 	    secmodel_securelevel_device_cb, NULL);
174 	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
175 	    secmodel_securelevel_vnode_cb, NULL);
176 }
177 
178 void
179 secmodel_securelevel_stop(void)
180 {
181 	kauth_unlisten_scope(l_system);
182 	kauth_unlisten_scope(l_process);
183 	kauth_unlisten_scope(l_network);
184 	kauth_unlisten_scope(l_machdep);
185 	kauth_unlisten_scope(l_device);
186 	kauth_unlisten_scope(l_vnode);
187 }
188 
189 static int
190 securelevel_eval(const char *what, void *arg, void *ret)
191 {
192 	int error = 0;
193 
194 	if (strcasecmp(what, "is-securelevel-above") == 0) {
195 		int level = (int)(uintptr_t)arg;
196 		bool *bp = ret;
197 
198 		*bp = (securelevel > level);
199 	} else {
200 		error = ENOENT;
201 	}
202 
203 	return error;
204 }
205 
206 static int
207 securelevel_modcmd(modcmd_t cmd, void *arg)
208 {
209 	int error = 0;
210 
211 	switch (cmd) {
212 	case MODULE_CMD_INIT:
213 		secmodel_securelevel_init();
214 		error = secmodel_register(&securelevel_sm,
215 		    SECMODEL_SECURELEVEL_ID, SECMODEL_SECURELEVEL_NAME,
216 		    NULL, securelevel_eval, NULL);
217 		if (error != 0)
218 			printf("securelevel_modcmd::init: secmodel_register "
219 			    "returned %d\n", error);
220 
221 		secmodel_securelevel_start();
222 		sysctl_security_securelevel_setup(&securelevel_sysctl_log);
223 		break;
224 
225 	case MODULE_CMD_FINI:
226 		sysctl_teardown(&securelevel_sysctl_log);
227 		secmodel_securelevel_stop();
228 
229 		error = secmodel_deregister(securelevel_sm);
230 		if (error != 0)
231 			printf("securelevel_modcmd::fini: secmodel_deregister "
232 			    "returned %d\n", error);
233 
234 		break;
235 
236 	case MODULE_CMD_AUTOUNLOAD:
237 		error = EPERM;
238 		break;
239 
240 	default:
241 		error = ENOTTY;
242 		break;
243 	}
244 
245 	return (error);
246 }
247 
248 /*
249  * kauth(9) listener
250  *
251  * Security model: Traditional NetBSD
252  * Scope: System
253  * Responsibility: Securelevel
254  */
255 int
256 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action,
257     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
258 {
259 	int result;
260 	enum kauth_system_req req;
261 
262 	result = KAUTH_RESULT_DEFER;
263 	req = (enum kauth_system_req)arg0;
264 
265 	switch (action) {
266 	case KAUTH_SYSTEM_CHSYSFLAGS:
267 		/* Deprecated. */
268 		if (securelevel > 0)
269 			result = KAUTH_RESULT_DENY;
270 		break;
271 
272 	case KAUTH_SYSTEM_TIME:
273 		switch (req) {
274 		case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
275 			if (securelevel > 0)
276 				result = KAUTH_RESULT_DENY;
277 			break;
278 
279 		case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
280 			struct timespec *ts = arg1;
281 			struct timespec *delta = arg2;
282 
283 			if (securelevel > 1 && time_wraps(ts, delta))
284 				result = KAUTH_RESULT_DENY;
285 
286 			break;
287 		}
288 
289 		default:
290 			break;
291 		}
292 		break;
293 
294 	case KAUTH_SYSTEM_MAP_VA_ZERO:
295 		if (securelevel > 0)
296 			result = KAUTH_RESULT_DENY;
297 		break;
298 
299 	case KAUTH_SYSTEM_MODULE:
300 		if (securelevel > 0)
301 			result = KAUTH_RESULT_DENY;
302 		break;
303 
304 	case KAUTH_SYSTEM_MOUNT:
305 		switch (req) {
306 		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
307 			if (securelevel > 1)
308 				result = KAUTH_RESULT_DENY;
309 
310 			break;
311 
312 		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
313 			if (securelevel > 1) {
314 				struct mount *mp = arg1;
315 				u_long flags = (u_long)arg2;
316 
317 				/* Can only degrade from read/write to read-only. */
318 				if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
319 				    MNT_FORCE | MNT_UPDATE))
320 					result = KAUTH_RESULT_DENY;
321 			}
322 
323 			break;
324 
325 		default:
326 			break;
327 		}
328 
329 		break;
330 
331 	case KAUTH_SYSTEM_SYSCTL:
332 		switch (req) {
333 		case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
334 		case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
335 		case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
336 			if (securelevel > 0)
337 				result = KAUTH_RESULT_DENY;
338 			break;
339 
340 		default:
341 			break;
342 		}
343 		break;
344 
345 	case KAUTH_SYSTEM_SETIDCORE:
346 		if (securelevel > 0)
347 			result = KAUTH_RESULT_DENY;
348 		break;
349 
350 	case KAUTH_SYSTEM_DEBUG:
351 		switch (req) {
352 		case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
353 			if (securelevel > 0)
354 				result = KAUTH_RESULT_DENY;
355 			break;
356 
357 		default:
358 			break;
359 		}
360 		break;
361 
362 	default:
363 		break;
364 	}
365 
366 	return (result);
367 }
368 
369 /*
370  * kauth(9) listener
371  *
372  * Security model: Traditional NetBSD
373  * Scope: Process
374  * Responsibility: Securelevel
375  */
376 int
377 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action,
378     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
379 {
380 	struct proc *p;
381 	int result;
382 
383 	result = KAUTH_RESULT_DEFER;
384 	p = arg0;
385 
386 	switch (action) {
387 	case KAUTH_PROCESS_PROCFS: {
388 		enum kauth_process_req req;
389 
390 		req = (enum kauth_process_req)arg2;
391 		switch (req) {
392 		case KAUTH_REQ_PROCESS_PROCFS_READ:
393 			break;
394 
395 		case KAUTH_REQ_PROCESS_PROCFS_RW:
396 		case KAUTH_REQ_PROCESS_PROCFS_WRITE:
397 			if ((p == initproc) && (securelevel > -1))
398 				result = KAUTH_RESULT_DENY;
399 
400 			break;
401 
402 		default:
403 			break;
404 		}
405 
406 		break;
407 		}
408 
409 	case KAUTH_PROCESS_PTRACE:
410 		if ((p == initproc) && (securelevel > -1))
411 			result = KAUTH_RESULT_DENY;
412 
413 		break;
414 
415 	case KAUTH_PROCESS_CORENAME:
416 		if (securelevel > 1)
417 			result = KAUTH_RESULT_DENY;
418 		break;
419 
420 	default:
421 		break;
422 	}
423 
424 	return (result);
425 }
426 
427 /*
428  * kauth(9) listener
429  *
430  * Security model: Traditional NetBSD
431  * Scope: Network
432  * Responsibility: Securelevel
433  */
434 int
435 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action,
436     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
437 {
438 	int result;
439 	enum kauth_network_req req;
440 
441 	result = KAUTH_RESULT_DEFER;
442 	req = (enum kauth_network_req)arg0;
443 
444 	switch (action) {
445 	case KAUTH_NETWORK_FIREWALL:
446 		switch (req) {
447 		case KAUTH_REQ_NETWORK_FIREWALL_FW:
448 		case KAUTH_REQ_NETWORK_FIREWALL_NAT:
449 			if (securelevel > 1)
450 				result = KAUTH_RESULT_DENY;
451 			break;
452 
453 		default:
454 			break;
455 		}
456 		break;
457 
458 	case KAUTH_NETWORK_FORWSRCRT:
459 		if (securelevel > 0)
460 			result = KAUTH_RESULT_DENY;
461 		break;
462 
463 	default:
464 		break;
465 	}
466 
467 	return (result);
468 }
469 
470 /*
471  * kauth(9) listener
472  *
473  * Security model: Traditional NetBSD
474  * Scope: Machdep
475  * Responsibility: Securelevel
476  */
477 int
478 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action,
479     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
480 {
481 	int result;
482 
483 	result = KAUTH_RESULT_DEFER;
484 
485 	switch (action) {
486 	case KAUTH_MACHDEP_IOPERM_SET:
487 	case KAUTH_MACHDEP_IOPL:
488 		if (securelevel > 0)
489 			result = KAUTH_RESULT_DENY;
490 		break;
491 
492 	case KAUTH_MACHDEP_UNMANAGEDMEM:
493 		if (securelevel > 0)
494 			result = KAUTH_RESULT_DENY;
495 		break;
496 
497 	case KAUTH_MACHDEP_SVS_DISABLE:
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