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