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