1 /* $NetBSD: secmodel_securelevel.c,v 1.32 2018/07/15 05:16:45 maxv 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.32 2018/07/15 05:16:45 maxv 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 > 0) 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