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