Home | History | Annotate | Line # | Download | only in suser
secmodel_suser.c revision 1.22
      1 /* $NetBSD: secmodel_suser.c,v 1.22 2009/10/03 02:01:12 elad 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 superuser access restrictions.
     32  *
     33  * There are two main resources a request can be issued to: user-owned and
     34  * system owned. For the first, traditional Unix access checks are done, as
     35  * well as superuser checks. If needed, the request context is examined before
     36  * a decision is made. For the latter, usually only superuser checks are done
     37  * as normal users are not allowed to access system resources.
     38  */
     39 
     40 #include <sys/cdefs.h>
     41 __KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.22 2009/10/03 02:01:12 elad Exp $");
     42 
     43 #include <sys/types.h>
     44 #include <sys/param.h>
     45 #include <sys/kauth.h>
     46 
     47 #include <sys/mutex.h>
     48 #include <sys/mount.h>
     49 #include <sys/socketvar.h>
     50 #include <sys/sysctl.h>
     51 #include <sys/vnode.h>
     52 #include <sys/proc.h>
     53 #include <sys/uidinfo.h>
     54 #include <sys/module.h>
     55 
     56 #include <miscfs/procfs/procfs.h>
     57 
     58 #include <secmodel/suser/suser.h>
     59 
     60 MODULE(MODULE_CLASS_SECMODEL, suser, NULL);
     61 
     62 static int secmodel_suser_curtain;
     63 /* static */ int dovfsusermount;
     64 
     65 static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep,
     66     l_device, l_vnode;
     67 
     68 static struct sysctllog *suser_sysctl_log;
     69 
     70 void
     71 sysctl_security_suser_setup(struct sysctllog **clog)
     72 {
     73 	const struct sysctlnode *rnode;
     74 
     75 	sysctl_createv(clog, 0, NULL, &rnode,
     76 		       CTLFLAG_PERMANENT,
     77 		       CTLTYPE_NODE, "security", NULL,
     78 		       NULL, 0, NULL, 0,
     79 		       CTL_SECURITY, CTL_EOL);
     80 
     81 	sysctl_createv(clog, 0, &rnode, &rnode,
     82 		       CTLFLAG_PERMANENT,
     83 		       CTLTYPE_NODE, "models", NULL,
     84 		       NULL, 0, NULL, 0,
     85 		       CTL_CREATE, CTL_EOL);
     86 
     87 	sysctl_createv(clog, 0, &rnode, &rnode,
     88 		       CTLFLAG_PERMANENT,
     89 		       CTLTYPE_NODE, "suser", NULL,
     90 		       NULL, 0, NULL, 0,
     91 		       CTL_CREATE, CTL_EOL);
     92 
     93 	sysctl_createv(clog, 0, &rnode, NULL,
     94 		       CTLFLAG_PERMANENT,
     95 		       CTLTYPE_STRING, "name", NULL,
     96 		       NULL, 0, __UNCONST("Traditional NetBSD: Superuser"), 0,
     97 		       CTL_CREATE, CTL_EOL);
     98 
     99 	sysctl_createv(clog, 0, &rnode, NULL,
    100 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    101 		       CTLTYPE_INT, "curtain",
    102 		       SYSCTL_DESCR("Curtain information about objects to "\
    103 		       		    "users not owning them."),
    104 		       NULL, 0, &secmodel_suser_curtain, 0,
    105 		       CTL_CREATE, CTL_EOL);
    106 
    107 	sysctl_createv(clog, 0, &rnode, NULL,
    108 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    109 		       CTLTYPE_INT, "usermount",
    110 		       SYSCTL_DESCR("Whether unprivileged users may mount "
    111 				    "filesystems"),
    112 		       NULL, 0, &dovfsusermount, 0,
    113 		       CTL_CREATE, CTL_EOL);
    114 
    115 	/* Compatibility: security.curtain */
    116 	sysctl_createv(clog, 0, NULL, &rnode,
    117 		       CTLFLAG_PERMANENT,
    118 		       CTLTYPE_NODE, "security", NULL,
    119 		       NULL, 0, NULL, 0,
    120 		       CTL_SECURITY, CTL_EOL);
    121 
    122 	sysctl_createv(clog, 0, &rnode, NULL,
    123 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    124 		       CTLTYPE_INT, "curtain",
    125 		       SYSCTL_DESCR("Curtain information about objects to "\
    126 		       		    "users not owning them."),
    127 		       NULL, 0, &secmodel_suser_curtain, 0,
    128 		       CTL_CREATE, CTL_EOL);
    129 
    130 	/* Compatibility: vfs.generic.usermount */
    131 	sysctl_createv(clog, 0, NULL, NULL,
    132 		       CTLFLAG_PERMANENT,
    133 		       CTLTYPE_NODE, "vfs", NULL,
    134 		       NULL, 0, NULL, 0,
    135 		       CTL_VFS, CTL_EOL);
    136 
    137 	sysctl_createv(clog, 0, NULL, NULL,
    138 		       CTLFLAG_PERMANENT,
    139 		       CTLTYPE_NODE, "generic",
    140 		       SYSCTL_DESCR("Non-specific vfs related information"),
    141 		       NULL, 0, NULL, 0,
    142 		       CTL_VFS, VFS_GENERIC, CTL_EOL);
    143 
    144 	sysctl_createv(clog, 0, NULL, NULL,
    145 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    146 		       CTLTYPE_INT, "usermount",
    147 		       SYSCTL_DESCR("Whether unprivileged users may mount "
    148 				    "filesystems"),
    149 		       NULL, 0, &dovfsusermount, 0,
    150 		       CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);
    151 }
    152 
    153 void
    154 secmodel_suser_init(void)
    155 {
    156 	secmodel_suser_curtain = 0;
    157 	dovfsusermount = 0;
    158 }
    159 
    160 void
    161 secmodel_suser_start(void)
    162 {
    163 	l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC,
    164 	    secmodel_suser_generic_cb, NULL);
    165 	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
    166 	    secmodel_suser_system_cb, NULL);
    167 	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
    168 	    secmodel_suser_process_cb, NULL);
    169 	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
    170 	    secmodel_suser_network_cb, NULL);
    171 	l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
    172 	    secmodel_suser_machdep_cb, NULL);
    173 	l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
    174 	    secmodel_suser_device_cb, NULL);
    175 	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
    176 	    secmodel_suser_vnode_cb, NULL);
    177 }
    178 
    179 void
    180 secmodel_suser_stop(void)
    181 {
    182 	kauth_unlisten_scope(l_generic);
    183 	kauth_unlisten_scope(l_system);
    184 	kauth_unlisten_scope(l_process);
    185 	kauth_unlisten_scope(l_network);
    186 	kauth_unlisten_scope(l_machdep);
    187 	kauth_unlisten_scope(l_device);
    188 	kauth_unlisten_scope(l_vnode);
    189 }
    190 
    191 static int
    192 suser_modcmd(modcmd_t cmd, void *arg)
    193 {
    194 	int error = 0;
    195 
    196 	switch (cmd) {
    197 	case MODULE_CMD_INIT:
    198 		secmodel_suser_init();
    199 		secmodel_suser_start();
    200 		sysctl_security_suser_setup(&suser_sysctl_log);
    201 		break;
    202 
    203 	case MODULE_CMD_FINI:
    204 		sysctl_teardown(&suser_sysctl_log);
    205 		secmodel_suser_stop();
    206 		break;
    207 
    208 	case MODULE_CMD_AUTOUNLOAD:
    209 		error = EPERM;
    210 		break;
    211 
    212 	default:
    213 		error = ENOTTY;
    214 		break;
    215 	}
    216 
    217 	return (error);
    218 }
    219 
    220 /*
    221  * kauth(9) listener
    222  *
    223  * Security model: Traditional NetBSD
    224  * Scope: Generic
    225  * Responsibility: Superuser access
    226  */
    227 int
    228 secmodel_suser_generic_cb(kauth_cred_t cred, kauth_action_t action,
    229     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    230 {
    231 	bool isroot;
    232 	int result;
    233 
    234 	isroot = (kauth_cred_geteuid(cred) == 0);
    235 	result = KAUTH_RESULT_DEFER;
    236 
    237 	switch (action) {
    238 	case KAUTH_GENERIC_ISSUSER:
    239 		if (isroot)
    240 			result = KAUTH_RESULT_ALLOW;
    241 		break;
    242 
    243 	case KAUTH_GENERIC_CANSEE:
    244 		if (!secmodel_suser_curtain)
    245 			result = KAUTH_RESULT_ALLOW;
    246 		else if (isroot || kauth_cred_uidmatch(cred, arg0))
    247 			result = KAUTH_RESULT_ALLOW;
    248 
    249 		break;
    250 
    251 	default:
    252 		break;
    253 	}
    254 
    255 	return (result);
    256 }
    257 
    258 /*
    259  * kauth(9) listener
    260  *
    261  * Security model: Traditional NetBSD
    262  * Scope: System
    263  * Responsibility: Superuser access
    264  */
    265 int
    266 secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
    267     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    268 {
    269 	bool isroot;
    270 	int result;
    271 	enum kauth_system_req req;
    272 
    273 	isroot = (kauth_cred_geteuid(cred) == 0);
    274 	result = KAUTH_RESULT_DEFER;
    275 	req = (enum kauth_system_req)arg0;
    276 
    277 	switch (action) {
    278 	case KAUTH_SYSTEM_CPU:
    279 		switch (req) {
    280 		case KAUTH_REQ_SYSTEM_CPU_SETSTATE:
    281 			if (isroot)
    282 				result = KAUTH_RESULT_ALLOW;
    283 
    284 			break;
    285 
    286 		default:
    287 			break;
    288 		}
    289 
    290 		break;
    291 
    292 	case KAUTH_SYSTEM_FS_QUOTA:
    293 		switch (req) {
    294 		case KAUTH_REQ_SYSTEM_FS_QUOTA_GET:
    295 		case KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF:
    296 		case KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE:
    297 		case KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT:
    298 			if (isroot)
    299 				result = KAUTH_RESULT_ALLOW;
    300 			break;
    301 
    302 		default:
    303 			break;
    304 		}
    305 
    306 		break;
    307 
    308 	case KAUTH_SYSTEM_FS_RESERVEDSPACE:
    309 		if (isroot)
    310 			result = KAUTH_RESULT_ALLOW;
    311 		break;
    312 
    313 	case KAUTH_SYSTEM_MOUNT:
    314 		switch (req) {
    315 		case KAUTH_REQ_SYSTEM_MOUNT_GET:
    316 			result = KAUTH_RESULT_ALLOW;
    317 			break;
    318 
    319 		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
    320 			if (isroot)
    321 				result = KAUTH_RESULT_ALLOW;
    322 			else if (dovfsusermount) {
    323 				struct vnode *vp = arg1;
    324 				u_long flags = (u_long)arg2;
    325 
    326 				if (!(flags & MNT_NODEV) ||
    327 				    !(flags & MNT_NOSUID))
    328 					break;
    329 
    330 				if ((vp->v_mount->mnt_flag & MNT_NOEXEC) &&
    331 				    !(flags & MNT_NOEXEC))
    332 					break;
    333 
    334 				result = KAUTH_RESULT_ALLOW;
    335 			}
    336 
    337 			break;
    338 
    339 		case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
    340 			if (isroot)
    341 				result = KAUTH_RESULT_ALLOW;
    342 			else {
    343 				struct mount *mp = arg1;
    344 
    345 				if (mp->mnt_stat.f_owner ==
    346 				    kauth_cred_geteuid(cred))
    347 					result = KAUTH_RESULT_ALLOW;
    348 			}
    349 
    350 			break;
    351 
    352 		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
    353 			if (isroot)
    354 				result = KAUTH_RESULT_ALLOW;
    355 			else if (dovfsusermount) {
    356 				struct mount *mp = arg1;
    357 				u_long flags = (u_long)arg2;
    358 
    359 				/* No exporting for non-root. */
    360 				if (flags & MNT_EXPORTED)
    361 					break;
    362 
    363 				if (!(flags & MNT_NODEV) ||
    364 				    !(flags & MNT_NOSUID))
    365 					break;
    366 
    367 				/*
    368 				 * Only super-user, or user that did the mount,
    369 				 * can update.
    370 				 */
    371 				if (mp->mnt_stat.f_owner !=
    372 				    kauth_cred_geteuid(cred))
    373 					break;
    374 
    375 				/* Retain 'noexec'. */
    376 				if ((mp->mnt_flag & MNT_NOEXEC) &&
    377 				    !(flags & MNT_NOEXEC))
    378 					break;
    379 
    380 				result = KAUTH_RESULT_ALLOW;
    381 			}
    382 
    383 			break;
    384 
    385 		default:
    386 			break;
    387 		}
    388 
    389 		break;
    390 
    391 	case KAUTH_SYSTEM_PSET:
    392 		switch (req) {
    393 		case KAUTH_REQ_SYSTEM_PSET_ASSIGN:
    394 		case KAUTH_REQ_SYSTEM_PSET_BIND:
    395 		case KAUTH_REQ_SYSTEM_PSET_CREATE:
    396 		case KAUTH_REQ_SYSTEM_PSET_DESTROY:
    397 			if (isroot)
    398 				result = KAUTH_RESULT_ALLOW;
    399 
    400 			break;
    401 
    402 		default:
    403 			break;
    404 		}
    405 
    406 		break;
    407 
    408 	case KAUTH_SYSTEM_TIME:
    409 		switch (req) {
    410 		case KAUTH_REQ_SYSTEM_TIME_ADJTIME:
    411 		case KAUTH_REQ_SYSTEM_TIME_NTPADJTIME:
    412 		case KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS:
    413 		case KAUTH_REQ_SYSTEM_TIME_SYSTEM:
    414 		case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
    415 			if (isroot)
    416 				result = KAUTH_RESULT_ALLOW;
    417 			break;
    418 
    419 		default:
    420 			break;
    421 		}
    422 		break;
    423 
    424 	case KAUTH_SYSTEM_SYSCTL:
    425 		switch (req) {
    426 		case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
    427 		case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
    428 		case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
    429 		case KAUTH_REQ_SYSTEM_SYSCTL_MODIFY:
    430 		case KAUTH_REQ_SYSTEM_SYSCTL_PRVT:
    431 			if (isroot)
    432 				result = KAUTH_RESULT_ALLOW;
    433 			break;
    434 
    435 		default:
    436 			break;
    437 		}
    438 
    439 		break;
    440 
    441 	case KAUTH_SYSTEM_SWAPCTL:
    442 	case KAUTH_SYSTEM_ACCOUNTING:
    443 	case KAUTH_SYSTEM_REBOOT:
    444 	case KAUTH_SYSTEM_CHROOT:
    445 	case KAUTH_SYSTEM_FILEHANDLE:
    446 	case KAUTH_SYSTEM_MKNOD:
    447 		if (isroot)
    448 			result = KAUTH_RESULT_ALLOW;
    449 		break;
    450 
    451 	case KAUTH_SYSTEM_CHSYSFLAGS:
    452 		/*
    453 		 * Needs to be checked in conjunction with the immutable and
    454 		 * append-only flags (usually). Should be handled differently.
    455 		 * Infects ufs, ext2fs, tmpfs, and rump.
    456 		 */
    457 		if (isroot)
    458 			result = KAUTH_RESULT_ALLOW;
    459 
    460 		break;
    461 
    462 	case KAUTH_SYSTEM_SETIDCORE:
    463 		if (isroot)
    464 			result = KAUTH_RESULT_ALLOW;
    465 
    466 		break;
    467 
    468 	case KAUTH_SYSTEM_MODULE:
    469 		if (isroot)
    470 			result = KAUTH_RESULT_ALLOW;
    471 
    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: Process
    486  * Responsibility: Superuser access
    487  */
    488 int
    489 secmodel_suser_process_cb(kauth_cred_t cred, kauth_action_t action,
    490     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    491 {
    492 	struct proc *p;
    493 	bool isroot;
    494 	int result;
    495 
    496 	isroot = (kauth_cred_geteuid(cred) == 0);
    497 	result = KAUTH_RESULT_DEFER;
    498 	p = arg0;
    499 
    500 	switch (action) {
    501 	case KAUTH_PROCESS_SIGNAL:
    502 		if (isroot)
    503 			result = KAUTH_RESULT_ALLOW;
    504 
    505 		break;
    506 
    507 	case KAUTH_PROCESS_CANSEE: {
    508 		unsigned long req;
    509 
    510 		req = (unsigned long)arg1;
    511 
    512 		switch (req) {
    513 		case KAUTH_REQ_PROCESS_CANSEE_ARGS:
    514 		case KAUTH_REQ_PROCESS_CANSEE_ENTRY:
    515 		case KAUTH_REQ_PROCESS_CANSEE_OPENFILES:
    516 			if (!secmodel_suser_curtain)
    517 				result = KAUTH_RESULT_ALLOW;
    518 			else if (isroot || kauth_cred_uidmatch(cred, p->p_cred))
    519 				result = KAUTH_RESULT_ALLOW;
    520 			break;
    521 
    522 		case KAUTH_REQ_PROCESS_CANSEE_ENV:
    523 			if (!isroot &&
    524 			    (kauth_cred_getuid(cred) !=
    525 			     kauth_cred_getuid(p->p_cred) ||
    526 			    kauth_cred_getuid(cred) !=
    527 			     kauth_cred_getsvuid(p->p_cred)))
    528 				break;
    529 			else
    530 				result = KAUTH_RESULT_ALLOW;
    531 
    532 			break;
    533 
    534 		default:
    535 			break;
    536 		}
    537 
    538 		break;
    539 		}
    540 
    541 	case KAUTH_PROCESS_KTRACE:
    542 		if (isroot)
    543 			result = KAUTH_RESULT_ALLOW;
    544 
    545 		break;
    546 
    547 	case KAUTH_PROCESS_PROCFS:
    548 		if (isroot)
    549 			result = KAUTH_RESULT_ALLOW;
    550 
    551 		break;
    552 
    553 	case KAUTH_PROCESS_PTRACE:
    554 		if (isroot)
    555 			result = KAUTH_RESULT_ALLOW;
    556 
    557 		break;
    558 
    559 	case KAUTH_PROCESS_CORENAME:
    560 		if (isroot || proc_uidmatch(cred, p->p_cred) == 0)
    561 			result = KAUTH_RESULT_ALLOW;
    562 
    563 		break;
    564 
    565 	case KAUTH_PROCESS_FORK: {
    566 		int lnprocs = (int)(unsigned long)arg2;
    567 
    568 		/*
    569 		 * Don't allow a nonprivileged user to use the last few
    570 		 * processes. The variable lnprocs is the current number of
    571 		 * processes, maxproc is the limit.
    572 		 */
    573 		if (__predict_false((lnprocs >= maxproc - 5) && !isroot))
    574 			break;
    575 		else
    576 			result = KAUTH_RESULT_ALLOW;
    577 
    578 		break;
    579 		}
    580 
    581 	case KAUTH_PROCESS_KEVENT_FILTER:
    582 		if (isroot)
    583 			result = KAUTH_RESULT_ALLOW;
    584 
    585 		break;
    586 
    587 	case KAUTH_PROCESS_NICE:
    588 		if (isroot)
    589 			result = KAUTH_RESULT_ALLOW;
    590 
    591 		break;
    592 
    593 	case KAUTH_PROCESS_RLIMIT: {
    594 		enum kauth_process_req req;
    595 
    596 		req = (enum kauth_process_req)(unsigned long)arg1;
    597 
    598 		switch (req) {
    599 		case KAUTH_REQ_PROCESS_RLIMIT_SET:
    600 		case KAUTH_REQ_PROCESS_RLIMIT_GET:
    601 			if (isroot)
    602 				result = KAUTH_RESULT_ALLOW;
    603 
    604 			break;
    605 
    606 		default:
    607 			break;
    608 		}
    609 
    610 		break;
    611 		}
    612 
    613 	case KAUTH_PROCESS_SCHEDULER_GETPARAM:
    614 	case KAUTH_PROCESS_SCHEDULER_SETPARAM:
    615 	case KAUTH_PROCESS_SCHEDULER_SETAFFINITY:
    616 		if (isroot)
    617 			result = KAUTH_RESULT_ALLOW;
    618 
    619 		break;
    620 
    621 	case KAUTH_PROCESS_SETID:
    622 		if (isroot)
    623 			result = KAUTH_RESULT_ALLOW;
    624 		break;
    625 
    626 	case KAUTH_PROCESS_STOPFLAG:
    627 		if (isroot || proc_uidmatch(cred, p->p_cred) == 0) {
    628 			result = KAUTH_RESULT_ALLOW;
    629 			break;
    630 		}
    631 		break;
    632 
    633 	default:
    634 		break;
    635 	}
    636 
    637 	return (result);
    638 }
    639 
    640 /*
    641  * kauth(9) listener
    642  *
    643  * Security model: Traditional NetBSD
    644  * Scope: Network
    645  * Responsibility: Superuser access
    646  */
    647 int
    648 secmodel_suser_network_cb(kauth_cred_t cred, kauth_action_t action,
    649     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    650 {
    651 	bool isroot;
    652 	int result;
    653 	enum kauth_network_req req;
    654 
    655 	isroot = (kauth_cred_geteuid(cred) == 0);
    656 	result = KAUTH_RESULT_DEFER;
    657 	req = (enum kauth_network_req)arg0;
    658 
    659 	switch (action) {
    660 	case KAUTH_NETWORK_ALTQ:
    661 		switch (req) {
    662 		case KAUTH_REQ_NETWORK_ALTQ_AFMAP:
    663 		case KAUTH_REQ_NETWORK_ALTQ_BLUE:
    664 		case KAUTH_REQ_NETWORK_ALTQ_CBQ:
    665 		case KAUTH_REQ_NETWORK_ALTQ_CDNR:
    666 		case KAUTH_REQ_NETWORK_ALTQ_CONF:
    667 		case KAUTH_REQ_NETWORK_ALTQ_FIFOQ:
    668 		case KAUTH_REQ_NETWORK_ALTQ_HFSC:
    669 		case KAUTH_REQ_NETWORK_ALTQ_JOBS:
    670 		case KAUTH_REQ_NETWORK_ALTQ_PRIQ:
    671 		case KAUTH_REQ_NETWORK_ALTQ_RED:
    672 		case KAUTH_REQ_NETWORK_ALTQ_RIO:
    673 		case KAUTH_REQ_NETWORK_ALTQ_WFQ:
    674 			if (isroot)
    675 				result = KAUTH_RESULT_ALLOW;
    676 			break;
    677 
    678 		default:
    679 			break;
    680 		}
    681 
    682 		break;
    683 
    684 	case KAUTH_NETWORK_BIND:
    685 		switch (req) {
    686 		case KAUTH_REQ_NETWORK_BIND_PORT:
    687 			result = KAUTH_RESULT_ALLOW;
    688 			break;
    689 
    690 		case KAUTH_REQ_NETWORK_BIND_PRIVPORT:
    691 			if (isroot)
    692 				result = KAUTH_RESULT_ALLOW;
    693 			break;
    694 
    695 		default:
    696 			break;
    697 		}
    698 		break;
    699 
    700 	case KAUTH_NETWORK_FORWSRCRT:
    701 		if (isroot)
    702 			result = KAUTH_RESULT_ALLOW;
    703 
    704 		break;
    705 
    706 	case KAUTH_NETWORK_INTERFACE:
    707 		switch (req) {
    708 		case KAUTH_REQ_NETWORK_INTERFACE_GETPRIV:
    709 		case KAUTH_REQ_NETWORK_INTERFACE_SETPRIV:
    710 			if (isroot)
    711 				result = KAUTH_RESULT_ALLOW;
    712 			break;
    713 
    714 		default:
    715 			break;
    716 		}
    717 		break;
    718 
    719 	case KAUTH_NETWORK_INTERFACE_PPP:
    720 		switch (req) {
    721 		case KAUTH_REQ_NETWORK_INTERFACE_PPP_ADD:
    722 			if (isroot)
    723 				result = KAUTH_RESULT_ALLOW;
    724 			break;
    725 
    726 		default:
    727 			break;
    728 		}
    729 
    730 		break;
    731 
    732 	case KAUTH_NETWORK_INTERFACE_SLIP:
    733 		switch (req) {
    734 		case KAUTH_REQ_NETWORK_INTERFACE_SLIP_ADD:
    735 			if (isroot)
    736 				result = KAUTH_RESULT_ALLOW;
    737 			break;
    738 
    739 		default:
    740 			break;
    741 		}
    742 
    743 		break;
    744 
    745 	case KAUTH_NETWORK_INTERFACE_STRIP:
    746 		switch (req) {
    747 		case KAUTH_REQ_NETWORK_INTERFACE_STRIP_ADD:
    748 			if (isroot)
    749 				result = KAUTH_RESULT_ALLOW;
    750 			break;
    751 
    752 		default:
    753 			break;
    754 		}
    755 
    756 		break;
    757 
    758 	case KAUTH_NETWORK_INTERFACE_TUN:
    759 		switch (req) {
    760 		case KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD:
    761 			if (isroot)
    762 				result = KAUTH_RESULT_ALLOW;
    763 			break;
    764 
    765 		default:
    766 			break;
    767 		}
    768 
    769 		break;
    770 
    771 	case KAUTH_NETWORK_NFS:
    772 		switch (req) {
    773 		case KAUTH_REQ_NETWORK_NFS_EXPORT:
    774 		case KAUTH_REQ_NETWORK_NFS_SVC:
    775 			if (isroot)
    776 				result = KAUTH_RESULT_ALLOW;
    777 
    778 			break;
    779 
    780 		default:
    781 			break;
    782 		}
    783 		break;
    784 
    785 	case KAUTH_NETWORK_ROUTE:
    786 		if (isroot)
    787 			result = KAUTH_RESULT_ALLOW;
    788 
    789 		break;
    790 
    791 	case KAUTH_NETWORK_SOCKET:
    792 		switch (req) {
    793 		case KAUTH_REQ_NETWORK_SOCKET_DROP:
    794 		case KAUTH_REQ_NETWORK_SOCKET_OPEN:
    795 		case KAUTH_REQ_NETWORK_SOCKET_RAWSOCK:
    796 		case KAUTH_REQ_NETWORK_SOCKET_SETPRIV:
    797 			if (isroot)
    798 				result = KAUTH_RESULT_ALLOW;
    799 			break;
    800 
    801 		case KAUTH_REQ_NETWORK_SOCKET_CANSEE:
    802 			if (isroot) {
    803 				result = KAUTH_RESULT_ALLOW;
    804 				break;
    805 			}
    806 
    807 			if (secmodel_suser_curtain) {
    808 				struct socket *so;
    809 				uid_t so_uid;
    810 
    811 				so = (struct socket *)arg1;
    812 				so_uid = so->so_uidinfo->ui_uid;
    813 				if (kauth_cred_geteuid(cred) != so_uid)
    814 					result = KAUTH_RESULT_DENY;
    815 			}
    816 
    817 			break;
    818 
    819 		default:
    820 			break;
    821 		}
    822 
    823 		break;
    824 
    825 
    826 	default:
    827 		break;
    828 	}
    829 
    830 	return (result);
    831 }
    832 
    833 /*
    834  * kauth(9) listener
    835  *
    836  * Security model: Traditional NetBSD
    837  * Scope: Machdep
    838  * Responsibility: Superuser access
    839  */
    840 int
    841 secmodel_suser_machdep_cb(kauth_cred_t cred, kauth_action_t action,
    842     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    843 {
    844         bool isroot;
    845         int result;
    846 
    847         isroot = (kauth_cred_geteuid(cred) == 0);
    848         result = KAUTH_RESULT_DEFER;
    849 
    850         switch (action) {
    851 	case KAUTH_MACHDEP_IOPERM_GET:
    852 	case KAUTH_MACHDEP_LDT_GET:
    853 	case KAUTH_MACHDEP_LDT_SET:
    854 	case KAUTH_MACHDEP_MTRR_GET:
    855 		result = KAUTH_RESULT_ALLOW;
    856 		break;
    857 
    858 	case KAUTH_MACHDEP_CACHEFLUSH:
    859 	case KAUTH_MACHDEP_IOPERM_SET:
    860 	case KAUTH_MACHDEP_IOPL:
    861 	case KAUTH_MACHDEP_MTRR_SET:
    862 	case KAUTH_MACHDEP_NVRAM:
    863 	case KAUTH_MACHDEP_UNMANAGEDMEM:
    864 		if (isroot)
    865 			result = KAUTH_RESULT_ALLOW;
    866 		break;
    867 
    868 	default:
    869 		break;
    870 	}
    871 
    872 	return (result);
    873 }
    874 
    875 /*
    876  * kauth(9) listener
    877  *
    878  * Security model: Traditional NetBSD
    879  * Scope: Device
    880  * Responsibility: Superuser access
    881  */
    882 int
    883 secmodel_suser_device_cb(kauth_cred_t cred, kauth_action_t action,
    884     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    885 {
    886         bool isroot;
    887         int result;
    888 
    889         isroot = (kauth_cred_geteuid(cred) == 0);
    890         result = KAUTH_RESULT_DEFER;
    891 
    892 	switch (action) {
    893 	case KAUTH_DEVICE_BLUETOOTH_SETPRIV:
    894 	case KAUTH_DEVICE_BLUETOOTH_SEND:
    895 	case KAUTH_DEVICE_BLUETOOTH_RECV:
    896 		if (isroot)
    897 			result = KAUTH_RESULT_ALLOW;
    898 		break;
    899 
    900 	case KAUTH_DEVICE_BLUETOOTH_BCSP:
    901 	case KAUTH_DEVICE_BLUETOOTH_BTUART: {
    902 		enum kauth_device_req req;
    903 
    904 		req = (enum kauth_device_req)arg0;
    905 		switch (req) {
    906 		case KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD:
    907 		case KAUTH_REQ_DEVICE_BLUETOOTH_BTUART_ADD:
    908 			if (isroot)
    909 				result = KAUTH_RESULT_ALLOW;
    910 			break;
    911 
    912 		default:
    913 			break;
    914 		}
    915 
    916 		break;
    917 		}
    918 
    919 	case KAUTH_DEVICE_RAWIO_SPEC:
    920 	case KAUTH_DEVICE_RAWIO_PASSTHRU:
    921 		/*
    922 		 * Decision is root-agnostic.
    923 		 *
    924 		 * Both requests can be issued on devices subject to their
    925 		 * permission bits.
    926 		 */
    927 		result = KAUTH_RESULT_ALLOW;
    928 		break;
    929 
    930 	case KAUTH_DEVICE_TTY_OPEN:
    931 		if (isroot)
    932 			result = KAUTH_RESULT_ALLOW;
    933 
    934 		break;
    935 
    936 	case KAUTH_DEVICE_TTY_PRIVSET:
    937 		if (isroot)
    938 			result = KAUTH_RESULT_ALLOW;
    939 
    940 		break;
    941 
    942 	case KAUTH_DEVICE_TTY_STI:
    943 		if (isroot)
    944 			result = KAUTH_RESULT_ALLOW;
    945 
    946 		break;
    947 
    948 	case KAUTH_DEVICE_RND_ADDDATA:
    949 	case KAUTH_DEVICE_RND_GETPRIV:
    950 	case KAUTH_DEVICE_RND_SETPRIV:
    951 		if (isroot)
    952 			result = KAUTH_RESULT_ALLOW;
    953 		break;
    954 
    955 	case KAUTH_DEVICE_GPIO_PINSET:
    956 		/*
    957 		 * root can access gpio pins, secmodel_securlevel can veto
    958 		 * this decision.
    959 		 */
    960 		if (isroot)
    961 			result = KAUTH_RESULT_ALLOW;
    962 		break;
    963 
    964 	default:
    965 		break;
    966 	}
    967 
    968 	return (result);
    969 }
    970 
    971 int
    972 secmodel_suser_vnode_cb(kauth_cred_t cred, kauth_action_t action,
    973     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
    974 {
    975 	bool isroot;
    976 	int result;
    977 
    978 	isroot = (kauth_cred_geteuid(cred) == 0);
    979 	result = KAUTH_RESULT_DEFER;
    980 
    981 	if (isroot)
    982 		result = KAUTH_RESULT_ALLOW;
    983 
    984 	return (result);
    985 }
    986 
    987