1 /* $NetBSD: secmodel_securelevel.c,v 1.30 2014/02/25 18:30:13 pooka 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.30 2014/02/25 18:30:13 pooka 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 switch (req) { 352 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB: 353 if (securelevel > 0) 354 result = KAUTH_RESULT_DENY; 355 break; 356 357 default: 358 break; 359 } 360 break; 361 362 default: 363 break; 364 } 365 366 return (result); 367 } 368 369 /* 370 * kauth(9) listener 371 * 372 * Security model: Traditional NetBSD 373 * Scope: Process 374 * Responsibility: Securelevel 375 */ 376 int 377 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action, 378 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 379 { 380 struct proc *p; 381 int result; 382 383 result = KAUTH_RESULT_DEFER; 384 p = arg0; 385 386 switch (action) { 387 case KAUTH_PROCESS_PROCFS: { 388 enum kauth_process_req req; 389 390 req = (enum kauth_process_req)arg2; 391 switch (req) { 392 case KAUTH_REQ_PROCESS_PROCFS_READ: 393 break; 394 395 case KAUTH_REQ_PROCESS_PROCFS_RW: 396 case KAUTH_REQ_PROCESS_PROCFS_WRITE: 397 if ((p == initproc) && (securelevel > -1)) 398 result = KAUTH_RESULT_DENY; 399 400 break; 401 402 default: 403 break; 404 } 405 406 break; 407 } 408 409 case KAUTH_PROCESS_PTRACE: 410 if ((p == initproc) && (securelevel > -1)) 411 result = KAUTH_RESULT_DENY; 412 413 break; 414 415 case KAUTH_PROCESS_CORENAME: 416 if (securelevel > 1) 417 result = KAUTH_RESULT_DENY; 418 break; 419 420 default: 421 break; 422 } 423 424 return (result); 425 } 426 427 /* 428 * kauth(9) listener 429 * 430 * Security model: Traditional NetBSD 431 * Scope: Network 432 * Responsibility: Securelevel 433 */ 434 int 435 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action, 436 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 437 { 438 int result; 439 enum kauth_network_req req; 440 441 result = KAUTH_RESULT_DEFER; 442 req = (enum kauth_network_req)arg0; 443 444 switch (action) { 445 case KAUTH_NETWORK_FIREWALL: 446 switch (req) { 447 case KAUTH_REQ_NETWORK_FIREWALL_FW: 448 case KAUTH_REQ_NETWORK_FIREWALL_NAT: 449 if (securelevel > 1) 450 result = KAUTH_RESULT_DENY; 451 break; 452 453 default: 454 break; 455 } 456 break; 457 458 case KAUTH_NETWORK_FORWSRCRT: 459 if (securelevel > 0) 460 result = KAUTH_RESULT_DENY; 461 break; 462 463 default: 464 break; 465 } 466 467 return (result); 468 } 469 470 /* 471 * kauth(9) listener 472 * 473 * Security model: Traditional NetBSD 474 * Scope: Machdep 475 * Responsibility: Securelevel 476 */ 477 int 478 secmodel_securelevel_machdep_cb(kauth_cred_t cred, kauth_action_t action, 479 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 480 { 481 int result; 482 483 result = KAUTH_RESULT_DEFER; 484 485 switch (action) { 486 case KAUTH_MACHDEP_IOPERM_SET: 487 case KAUTH_MACHDEP_IOPL: 488 if (securelevel > 0) 489 result = KAUTH_RESULT_DENY; 490 break; 491 492 case KAUTH_MACHDEP_UNMANAGEDMEM: 493 if (securelevel > 0) 494 result = KAUTH_RESULT_DENY; 495 break; 496 497 case KAUTH_MACHDEP_CPU_UCODE_APPLY: 498 if (securelevel > 1) 499 result = KAUTH_RESULT_DENY; 500 break; 501 502 default: 503 break; 504 } 505 506 return (result); 507 } 508 509 /* 510 * kauth(9) listener 511 * 512 * Security model: Traditional NetBSD 513 * Scope: Device 514 * Responsibility: Securelevel 515 */ 516 int 517 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action, 518 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 519 { 520 int result; 521 522 result = KAUTH_RESULT_DEFER; 523 524 switch (action) { 525 case KAUTH_DEVICE_RAWIO_SPEC: { 526 struct vnode *vp; 527 enum kauth_device_req req; 528 529 req = (enum kauth_device_req)arg0; 530 vp = arg1; 531 532 KASSERT(vp != NULL); 533 534 /* Handle /dev/mem and /dev/kmem. */ 535 if (iskmemvp(vp)) { 536 switch (req) { 537 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 538 break; 539 540 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 541 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 542 if (securelevel > 0) 543 result = KAUTH_RESULT_DENY; 544 545 break; 546 547 default: 548 break; 549 } 550 551 break; 552 } 553 554 switch (req) { 555 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 556 break; 557 558 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 559 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: { 560 int error; 561 562 error = rawdev_mounted(vp, NULL); 563 564 /* Not a disk. */ 565 if (error == EINVAL) 566 break; 567 568 if (error && securelevel > 0) 569 result = KAUTH_RESULT_DENY; 570 571 if (securelevel > 1) 572 result = KAUTH_RESULT_DENY; 573 574 break; 575 } 576 577 default: 578 break; 579 } 580 581 break; 582 } 583 584 case KAUTH_DEVICE_RAWIO_PASSTHRU: 585 if (securelevel > 0) { 586 u_long bits; 587 588 bits = (u_long)arg0; 589 590 KASSERT(bits != 0); 591 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0); 592 593 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) 594 result = KAUTH_RESULT_DENY; 595 } 596 597 break; 598 599 case KAUTH_DEVICE_GPIO_PINSET: 600 if (securelevel > 0) 601 result = KAUTH_RESULT_DENY; 602 break; 603 604 case KAUTH_DEVICE_RND_ADDDATA_ESTIMATE: 605 if (securelevel > 0) 606 result = KAUTH_RESULT_DENY; 607 break; 608 609 default: 610 break; 611 } 612 613 return (result); 614 } 615 616 int 617 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action, 618 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 619 { 620 int result; 621 622 result = KAUTH_RESULT_DEFER; 623 624 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) && 625 (action & KAUTH_VNODE_HAS_SYSFLAGS)) { 626 if (securelevel > 0) 627 result = KAUTH_RESULT_DENY; 628 } 629 630 return (result); 631 } 632 633