No empty .Rs/.Re
[netbsd-mini2440.git] / sys / secmodel / securelevel / secmodel_securelevel.c
blob192f6b1823c9686faa313227f7ab81a3013d89c1
1 /* $NetBSD: secmodel_securelevel.c,v 1.19 2009/10/06 05:03:58 elad Exp $ */
2 /*-
3 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
4 * All rights reserved.
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.
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.
30 * This file contains kauth(9) listeners needed to implement the traditional
31 * NetBSD securelevel.
33 * The securelevel is a system-global indication on what operations are
34 * allowed or not. It affects all users, including root.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.19 2009/10/06 05:03:58 elad Exp $");
40 #ifdef _KERNEL_OPT
41 #include "opt_insecure.h"
42 #endif /* _KERNEL_OPT */
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/kauth.h>
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>
55 #include <miscfs/specfs/specdev.h>
57 #include <secmodel/securelevel/securelevel.h>
59 MODULE(MODULE_CLASS_SECMODEL, securelevel, NULL);
61 static int securelevel;
63 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device,
64 l_vnode;
66 static struct sysctllog *securelevel_sysctl_log;
69 * Sysctl helper routine for securelevel. Ensures that the value only rises
70 * unless the caller is init.
72 int
73 secmodel_securelevel_sysctl(SYSCTLFN_ARGS)
75 int newsecurelevel, error;
76 struct sysctlnode node;
78 newsecurelevel = securelevel;
79 node = *rnode;
80 node.sysctl_data = &newsecurelevel;
81 error = sysctl_lookup(SYSCTLFN_CALL(&node));
82 if (error || newp == NULL)
83 return (error);
85 if ((newsecurelevel < securelevel) && (l->l_proc != initproc))
86 return (EPERM);
88 securelevel = newsecurelevel;
90 return (error);
93 void
94 sysctl_security_securelevel_setup(struct sysctllog **clog)
96 const struct sysctlnode *rnode;
98 sysctl_createv(clog, 0, NULL, &rnode,
99 CTLFLAG_PERMANENT,
100 CTLTYPE_NODE, "security", NULL,
101 NULL, 0, NULL, 0,
102 CTL_SECURITY, CTL_EOL);
104 sysctl_createv(clog, 0, &rnode, &rnode,
105 CTLFLAG_PERMANENT,
106 CTLTYPE_NODE, "models", NULL,
107 NULL, 0, NULL, 0,
108 CTL_CREATE, CTL_EOL);
110 sysctl_createv(clog, 0, &rnode, &rnode,
111 CTLFLAG_PERMANENT,
112 CTLTYPE_NODE, "securelevel", NULL,
113 NULL, 0, NULL, 0,
114 CTL_CREATE, CTL_EOL);
116 sysctl_createv(clog, 0, &rnode, NULL,
117 CTLFLAG_PERMANENT,
118 CTLTYPE_STRING, "name", NULL,
119 NULL, 0, __UNCONST("Traditional NetBSD: Securelevel"), 0,
120 CTL_CREATE, CTL_EOL);
122 sysctl_createv(clog, 0, &rnode, NULL,
123 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
124 CTLTYPE_INT, "securelevel",
125 SYSCTL_DESCR("System security level"),
126 secmodel_securelevel_sysctl, 0, NULL, 0,
127 CTL_CREATE, CTL_EOL);
129 /* Compatibility: kern.securelevel */
130 sysctl_createv(clog, 0, NULL, NULL,
131 CTLFLAG_PERMANENT,
132 CTLTYPE_NODE, "kern", NULL,
133 NULL, 0, NULL, 0,
134 CTL_KERN, CTL_EOL);
136 sysctl_createv(clog, 0, NULL, NULL,
137 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
138 CTLTYPE_INT, "securelevel",
139 SYSCTL_DESCR("System security level"),
140 secmodel_securelevel_sysctl, 0, NULL, 0,
141 CTL_KERN, KERN_SECURELVL, CTL_EOL);
144 void
145 secmodel_securelevel_init(void)
147 #ifdef INSECURE
148 securelevel = -1;
149 #else
150 securelevel = 0;
151 #endif /* INSECURE */
154 void
155 secmodel_securelevel_start(void)
157 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
158 secmodel_securelevel_system_cb, NULL);
159 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
160 secmodel_securelevel_process_cb, NULL);
161 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
162 secmodel_securelevel_network_cb, NULL);
163 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
164 secmodel_securelevel_machdep_cb, NULL);
165 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
166 secmodel_securelevel_device_cb, NULL);
167 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
168 secmodel_securelevel_vnode_cb, NULL);
171 void
172 secmodel_securelevel_stop(void)
174 kauth_unlisten_scope(l_system);
175 kauth_unlisten_scope(l_process);
176 kauth_unlisten_scope(l_network);
177 kauth_unlisten_scope(l_machdep);
178 kauth_unlisten_scope(l_device);
179 kauth_unlisten_scope(l_vnode);
182 static int
183 securelevel_modcmd(modcmd_t cmd, void *arg)
185 int error = 0;
187 switch (cmd) {
188 case MODULE_CMD_INIT:
189 secmodel_securelevel_init();
190 secmodel_securelevel_start();
191 sysctl_security_securelevel_setup(&securelevel_sysctl_log);
192 break;
194 case MODULE_CMD_FINI:
195 sysctl_teardown(&securelevel_sysctl_log);
196 secmodel_securelevel_stop();
197 break;
199 case MODULE_CMD_AUTOUNLOAD:
200 error = EPERM;
201 break;
203 default:
204 error = ENOTTY;
205 break;
208 return (error);
212 * kauth(9) listener
214 * Security model: Traditional NetBSD
215 * Scope: System
216 * Responsibility: Securelevel
219 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action,
220 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
222 int result;
223 enum kauth_system_req req;
225 result = KAUTH_RESULT_DEFER;
226 req = (enum kauth_system_req)arg0;
228 switch (action) {
229 case KAUTH_SYSTEM_CHSYSFLAGS:
230 if (securelevel > 0)
231 result = KAUTH_RESULT_DENY;
232 break;
234 case KAUTH_SYSTEM_TIME:
235 switch (req) {
236 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
237 if (securelevel > 0)
238 result = KAUTH_RESULT_DENY;
239 break;
241 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
242 struct timespec *ts = arg1;
243 struct timespec *delta = arg2;
245 if (securelevel > 1 && time_wraps(ts, delta))
246 result = KAUTH_RESULT_DENY;
248 break;
251 default:
252 break;
254 break;
256 case KAUTH_SYSTEM_MODULE:
257 if (securelevel > 0)
258 result = KAUTH_RESULT_DENY;
259 break;
261 case KAUTH_SYSTEM_MOUNT:
262 switch (req) {
263 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
264 if (securelevel > 1)
265 result = KAUTH_RESULT_DENY;
267 break;
269 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
270 if (securelevel > 1) {
271 struct mount *mp = arg1;
272 u_long flags = (u_long)arg2;
274 /* Can only degrade from read/write to read-only. */
275 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
276 MNT_FORCE | MNT_UPDATE))
277 result = KAUTH_RESULT_DENY;
280 break;
282 default:
283 break;
286 break;
288 case KAUTH_SYSTEM_SYSCTL:
289 switch (req) {
290 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
291 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
292 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
293 if (securelevel > 0)
294 result = KAUTH_RESULT_DENY;
295 break;
297 default:
298 break;
300 break;
302 case KAUTH_SYSTEM_SETIDCORE:
303 if (securelevel > 0)
304 result = KAUTH_RESULT_DENY;
305 break;
307 case KAUTH_SYSTEM_DEBUG:
308 switch (req) {
309 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
310 if (securelevel > 0)
311 result = KAUTH_RESULT_DENY;
312 break;
314 default:
315 break;
317 break;
319 default:
320 break;
323 return (result);
327 * kauth(9) listener
329 * Security model: Traditional NetBSD
330 * Scope: Process
331 * Responsibility: Securelevel
334 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action,
335 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
337 struct proc *p;
338 int result;
340 result = KAUTH_RESULT_DEFER;
341 p = arg0;
343 switch (action) {
344 case KAUTH_PROCESS_PROCFS: {
345 enum kauth_process_req req;
347 req = (enum kauth_process_req)arg2;
348 switch (req) {
349 case KAUTH_REQ_PROCESS_PROCFS_READ:
350 break;
352 case KAUTH_REQ_PROCESS_PROCFS_RW:
353 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
354 if ((p == initproc) && (securelevel > -1))
355 result = KAUTH_RESULT_DENY;
357 break;
359 default:
360 break;
363 break;
366 case KAUTH_PROCESS_PTRACE:
367 if ((p == initproc) && (securelevel > -1))
368 result = KAUTH_RESULT_DENY;
370 break;
372 case KAUTH_PROCESS_CORENAME:
373 if (securelevel > 1)
374 result = KAUTH_RESULT_DENY;
375 break;
377 default:
378 break;
381 return (result);
385 * kauth(9) listener
387 * Security model: Traditional NetBSD
388 * Scope: Network
389 * Responsibility: Securelevel
392 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action,
393 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
395 int result;
396 enum kauth_network_req req;
398 result = KAUTH_RESULT_DEFER;
399 req = (enum kauth_network_req)arg0;
401 switch (action) {
402 case KAUTH_NETWORK_FIREWALL:
403 switch (req) {
404 case KAUTH_REQ_NETWORK_FIREWALL_FW:
405 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
406 if (securelevel > 1)
407 result = KAUTH_RESULT_DENY;
408 break;
410 default:
411 break;
413 break;
415 case KAUTH_NETWORK_FORWSRCRT:
416 if (securelevel > 0)
417 result = KAUTH_RESULT_DENY;
418 break;
420 default:
421 break;
424 return (result);
428 * kauth(9) listener
430 * Security model: Traditional NetBSD
431 * Scope: Machdep
432 * Responsibility: Securelevel
435 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action,
436 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
438 int result;
440 result = KAUTH_RESULT_DEFER;
442 switch (action) {
443 case KAUTH_MACHDEP_IOPERM_SET:
444 case KAUTH_MACHDEP_IOPL:
445 if (securelevel > 0)
446 result = KAUTH_RESULT_DENY;
447 break;
449 case KAUTH_MACHDEP_UNMANAGEDMEM:
450 if (securelevel > 0)
451 result = KAUTH_RESULT_DENY;
452 break;
454 default:
455 break;
458 return (result);
462 * kauth(9) listener
464 * Security model: Traditional NetBSD
465 * Scope: Device
466 * Responsibility: Securelevel
469 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action,
470 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
472 int result;
474 result = KAUTH_RESULT_DEFER;
476 switch (action) {
477 case KAUTH_DEVICE_RAWIO_SPEC: {
478 struct vnode *vp;
479 enum kauth_device_req req;
481 req = (enum kauth_device_req)arg0;
482 vp = arg1;
484 KASSERT(vp != NULL);
486 /* Handle /dev/mem and /dev/kmem. */
487 if (iskmemvp(vp)) {
488 switch (req) {
489 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
490 break;
492 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
493 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
494 if (securelevel > 0)
495 result = KAUTH_RESULT_DENY;
497 break;
499 default:
500 break;
503 break;
506 switch (req) {
507 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
508 break;
510 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
511 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
512 int error;
514 error = rawdev_mounted(vp, NULL);
516 /* Not a disk. */
517 if (error == EINVAL)
518 break;
520 if (error && securelevel > 0)
521 result = KAUTH_RESULT_DENY;
523 if (securelevel > 1)
524 result = KAUTH_RESULT_DENY;
526 break;
529 default:
530 break;
533 break;
536 case KAUTH_DEVICE_RAWIO_PASSTHRU:
537 if (securelevel > 0) {
538 u_long bits;
540 bits = (u_long)arg0;
542 KASSERT(bits != 0);
543 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
545 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
546 result = KAUTH_RESULT_DENY;
549 break;
551 case KAUTH_DEVICE_GPIO_PINSET:
552 if (securelevel > 0)
553 result = KAUTH_RESULT_DENY;
554 break;
556 default:
557 break;
560 return (result);
564 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
565 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
567 int result;
569 result = KAUTH_RESULT_DEFER;
571 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
572 (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
573 if (securelevel > 0)
574 result = KAUTH_RESULT_DENY;
577 return (result);