1/* $NetBSD: secmodel_suser.c,v 1.37 2012/01/13 16:05:15 cegger 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 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.37 2012/01/13 16:05:15 cegger 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/module.h>
54
55#include <secmodel/secmodel.h>
56#include <secmodel/suser/suser.h>
57
58MODULE(MODULE_CLASS_SECMODEL, suser, NULL);
59
60static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep,
61    l_device, l_vnode;
62
63static secmodel_t suser_sm;
64static struct sysctllog *suser_sysctl_log;
65
66void
67sysctl_security_suser_setup(struct sysctllog **clog)
68{
69	const struct sysctlnode *rnode;
70
71	sysctl_createv(clog, 0, NULL, &rnode,
72		       CTLFLAG_PERMANENT,
73		       CTLTYPE_NODE, "security", NULL,
74		       NULL, 0, NULL, 0,
75		       CTL_SECURITY, CTL_EOL);
76
77	sysctl_createv(clog, 0, &rnode, &rnode,
78		       CTLFLAG_PERMANENT,
79		       CTLTYPE_NODE, "models", NULL,
80		       NULL, 0, NULL, 0,
81		       CTL_CREATE, CTL_EOL);
82
83	sysctl_createv(clog, 0, &rnode, &rnode,
84		       CTLFLAG_PERMANENT,
85		       CTLTYPE_NODE, "suser", NULL,
86		       NULL, 0, NULL, 0,
87		       CTL_CREATE, CTL_EOL);
88
89	sysctl_createv(clog, 0, &rnode, NULL,
90		       CTLFLAG_PERMANENT,
91		       CTLTYPE_STRING, "name", NULL,
92		       NULL, 0, __UNCONST(SECMODEL_SUSER_NAME), 0,
93		       CTL_CREATE, CTL_EOL);
94}
95
96void
97secmodel_suser_init(void)
98{
99
100}
101
102void
103secmodel_suser_start(void)
104{
105	l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC,
106	    secmodel_suser_generic_cb, NULL);
107	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
108	    secmodel_suser_system_cb, NULL);
109	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
110	    secmodel_suser_process_cb, NULL);
111	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
112	    secmodel_suser_network_cb, NULL);
113	l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
114	    secmodel_suser_machdep_cb, NULL);
115	l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
116	    secmodel_suser_device_cb, NULL);
117	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
118	    secmodel_suser_vnode_cb, NULL);
119}
120
121void
122secmodel_suser_stop(void)
123{
124	kauth_unlisten_scope(l_generic);
125	kauth_unlisten_scope(l_system);
126	kauth_unlisten_scope(l_process);
127	kauth_unlisten_scope(l_network);
128	kauth_unlisten_scope(l_machdep);
129	kauth_unlisten_scope(l_device);
130	kauth_unlisten_scope(l_vnode);
131}
132
133static bool
134suser_isroot(kauth_cred_t cred)
135{
136	return kauth_cred_geteuid(cred) == 0;
137}
138
139static int
140suser_eval(const char *what, void *arg, void *ret)
141{
142	int error = 0;
143
144	if (strcasecmp(what, "is-root") == 0) {
145		kauth_cred_t cred = arg;
146		bool *bp = ret;
147
148		*bp = suser_isroot(cred);
149	} else {
150		error = ENOENT;
151	}
152
153	return error;
154}
155
156static int
157suser_modcmd(modcmd_t cmd, void *arg)
158{
159	int error = 0;
160
161	switch (cmd) {
162	case MODULE_CMD_INIT:
163		error = secmodel_register(&suser_sm,
164		    SECMODEL_SUSER_ID, SECMODEL_SUSER_NAME,
165		    NULL, suser_eval, NULL);
166		if (error != 0)
167			printf("suser_modcmd::init: secmodel_register "
168			    "returned %d\n", error);
169
170		secmodel_suser_init();
171		secmodel_suser_start();
172		sysctl_security_suser_setup(&suser_sysctl_log);
173		break;
174
175	case MODULE_CMD_FINI:
176		sysctl_teardown(&suser_sysctl_log);
177		secmodel_suser_stop();
178
179		error = secmodel_deregister(suser_sm);
180		if (error != 0)
181			printf("suser_modcmd::fini: secmodel_deregister "
182			    "returned %d\n", error);
183
184		break;
185
186	case MODULE_CMD_AUTOUNLOAD:
187		error = EPERM;
188		break;
189
190	default:
191		error = ENOTTY;
192		break;
193	}
194
195	return (error);
196}
197
198/*
199 * kauth(9) listener
200 *
201 * Security model: Traditional NetBSD
202 * Scope: Generic
203 * Responsibility: Superuser access
204 */
205int
206secmodel_suser_generic_cb(kauth_cred_t cred, kauth_action_t action,
207    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
208{
209	bool isroot;
210	int result;
211
212	isroot = suser_isroot(cred);
213	result = KAUTH_RESULT_DEFER;
214
215	switch (action) {
216	case KAUTH_GENERIC_ISSUSER:
217		if (isroot)
218			result = KAUTH_RESULT_ALLOW;
219		break;
220
221	default:
222		break;
223	}
224
225	return (result);
226}
227
228/*
229 * kauth(9) listener
230 *
231 * Security model: Traditional NetBSD
232 * Scope: System
233 * Responsibility: Superuser access
234 */
235int
236secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
237    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
238{
239	bool isroot;
240	int result;
241	enum kauth_system_req req;
242
243	isroot = suser_isroot(cred);
244	result = KAUTH_RESULT_DEFER;
245	req = (enum kauth_system_req)arg0;
246
247	switch (action) {
248	case KAUTH_SYSTEM_CPU:
249		switch (req) {
250		case KAUTH_REQ_SYSTEM_CPU_SETSTATE:
251			if (isroot)
252				result = KAUTH_RESULT_ALLOW;
253
254			break;
255
256		default:
257			break;
258		}
259
260		break;
261
262	case KAUTH_SYSTEM_FS_QUOTA:
263		switch (req) {
264		case KAUTH_REQ_SYSTEM_FS_QUOTA_GET:
265		case KAUTH_REQ_SYSTEM_FS_QUOTA_ONOFF:
266		case KAUTH_REQ_SYSTEM_FS_QUOTA_MANAGE:
267		case KAUTH_REQ_SYSTEM_FS_QUOTA_NOLIMIT:
268			if (isroot)
269				result = KAUTH_RESULT_ALLOW;
270			break;
271
272		default:
273			break;
274		}
275
276		break;
277
278	case KAUTH_SYSTEM_MOUNT:
279		switch (req) {
280		case KAUTH_REQ_SYSTEM_MOUNT_GET:
281			if (isroot) {
282				result = KAUTH_RESULT_ALLOW;
283				break;
284			}
285
286			break;
287
288		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
289		case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
290		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
291			if (isroot) {
292				result = KAUTH_RESULT_ALLOW;
293				break;
294			}
295
296			break;
297
298		default:
299			break;
300		}
301
302		break;
303
304	case KAUTH_SYSTEM_PSET:
305		switch (req) {
306		case KAUTH_REQ_SYSTEM_PSET_ASSIGN:
307		case KAUTH_REQ_SYSTEM_PSET_BIND:
308		case KAUTH_REQ_SYSTEM_PSET_CREATE:
309		case KAUTH_REQ_SYSTEM_PSET_DESTROY:
310			if (isroot)
311				result = KAUTH_RESULT_ALLOW;
312
313			break;
314
315		default:
316			break;
317		}
318
319		break;
320
321	case KAUTH_SYSTEM_TIME:
322		switch (req) {
323		case KAUTH_REQ_SYSTEM_TIME_ADJTIME:
324		case KAUTH_REQ_SYSTEM_TIME_NTPADJTIME:
325		case KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS:
326		case KAUTH_REQ_SYSTEM_TIME_SYSTEM:
327		case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
328			if (isroot)
329				result = KAUTH_RESULT_ALLOW;
330			break;
331
332		default:
333			break;
334		}
335		break;
336
337	case KAUTH_SYSTEM_SYSCTL:
338		switch (req) {
339		case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
340		case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
341		case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
342		case KAUTH_REQ_SYSTEM_SYSCTL_MODIFY:
343		case KAUTH_REQ_SYSTEM_SYSCTL_PRVT:
344			if (isroot)
345				result = KAUTH_RESULT_ALLOW;
346			break;
347
348		default:
349			break;
350		}
351
352		break;
353
354	case KAUTH_SYSTEM_SWAPCTL:
355	case KAUTH_SYSTEM_ACCOUNTING:
356	case KAUTH_SYSTEM_REBOOT:
357	case KAUTH_SYSTEM_CHROOT:
358	case KAUTH_SYSTEM_FILEHANDLE:
359	case KAUTH_SYSTEM_MKNOD:
360	case KAUTH_SYSTEM_SETIDCORE:
361	case KAUTH_SYSTEM_MODULE:
362	case KAUTH_SYSTEM_FS_RESERVEDSPACE:
363		if (isroot)
364			result = KAUTH_RESULT_ALLOW;
365		break;
366
367	case KAUTH_SYSTEM_DEBUG:
368		switch (req) {
369		case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
370			if (isroot)
371				result = KAUTH_RESULT_ALLOW;
372
373			break;
374
375		default:
376			break;
377		}
378
379		break;
380
381	case KAUTH_SYSTEM_CHSYSFLAGS:
382		/*
383		 * Needs to be checked in conjunction with the immutable and
384		 * append-only flags (usually). Should be handled differently.
385		 * Infects ufs, ext2fs, tmpfs, and rump.
386		 */
387		if (isroot)
388			result = KAUTH_RESULT_ALLOW;
389
390		break;
391
392	default:
393		break;
394	}
395
396	return (result);
397}
398
399/*
400 * kauth(9) listener
401 *
402 * Security model: Traditional NetBSD
403 * Scope: Process
404 * Responsibility: Superuser access
405 */
406int
407secmodel_suser_process_cb(kauth_cred_t cred, kauth_action_t action,
408    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
409{
410	struct proc *p;
411	bool isroot;
412	int result;
413
414	isroot = suser_isroot(cred);
415	result = KAUTH_RESULT_DEFER;
416	p = arg0;
417
418	switch (action) {
419	case KAUTH_PROCESS_SIGNAL:
420	case KAUTH_PROCESS_KTRACE:
421	case KAUTH_PROCESS_PROCFS:
422	case KAUTH_PROCESS_PTRACE:
423	case KAUTH_PROCESS_SCHEDULER_GETPARAM:
424	case KAUTH_PROCESS_SCHEDULER_SETPARAM:
425	case KAUTH_PROCESS_SCHEDULER_GETAFFINITY:
426	case KAUTH_PROCESS_SCHEDULER_SETAFFINITY:
427	case KAUTH_PROCESS_SETID:
428	case KAUTH_PROCESS_KEVENT_FILTER:
429	case KAUTH_PROCESS_NICE:
430	case KAUTH_PROCESS_FORK:
431	case KAUTH_PROCESS_CORENAME:
432	case KAUTH_PROCESS_STOPFLAG:
433		if (isroot)
434			result = KAUTH_RESULT_ALLOW;
435
436		break;
437
438	case KAUTH_PROCESS_CANSEE: {
439		unsigned long req;
440
441		req = (unsigned long)arg1;
442
443		switch (req) {
444		case KAUTH_REQ_PROCESS_CANSEE_ARGS:
445		case KAUTH_REQ_PROCESS_CANSEE_ENTRY:
446		case KAUTH_REQ_PROCESS_CANSEE_OPENFILES:
447			if (isroot) {
448				result = KAUTH_RESULT_ALLOW;
449				break;
450			}
451
452			break;
453
454		case KAUTH_REQ_PROCESS_CANSEE_ENV:
455			if (isroot)
456				result = KAUTH_RESULT_ALLOW;
457
458			break;
459
460		default:
461			break;
462		}
463
464		break;
465		}
466
467	case KAUTH_PROCESS_RLIMIT: {
468		enum kauth_process_req req;
469
470		req = (enum kauth_process_req)(unsigned long)arg1;
471
472		switch (req) {
473		case KAUTH_REQ_PROCESS_RLIMIT_SET:
474		case KAUTH_REQ_PROCESS_RLIMIT_GET:
475			if (isroot)
476				result = KAUTH_RESULT_ALLOW;
477
478			break;
479
480		default:
481			break;
482		}
483
484		break;
485		}
486
487	default:
488		break;
489	}
490
491	return (result);
492}
493
494/*
495 * kauth(9) listener
496 *
497 * Security model: Traditional NetBSD
498 * Scope: Network
499 * Responsibility: Superuser access
500 */
501int
502secmodel_suser_network_cb(kauth_cred_t cred, kauth_action_t action,
503    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
504{
505	bool isroot;
506	int result;
507	enum kauth_network_req req;
508
509	isroot = suser_isroot(cred);
510	result = KAUTH_RESULT_DEFER;
511	req = (enum kauth_network_req)arg0;
512
513	switch (action) {
514	case KAUTH_NETWORK_ALTQ:
515		switch (req) {
516		case KAUTH_REQ_NETWORK_ALTQ_AFMAP:
517		case KAUTH_REQ_NETWORK_ALTQ_BLUE:
518		case KAUTH_REQ_NETWORK_ALTQ_CBQ:
519		case KAUTH_REQ_NETWORK_ALTQ_CDNR:
520		case KAUTH_REQ_NETWORK_ALTQ_CONF:
521		case KAUTH_REQ_NETWORK_ALTQ_FIFOQ:
522		case KAUTH_REQ_NETWORK_ALTQ_HFSC:
523		case KAUTH_REQ_NETWORK_ALTQ_JOBS:
524		case KAUTH_REQ_NETWORK_ALTQ_PRIQ:
525		case KAUTH_REQ_NETWORK_ALTQ_RED:
526		case KAUTH_REQ_NETWORK_ALTQ_RIO:
527		case KAUTH_REQ_NETWORK_ALTQ_WFQ:
528			if (isroot)
529				result = KAUTH_RESULT_ALLOW;
530			break;
531
532		default:
533			break;
534		}
535
536		break;
537
538	case KAUTH_NETWORK_BIND:
539		switch (req) {
540		case KAUTH_REQ_NETWORK_BIND_PORT:
541		case KAUTH_REQ_NETWORK_BIND_PRIVPORT:
542			if (isroot)
543				result = KAUTH_RESULT_ALLOW;
544			break;
545
546		default:
547			break;
548		}
549		break;
550
551	case KAUTH_NETWORK_FIREWALL:
552		switch (req) {
553		case KAUTH_REQ_NETWORK_FIREWALL_FW:
554		case KAUTH_REQ_NETWORK_FIREWALL_NAT:
555			if (isroot)
556				result = KAUTH_RESULT_ALLOW;
557
558			break;
559
560		default:
561			break;
562		}
563		break;
564
565	case KAUTH_NETWORK_FORWSRCRT:
566	case KAUTH_NETWORK_ROUTE:
567		if (isroot)
568			result = KAUTH_RESULT_ALLOW;
569
570		break;
571
572	case KAUTH_NETWORK_INTERFACE:
573		switch (req) {
574		case KAUTH_REQ_NETWORK_INTERFACE_GET:
575		case KAUTH_REQ_NETWORK_INTERFACE_SET:
576		case KAUTH_REQ_NETWORK_INTERFACE_GETPRIV:
577		case KAUTH_REQ_NETWORK_INTERFACE_SETPRIV:
578			if (isroot)
579				result = KAUTH_RESULT_ALLOW;
580			break;
581
582		default:
583			break;
584		}
585		break;
586
587	case KAUTH_NETWORK_INTERFACE_PPP:
588		switch (req) {
589		case KAUTH_REQ_NETWORK_INTERFACE_PPP_ADD:
590			if (isroot)
591				result = KAUTH_RESULT_ALLOW;
592			break;
593
594		default:
595			break;
596		}
597
598		break;
599
600	case KAUTH_NETWORK_INTERFACE_SLIP:
601		switch (req) {
602		case KAUTH_REQ_NETWORK_INTERFACE_SLIP_ADD:
603			if (isroot)
604				result = KAUTH_RESULT_ALLOW;
605			break;
606
607		default:
608			break;
609		}
610
611		break;
612
613	case KAUTH_NETWORK_INTERFACE_STRIP:
614		switch (req) {
615		case KAUTH_REQ_NETWORK_INTERFACE_STRIP_ADD:
616			if (isroot)
617				result = KAUTH_RESULT_ALLOW;
618			break;
619
620		default:
621			break;
622		}
623
624		break;
625
626	case KAUTH_NETWORK_INTERFACE_TUN:
627		switch (req) {
628		case KAUTH_REQ_NETWORK_INTERFACE_TUN_ADD:
629			if (isroot)
630				result = KAUTH_RESULT_ALLOW;
631			break;
632
633		default:
634			break;
635		}
636
637		break;
638
639	case KAUTH_NETWORK_NFS:
640		switch (req) {
641		case KAUTH_REQ_NETWORK_NFS_EXPORT:
642		case KAUTH_REQ_NETWORK_NFS_SVC:
643			if (isroot)
644				result = KAUTH_RESULT_ALLOW;
645
646			break;
647
648		default:
649			break;
650		}
651		break;
652
653	case KAUTH_NETWORK_SOCKET:
654		switch (req) {
655		case KAUTH_REQ_NETWORK_SOCKET_DROP:
656		case KAUTH_REQ_NETWORK_SOCKET_OPEN:
657		case KAUTH_REQ_NETWORK_SOCKET_RAWSOCK:
658		case KAUTH_REQ_NETWORK_SOCKET_SETPRIV:
659			if (isroot)
660				result = KAUTH_RESULT_ALLOW;
661			break;
662
663		case KAUTH_REQ_NETWORK_SOCKET_CANSEE:
664			if (isroot) {
665				result = KAUTH_RESULT_ALLOW;
666				break;
667			}
668
669			break;
670
671		default:
672			break;
673		}
674
675		break;
676
677
678	default:
679		break;
680	}
681
682	return (result);
683}
684
685/*
686 * kauth(9) listener
687 *
688 * Security model: Traditional NetBSD
689 * Scope: Machdep
690 * Responsibility: Superuser access
691 */
692int
693secmodel_suser_machdep_cb(kauth_cred_t cred, kauth_action_t action,
694    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
695{
696        bool isroot;
697        int result;
698
699        isroot = suser_isroot(cred);
700        result = KAUTH_RESULT_DEFER;
701
702        switch (action) {
703	case KAUTH_MACHDEP_CPU_UCODE_APPLY:
704	case KAUTH_MACHDEP_IOPERM_GET:
705	case KAUTH_MACHDEP_LDT_GET:
706	case KAUTH_MACHDEP_LDT_SET:
707	case KAUTH_MACHDEP_MTRR_GET:
708	case KAUTH_MACHDEP_CACHEFLUSH:
709	case KAUTH_MACHDEP_IOPERM_SET:
710	case KAUTH_MACHDEP_IOPL:
711	case KAUTH_MACHDEP_MTRR_SET:
712	case KAUTH_MACHDEP_NVRAM:
713	case KAUTH_MACHDEP_UNMANAGEDMEM:
714		if (isroot)
715			result = KAUTH_RESULT_ALLOW;
716		break;
717
718	default:
719		break;
720	}
721
722	return (result);
723}
724
725/*
726 * kauth(9) listener
727 *
728 * Security model: Traditional NetBSD
729 * Scope: Device
730 * Responsibility: Superuser access
731 */
732int
733secmodel_suser_device_cb(kauth_cred_t cred, kauth_action_t action,
734    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
735{
736        bool isroot;
737        int result;
738
739        isroot = suser_isroot(cred);
740        result = KAUTH_RESULT_DEFER;
741
742	switch (action) {
743	case KAUTH_DEVICE_BLUETOOTH_SETPRIV:
744	case KAUTH_DEVICE_BLUETOOTH_SEND:
745	case KAUTH_DEVICE_BLUETOOTH_RECV:
746	case KAUTH_DEVICE_TTY_OPEN:
747	case KAUTH_DEVICE_TTY_PRIVSET:
748	case KAUTH_DEVICE_TTY_STI:
749	case KAUTH_DEVICE_RND_ADDDATA:
750	case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
751	case KAUTH_DEVICE_RND_GETPRIV:
752	case KAUTH_DEVICE_RND_SETPRIV:
753		if (isroot)
754			result = KAUTH_RESULT_ALLOW;
755		break;
756
757	case KAUTH_DEVICE_BLUETOOTH_BCSP:
758	case KAUTH_DEVICE_BLUETOOTH_BTUART: {
759		enum kauth_device_req req;
760
761		req = (enum kauth_device_req)arg0;
762		switch (req) {
763		case KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD:
764		case KAUTH_REQ_DEVICE_BLUETOOTH_BTUART_ADD:
765			if (isroot)
766				result = KAUTH_RESULT_ALLOW;
767			break;
768
769		default:
770			break;
771		}
772
773		break;
774		}
775
776	case KAUTH_DEVICE_GPIO_PINSET:
777		/*
778		 * root can access gpio pins, secmodel_securlevel can veto
779		 * this decision.
780		 */
781		if (isroot)
782			result = KAUTH_RESULT_ALLOW;
783		break;
784
785	default:
786		break;
787	}
788
789	return (result);
790}
791
792int
793secmodel_suser_vnode_cb(kauth_cred_t cred, kauth_action_t action,
794    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
795{
796	bool isroot;
797	int result;
798
799	isroot = suser_isroot(cred);
800	result = KAUTH_RESULT_DEFER;
801
802	if (isroot)
803		result = KAUTH_RESULT_ALLOW;
804
805	return (result);
806}
807
808