1 /* $NetBSD: secmodel_securelevel.c,v 1.36 2020/05/28 23:17:25 riastradh 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 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