Home | History | Annotate | Line # | Download | only in securelevel
secmodel_securelevel.c revision 1.36
      1 /* $NetBSD: secmodel_securelevel.c,v 1.36 2020/05/28 23:17:25 riastradh 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.36 2020/05/28 23:17:25 riastradh 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 
     69 /*
     70  * Sysctl helper routine for securelevel. Ensures that the value only rises
     71  * unless the caller is init.
     72  */
     73 int
     74 secmodel_securelevel_sysctl(SYSCTLFN_ARGS)
     75 {
     76 	int newsecurelevel, error;
     77 	struct sysctlnode node;
     78 
     79 	newsecurelevel = securelevel;
     80 	node = *rnode;
     81 	node.sysctl_data = &newsecurelevel;
     82 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
     83 	if (error || newp == NULL)
     84 		return (error);
     85 
     86 	if ((newsecurelevel < securelevel) && (l->l_proc != initproc))
     87 		return (EPERM);
     88 
     89 	securelevel = newsecurelevel;
     90 
     91 	return (error);
     92 }
     93 
     94 SYSCTL_SETUP(sysctl_security_securelevel_setup, "securelevel sysctl")
     95 {
     96 	const struct sysctlnode *rnode, *rnode2;
     97 
     98 	sysctl_createv(clog, 0, NULL, &rnode,
     99 		       CTLFLAG_PERMANENT,
    100 		       CTLTYPE_NODE, "models", NULL,
    101 		       NULL, 0, NULL, 0,
    102 		       CTL_SECURITY, CTL_CREATE, CTL_EOL);
    103 
    104 	/* Compatibility: security.models.bsd44 */
    105 	rnode2 = rnode;
    106 	sysctl_createv(clog, 0, &rnode2, &rnode2,
    107 		       CTLFLAG_PERMANENT,
    108 		       CTLTYPE_NODE, "bsd44", NULL,
    109 		       NULL, 0, NULL, 0,
    110 		       CTL_CREATE, CTL_EOL);
    111 
    112         /* Compatibility: security.models.bsd44.securelevel */
    113 	sysctl_createv(clog, 0, &rnode2, NULL,
    114 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    115 		       CTLTYPE_INT, "securelevel",
    116 		       SYSCTL_DESCR("System security level"),
    117 		       secmodel_securelevel_sysctl, 0, NULL, 0,
    118 		       CTL_CREATE, CTL_EOL);
    119 
    120 	sysctl_createv(clog, 0, &rnode, &rnode,
    121 		       CTLFLAG_PERMANENT,
    122 		       CTLTYPE_NODE, "securelevel", NULL,
    123 		       NULL, 0, NULL, 0,
    124 		       CTL_CREATE, CTL_EOL);
    125 
    126 	sysctl_createv(clog, 0, &rnode, NULL,
    127 		       CTLFLAG_PERMANENT,
    128 		       CTLTYPE_STRING, "name", NULL,
    129 		       NULL, 0, __UNCONST(SECMODEL_SECURELEVEL_NAME), 0,
    130 		       CTL_CREATE, CTL_EOL);
    131 
    132 	sysctl_createv(clog, 0, &rnode, NULL,
    133 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    134 		       CTLTYPE_INT, "securelevel",
    135 		       SYSCTL_DESCR("System security level"),
    136 		       secmodel_securelevel_sysctl, 0, NULL, 0,
    137 		       CTL_CREATE, CTL_EOL);
    138 
    139 	/* Compatibility: kern.securelevel */
    140 
    141 	sysctl_createv(clog, 0, NULL, NULL,
    142 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    143 		       CTLTYPE_INT, "securelevel",
    144 		       SYSCTL_DESCR("System security level"),
    145 		       secmodel_securelevel_sysctl, 0, NULL, 0,
    146 		       CTL_KERN, KERN_SECURELVL, CTL_EOL);
    147 }
    148 
    149 void
    150 secmodel_securelevel_init(void)
    151 {
    152 #ifdef INSECURE
    153 	securelevel = -1;
    154 #else
    155 	securelevel = 0;
    156 #endif /* INSECURE */
    157 }
    158 
    159 void
    160 secmodel_securelevel_start(void)
    161 {
    162 	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
    163 	    secmodel_securelevel_system_cb, NULL);
    164 	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
    165 	    secmodel_securelevel_process_cb, NULL);
    166 	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
    167 	    secmodel_securelevel_network_cb, NULL);
    168 	l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
    169 	    secmodel_securelevel_machdep_cb, NULL);
    170 	l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
    171 	    secmodel_securelevel_device_cb, NULL);
    172 	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
    173 	    secmodel_securelevel_vnode_cb, NULL);
    174 }
    175 
    176 void
    177 secmodel_securelevel_stop(void)
    178 {
    179 	kauth_unlisten_scope(l_system);
    180 	kauth_unlisten_scope(l_process);
    181 	kauth_unlisten_scope(l_network);
    182 	kauth_unlisten_scope(l_machdep);
    183 	kauth_unlisten_scope(l_device);
    184 	kauth_unlisten_scope(l_vnode);
    185 }
    186 
    187 static int
    188 securelevel_eval(const char *what, void *arg, void *ret)
    189 {
    190 	int error = 0;
    191 
    192 	if (strcasecmp(what, "is-securelevel-above") == 0) {
    193 		int level = (int)(uintptr_t)arg;
    194 		bool *bp = ret;
    195 
    196 		*bp = (securelevel > level);
    197 	} else {
    198 		error = ENOENT;
    199 	}
    200 
    201 	return error;
    202 }
    203 
    204 static int
    205 securelevel_modcmd(modcmd_t cmd, void *arg)
    206 {
    207 	int error = 0;
    208 
    209 	switch (cmd) {
    210 	case MODULE_CMD_INIT:
    211 		secmodel_securelevel_init();
    212 		error = secmodel_register(&securelevel_sm,
    213 		    SECMODEL_SECURELEVEL_ID, SECMODEL_SECURELEVEL_NAME,
    214 		    NULL, securelevel_eval, NULL);
    215 		if (error != 0)
    216 			printf("securelevel_modcmd::init: secmodel_register "
    217 			    "returned %d\n", error);
    218 
    219 		secmodel_securelevel_start();
    220 		break;
    221 
    222 	case MODULE_CMD_FINI:
    223 		secmodel_securelevel_stop();
    224 
    225 		error = secmodel_deregister(securelevel_sm);
    226 		if (error != 0)
    227 			printf("securelevel_modcmd::fini: secmodel_deregister "
    228 			    "returned %d\n", error);
    229 
    230 		break;
    231 
    232 	case MODULE_CMD_AUTOUNLOAD:
    233 		error = EPERM;
    234 		break;
    235 
    236 	default:
    237 		error = ENOTTY;
    238 		break;
    239 	}
    240 
    241 	return (error);
    242 }
    243 
    244 /*
    245  * kauth(9) listener
    246  *
    247  * Security model: Traditional NetBSD
    248  * Scope: System
    249  * Responsibility: Securelevel
    250  */
    251 int
    252 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action,
    253     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    254 {
    255 	int result;
    256 	enum kauth_system_req req;
    257 
    258 	result = KAUTH_RESULT_DEFER;
    259 	req = (enum kauth_system_req)(uintptr_t)arg0;
    260 
    261 	switch (action) {
    262 	case KAUTH_SYSTEM_CHSYSFLAGS:
    263 		/* Deprecated. */
    264 		if (securelevel > 0)
    265 			result = KAUTH_RESULT_DENY;
    266 		break;
    267 
    268 	case KAUTH_SYSTEM_TIME:
    269 		switch (req) {
    270 		case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
    271 			if (securelevel > 0)
    272 				result = KAUTH_RESULT_DENY;
    273 			break;
    274 
    275 		case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
    276 			struct timespec *ts = arg1;
    277 			struct timespec *delta = arg2;
    278 
    279 			if (securelevel > 1 && time_wraps(ts, delta))
    280 				result = KAUTH_RESULT_DENY;
    281 
    282 			break;
    283 		}
    284 
    285 		default:
    286 			break;
    287 		}
    288 		break;
    289 
    290 	case KAUTH_SYSTEM_MAP_VA_ZERO:
    291 		if (securelevel > 0)
    292 			result = KAUTH_RESULT_DENY;
    293 		break;
    294 
    295 	case KAUTH_SYSTEM_MODULE:
    296 		if (securelevel > 0)
    297 			result = KAUTH_RESULT_DENY;
    298 		break;
    299 
    300 	case KAUTH_SYSTEM_MOUNT:
    301 		switch (req) {
    302 		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
    303 			if (securelevel > 1)
    304 				result = KAUTH_RESULT_DENY;
    305 
    306 			break;
    307 
    308 		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
    309 			if (securelevel > 1) {
    310 				struct mount *mp = arg1;
    311 				u_long flags = (u_long)arg2;
    312 
    313 				/* Can only degrade from read/write to read-only. */
    314 				if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
    315 				    MNT_FORCE | MNT_UPDATE))
    316 					result = KAUTH_RESULT_DENY;
    317 			}
    318 
    319 			break;
    320 
    321 		default:
    322 			break;
    323 		}
    324 
    325 		break;
    326 
    327 	case KAUTH_SYSTEM_SYSCTL:
    328 		switch (req) {
    329 		case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
    330 		case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
    331 		case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
    332 			if (securelevel > 0)
    333 				result = KAUTH_RESULT_DENY;
    334 			break;
    335 
    336 		default:
    337 			break;
    338 		}
    339 		break;
    340 
    341 	case KAUTH_SYSTEM_SETIDCORE:
    342 		if (securelevel > 0)
    343 			result = KAUTH_RESULT_DENY;
    344 		break;
    345 
    346 	case KAUTH_SYSTEM_DEBUG:
    347 	default:
    348 		break;
    349 	}
    350 
    351 	return (result);
    352 }
    353 
    354 /*
    355  * kauth(9) listener
    356  *
    357  * Security model: Traditional NetBSD
    358  * Scope: Process
    359  * Responsibility: Securelevel
    360  */
    361 int
    362 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action,
    363     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    364 {
    365 	struct proc *p;
    366 	int result;
    367 
    368 	result = KAUTH_RESULT_DEFER;
    369 	p = arg0;
    370 
    371 	switch (action) {
    372 	case KAUTH_PROCESS_PROCFS: {
    373 		enum kauth_process_req req;
    374 
    375 		req = (enum kauth_process_req)(uintptr_t)arg2;
    376 		switch (req) {
    377 		case KAUTH_REQ_PROCESS_PROCFS_READ:
    378 			break;
    379 
    380 		case KAUTH_REQ_PROCESS_PROCFS_RW:
    381 		case KAUTH_REQ_PROCESS_PROCFS_WRITE:
    382 			if ((p == initproc) && (securelevel > -1))
    383 				result = KAUTH_RESULT_DENY;
    384 
    385 			break;
    386 
    387 		default:
    388 			break;
    389 		}
    390 
    391 		break;
    392 		}
    393 
    394 	case KAUTH_PROCESS_PTRACE:
    395 		if ((p == initproc) && (securelevel > -1))
    396 			result = KAUTH_RESULT_DENY;
    397 
    398 		break;
    399 
    400 	case KAUTH_PROCESS_CORENAME:
    401 		if (securelevel > 1)
    402 			result = KAUTH_RESULT_DENY;
    403 		break;
    404 
    405 	default:
    406 		break;
    407 	}
    408 
    409 	return (result);
    410 }
    411 
    412 /*
    413  * kauth(9) listener
    414  *
    415  * Security model: Traditional NetBSD
    416  * Scope: Network
    417  * Responsibility: Securelevel
    418  */
    419 int
    420 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action,
    421     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    422 {
    423 	int result;
    424 	enum kauth_network_req req;
    425 
    426 	result = KAUTH_RESULT_DEFER;
    427 	req = (enum kauth_network_req)(uintptr_t)arg0;
    428 
    429 	switch (action) {
    430 	case KAUTH_NETWORK_FIREWALL:
    431 		switch (req) {
    432 		case KAUTH_REQ_NETWORK_FIREWALL_FW:
    433 		case KAUTH_REQ_NETWORK_FIREWALL_NAT:
    434 			if (securelevel > 1)
    435 				result = KAUTH_RESULT_DENY;
    436 			break;
    437 
    438 		default:
    439 			break;
    440 		}
    441 		break;
    442 
    443 	case KAUTH_NETWORK_FORWSRCRT:
    444 		if (securelevel > 0)
    445 			result = KAUTH_RESULT_DENY;
    446 		break;
    447 
    448 	default:
    449 		break;
    450 	}
    451 
    452 	return (result);
    453 }
    454 
    455 /*
    456  * kauth(9) listener
    457  *
    458  * Security model: Traditional NetBSD
    459  * Scope: Machdep
    460  * Responsibility: Securelevel
    461  */
    462 int
    463 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action,
    464     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    465 {
    466 	int result;
    467 
    468 	result = KAUTH_RESULT_DEFER;
    469 
    470 	switch (action) {
    471 	case KAUTH_MACHDEP_IOPERM_SET:
    472 	case KAUTH_MACHDEP_IOPL:
    473 		if (securelevel > 0)
    474 			result = KAUTH_RESULT_DENY;
    475 		break;
    476 
    477 	case KAUTH_MACHDEP_UNMANAGEDMEM:
    478 		if (securelevel > 0)
    479 			result = KAUTH_RESULT_DENY;
    480 		break;
    481 
    482 	case KAUTH_MACHDEP_SVS_DISABLE:
    483 		/* Deprecated. */
    484 		if (securelevel > 0)
    485 			result = KAUTH_RESULT_DENY;
    486 		break;
    487 
    488 	case KAUTH_MACHDEP_CPU_UCODE_APPLY:
    489 		if (securelevel > 1)
    490 			result = KAUTH_RESULT_DENY;
    491 		break;
    492 
    493 	default:
    494 		break;
    495 	}
    496 
    497 	return (result);
    498 }
    499 
    500 /*
    501  * kauth(9) listener
    502  *
    503  * Security model: Traditional NetBSD
    504  * Scope: Device
    505  * Responsibility: Securelevel
    506  */
    507 int
    508 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action,
    509     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    510 {
    511 	int result;
    512 
    513 	result = KAUTH_RESULT_DEFER;
    514 
    515 	switch (action) {
    516 	case KAUTH_DEVICE_RAWIO_SPEC: {
    517 		struct vnode *vp;
    518 		enum kauth_device_req req;
    519 
    520 		req = (enum kauth_device_req)(uintptr_t)arg0;
    521 		vp = arg1;
    522 
    523 		KASSERT(vp != NULL);
    524 
    525 		/* Handle /dev/mem and /dev/kmem. */
    526 		if (iskmemvp(vp)) {
    527 			switch (req) {
    528 			case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
    529 				break;
    530 
    531 			case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
    532 			case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
    533 				if (securelevel > 0)
    534 					result = KAUTH_RESULT_DENY;
    535 
    536 				break;
    537 
    538 			default:
    539 				break;
    540 			}
    541 
    542 			break;
    543 		}
    544 
    545 		switch (req) {
    546 		case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
    547 			break;
    548 
    549 		case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
    550 		case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
    551 			int error;
    552 
    553 			error = rawdev_mounted(vp, NULL);
    554 
    555 			/* Not a disk. */
    556 			if (error == EINVAL)
    557 				break;
    558 
    559 			if (error && securelevel > 0)
    560 				result = KAUTH_RESULT_DENY;
    561 
    562 			if (securelevel > 1)
    563 				result = KAUTH_RESULT_DENY;
    564 
    565 			break;
    566 			}
    567 
    568 		default:
    569 			break;
    570 		}
    571 
    572 		break;
    573 		}
    574 
    575 	case KAUTH_DEVICE_RAWIO_PASSTHRU:
    576 		if (securelevel > 0) {
    577 			u_long bits;
    578 
    579 			bits = (u_long)arg0;
    580 
    581 			KASSERT(bits != 0);
    582 			KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
    583 
    584 			if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
    585 				result = KAUTH_RESULT_DENY;
    586 		}
    587 
    588 		break;
    589 
    590 	case KAUTH_DEVICE_GPIO_PINSET:
    591 		if (securelevel > 0)
    592 			result = KAUTH_RESULT_DENY;
    593 		break;
    594 
    595 	case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
    596 		if (securelevel > 1)
    597 			result = KAUTH_RESULT_DENY;
    598 		break;
    599 
    600 	default:
    601 		break;
    602 	}
    603 
    604 	return (result);
    605 }
    606 
    607 int
    608 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
    609     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    610 {
    611 	int result;
    612 
    613 	result = KAUTH_RESULT_DEFER;
    614 
    615 	if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
    616 	    (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
    617 		if (securelevel > 0)
    618 			result = KAUTH_RESULT_DENY;
    619 	}
    620 
    621 	return (result);
    622 }
    623 
    624