secmodel_securelevel.c revision 1.32.4.1 1 /* $NetBSD: secmodel_securelevel.c,v 1.32.4.1 2020/08/17 11:27:33 martin 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.32.4.1 2020/08/17 11:27:33 martin 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, *rnode2;
99
100 sysctl_createv(clog, 0, NULL, &rnode,
101 CTLFLAG_PERMANENT,
102 CTLTYPE_NODE, "models", NULL,
103 NULL, 0, NULL, 0,
104 CTL_SECURITY, CTL_CREATE, CTL_EOL);
105
106 /* Compatibility: security.models.bsd44 */
107 rnode2 = rnode;
108 sysctl_createv(clog, 0, &rnode2, &rnode2,
109 CTLFLAG_PERMANENT,
110 CTLTYPE_NODE, "bsd44", NULL,
111 NULL, 0, NULL, 0,
112 CTL_CREATE, CTL_EOL);
113
114 /* Compatibility: security.models.bsd44.securelevel */
115 sysctl_createv(clog, 0, &rnode2, NULL,
116 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
117 CTLTYPE_INT, "securelevel",
118 SYSCTL_DESCR("System security level"),
119 secmodel_securelevel_sysctl, 0, NULL, 0,
120 CTL_CREATE, CTL_EOL);
121
122 sysctl_createv(clog, 0, &rnode, &rnode,
123 CTLFLAG_PERMANENT,
124 CTLTYPE_NODE, "securelevel", NULL,
125 NULL, 0, NULL, 0,
126 CTL_CREATE, CTL_EOL);
127
128 sysctl_createv(clog, 0, &rnode, NULL,
129 CTLFLAG_PERMANENT,
130 CTLTYPE_STRING, "name", NULL,
131 NULL, 0, __UNCONST(SECMODEL_SECURELEVEL_NAME), 0,
132 CTL_CREATE, CTL_EOL);
133
134 sysctl_createv(clog, 0, &rnode, NULL,
135 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
136 CTLTYPE_INT, "securelevel",
137 SYSCTL_DESCR("System security level"),
138 secmodel_securelevel_sysctl, 0, NULL, 0,
139 CTL_CREATE, CTL_EOL);
140
141 /* Compatibility: kern.securelevel */
142
143 sysctl_createv(clog, 0, NULL, NULL,
144 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
145 CTLTYPE_INT, "securelevel",
146 SYSCTL_DESCR("System security level"),
147 secmodel_securelevel_sysctl, 0, NULL, 0,
148 CTL_KERN, KERN_SECURELVL, CTL_EOL);
149 }
150
151 void
152 secmodel_securelevel_init(void)
153 {
154 #ifdef INSECURE
155 securelevel = -1;
156 #else
157 securelevel = 0;
158 #endif /* INSECURE */
159 }
160
161 void
162 secmodel_securelevel_start(void)
163 {
164 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
165 secmodel_securelevel_system_cb, NULL);
166 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
167 secmodel_securelevel_process_cb, NULL);
168 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
169 secmodel_securelevel_network_cb, NULL);
170 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
171 secmodel_securelevel_machdep_cb, NULL);
172 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
173 secmodel_securelevel_device_cb, NULL);
174 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
175 secmodel_securelevel_vnode_cb, NULL);
176 }
177
178 void
179 secmodel_securelevel_stop(void)
180 {
181 kauth_unlisten_scope(l_system);
182 kauth_unlisten_scope(l_process);
183 kauth_unlisten_scope(l_network);
184 kauth_unlisten_scope(l_machdep);
185 kauth_unlisten_scope(l_device);
186 kauth_unlisten_scope(l_vnode);
187 }
188
189 static int
190 securelevel_eval(const char *what, void *arg, void *ret)
191 {
192 int error = 0;
193
194 if (strcasecmp(what, "is-securelevel-above") == 0) {
195 int level = (int)(uintptr_t)arg;
196 bool *bp = ret;
197
198 *bp = (securelevel > level);
199 } else {
200 error = ENOENT;
201 }
202
203 return error;
204 }
205
206 static int
207 securelevel_modcmd(modcmd_t cmd, void *arg)
208 {
209 int error = 0;
210
211 switch (cmd) {
212 case MODULE_CMD_INIT:
213 secmodel_securelevel_init();
214 error = secmodel_register(&securelevel_sm,
215 SECMODEL_SECURELEVEL_ID, SECMODEL_SECURELEVEL_NAME,
216 NULL, securelevel_eval, NULL);
217 if (error != 0)
218 printf("securelevel_modcmd::init: secmodel_register "
219 "returned %d\n", error);
220
221 secmodel_securelevel_start();
222 sysctl_security_securelevel_setup(&securelevel_sysctl_log);
223 break;
224
225 case MODULE_CMD_FINI:
226 sysctl_teardown(&securelevel_sysctl_log);
227 secmodel_securelevel_stop();
228
229 error = secmodel_deregister(securelevel_sm);
230 if (error != 0)
231 printf("securelevel_modcmd::fini: secmodel_deregister "
232 "returned %d\n", error);
233
234 break;
235
236 case MODULE_CMD_AUTOUNLOAD:
237 error = EPERM;
238 break;
239
240 default:
241 error = ENOTTY;
242 break;
243 }
244
245 return (error);
246 }
247
248 /*
249 * kauth(9) listener
250 *
251 * Security model: Traditional NetBSD
252 * Scope: System
253 * Responsibility: Securelevel
254 */
255 int
256 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action,
257 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
258 {
259 int result;
260 enum kauth_system_req req;
261
262 result = KAUTH_RESULT_DEFER;
263 req = (enum kauth_system_req)arg0;
264
265 switch (action) {
266 case KAUTH_SYSTEM_CHSYSFLAGS:
267 /* Deprecated. */
268 if (securelevel > 0)
269 result = KAUTH_RESULT_DENY;
270 break;
271
272 case KAUTH_SYSTEM_TIME:
273 switch (req) {
274 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
275 if (securelevel > 0)
276 result = KAUTH_RESULT_DENY;
277 break;
278
279 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
280 struct timespec *ts = arg1;
281 struct timespec *delta = arg2;
282
283 if (securelevel > 1 && time_wraps(ts, delta))
284 result = KAUTH_RESULT_DENY;
285
286 break;
287 }
288
289 default:
290 break;
291 }
292 break;
293
294 case KAUTH_SYSTEM_MAP_VA_ZERO:
295 if (securelevel > 0)
296 result = KAUTH_RESULT_DENY;
297 break;
298
299 case KAUTH_SYSTEM_MODULE:
300 if (securelevel > 0)
301 result = KAUTH_RESULT_DENY;
302 break;
303
304 case KAUTH_SYSTEM_MOUNT:
305 switch (req) {
306 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
307 if (securelevel > 1)
308 result = KAUTH_RESULT_DENY;
309
310 break;
311
312 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
313 if (securelevel > 1) {
314 struct mount *mp = arg1;
315 u_long flags = (u_long)arg2;
316
317 /* Can only degrade from read/write to read-only. */
318 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
319 MNT_FORCE | MNT_UPDATE))
320 result = KAUTH_RESULT_DENY;
321 }
322
323 break;
324
325 default:
326 break;
327 }
328
329 break;
330
331 case KAUTH_SYSTEM_SYSCTL:
332 switch (req) {
333 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
334 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
335 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
336 if (securelevel > 0)
337 result = KAUTH_RESULT_DENY;
338 break;
339
340 default:
341 break;
342 }
343 break;
344
345 case KAUTH_SYSTEM_SETIDCORE:
346 if (securelevel > 0)
347 result = KAUTH_RESULT_DENY;
348 break;
349
350 case KAUTH_SYSTEM_DEBUG:
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 case KAUTH_MACHDEP_SVS_DISABLE:
487 if (securelevel > 0)
488 result = KAUTH_RESULT_DENY;
489 break;
490
491 case KAUTH_MACHDEP_CPU_UCODE_APPLY:
492 if (securelevel > 1)
493 result = KAUTH_RESULT_DENY;
494 break;
495
496 default:
497 break;
498 }
499
500 return (result);
501 }
502
503 /*
504 * kauth(9) listener
505 *
506 * Security model: Traditional NetBSD
507 * Scope: Device
508 * Responsibility: Securelevel
509 */
510 int
511 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action,
512 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
513 {
514 int result;
515
516 result = KAUTH_RESULT_DEFER;
517
518 switch (action) {
519 case KAUTH_DEVICE_RAWIO_SPEC: {
520 struct vnode *vp;
521 enum kauth_device_req req;
522
523 req = (enum kauth_device_req)arg0;
524 vp = arg1;
525
526 KASSERT(vp != NULL);
527
528 /* Handle /dev/mem and /dev/kmem. */
529 if (iskmemvp(vp)) {
530 switch (req) {
531 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
532 break;
533
534 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
535 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
536 if (securelevel > 0)
537 result = KAUTH_RESULT_DENY;
538
539 break;
540
541 default:
542 break;
543 }
544
545 break;
546 }
547
548 switch (req) {
549 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
550 break;
551
552 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
553 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
554 int error;
555
556 error = rawdev_mounted(vp, NULL);
557
558 /* Not a disk. */
559 if (error == EINVAL)
560 break;
561
562 if (error && securelevel > 0)
563 result = KAUTH_RESULT_DENY;
564
565 if (securelevel > 1)
566 result = KAUTH_RESULT_DENY;
567
568 break;
569 }
570
571 default:
572 break;
573 }
574
575 break;
576 }
577
578 case KAUTH_DEVICE_RAWIO_PASSTHRU:
579 if (securelevel > 0) {
580 u_long bits;
581
582 bits = (u_long)arg0;
583
584 KASSERT(bits != 0);
585 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
586
587 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
588 result = KAUTH_RESULT_DENY;
589 }
590
591 break;
592
593 case KAUTH_DEVICE_GPIO_PINSET:
594 if (securelevel > 0)
595 result = KAUTH_RESULT_DENY;
596 break;
597
598 case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE:
599 if (securelevel > 1)
600 result = KAUTH_RESULT_DENY;
601 break;
602
603 default:
604 break;
605 }
606
607 return (result);
608 }
609
610 int
611 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
612 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
613 {
614 int result;
615
616 result = KAUTH_RESULT_DEFER;
617
618 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
619 (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
620 if (securelevel > 0)
621 result = KAUTH_RESULT_DENY;
622 }
623
624 return (result);
625 }
626
627