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