1 /* $NetBSD: secmodel_securelevel.c,v 1.20 2009/10/07 01:06:57 elad 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.20 2009/10/07 01:06:57 elad 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/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 struct sysctllog *securelevel_sysctl_log; 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 void 94 sysctl_security_securelevel_setup(struct sysctllog **clog) 95 { 96 const struct sysctlnode *rnode; 97 98 sysctl_createv(clog, 0, NULL, &rnode, 99 CTLFLAG_PERMANENT, 100 CTLTYPE_NODE, "security", NULL, 101 NULL, 0, NULL, 0, 102 CTL_SECURITY, CTL_EOL); 103 104 sysctl_createv(clog, 0, &rnode, &rnode, 105 CTLFLAG_PERMANENT, 106 CTLTYPE_NODE, "models", NULL, 107 NULL, 0, NULL, 0, 108 CTL_CREATE, CTL_EOL); 109 110 sysctl_createv(clog, 0, &rnode, &rnode, 111 CTLFLAG_PERMANENT, 112 CTLTYPE_NODE, "securelevel", NULL, 113 NULL, 0, NULL, 0, 114 CTL_CREATE, CTL_EOL); 115 116 sysctl_createv(clog, 0, &rnode, NULL, 117 CTLFLAG_PERMANENT, 118 CTLTYPE_STRING, "name", NULL, 119 NULL, 0, __UNCONST("Traditional NetBSD: Securelevel"), 0, 120 CTL_CREATE, CTL_EOL); 121 122 sysctl_createv(clog, 0, &rnode, NULL, 123 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 124 CTLTYPE_INT, "securelevel", 125 SYSCTL_DESCR("System security level"), 126 secmodel_securelevel_sysctl, 0, NULL, 0, 127 CTL_CREATE, CTL_EOL); 128 129 /* Compatibility: kern.securelevel */ 130 sysctl_createv(clog, 0, NULL, NULL, 131 CTLFLAG_PERMANENT, 132 CTLTYPE_NODE, "kern", NULL, 133 NULL, 0, NULL, 0, 134 CTL_KERN, CTL_EOL); 135 136 sysctl_createv(clog, 0, NULL, NULL, 137 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 138 CTLTYPE_INT, "securelevel", 139 SYSCTL_DESCR("System security level"), 140 secmodel_securelevel_sysctl, 0, NULL, 0, 141 CTL_KERN, KERN_SECURELVL, CTL_EOL); 142 } 143 144 void 145 secmodel_securelevel_init(void) 146 { 147 #ifdef INSECURE 148 securelevel = -1; 149 #else 150 securelevel = 0; 151 #endif /* INSECURE */ 152 } 153 154 void 155 secmodel_securelevel_start(void) 156 { 157 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 158 secmodel_securelevel_system_cb, NULL); 159 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 160 secmodel_securelevel_process_cb, NULL); 161 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 162 secmodel_securelevel_network_cb, NULL); 163 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 164 secmodel_securelevel_machdep_cb, NULL); 165 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 166 secmodel_securelevel_device_cb, NULL); 167 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE, 168 secmodel_securelevel_vnode_cb, NULL); 169 } 170 171 void 172 secmodel_securelevel_stop(void) 173 { 174 kauth_unlisten_scope(l_system); 175 kauth_unlisten_scope(l_process); 176 kauth_unlisten_scope(l_network); 177 kauth_unlisten_scope(l_machdep); 178 kauth_unlisten_scope(l_device); 179 kauth_unlisten_scope(l_vnode); 180 } 181 182 static int 183 securelevel_modcmd(modcmd_t cmd, void *arg) 184 { 185 int error = 0; 186 187 switch (cmd) { 188 case MODULE_CMD_INIT: 189 secmodel_securelevel_init(); 190 secmodel_securelevel_start(); 191 sysctl_security_securelevel_setup(&securelevel_sysctl_log); 192 break; 193 194 case MODULE_CMD_FINI: 195 sysctl_teardown(&securelevel_sysctl_log); 196 secmodel_securelevel_stop(); 197 break; 198 199 case MODULE_CMD_AUTOUNLOAD: 200 error = EPERM; 201 break; 202 203 default: 204 error = ENOTTY; 205 break; 206 } 207 208 return (error); 209 } 210 211 /* 212 * kauth(9) listener 213 * 214 * Security model: Traditional NetBSD 215 * Scope: System 216 * Responsibility: Securelevel 217 */ 218 int 219 secmodel_securelevel_system_cb(kauth_cred_t cred, kauth_action_t action, 220 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 221 { 222 int result; 223 enum kauth_system_req req; 224 225 result = KAUTH_RESULT_DEFER; 226 req = (enum kauth_system_req)arg0; 227 228 switch (action) { 229 case KAUTH_SYSTEM_CHSYSFLAGS: 230 if (securelevel > 0) 231 result = KAUTH_RESULT_DENY; 232 break; 233 234 case KAUTH_SYSTEM_TIME: 235 switch (req) { 236 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: 237 if (securelevel > 0) 238 result = KAUTH_RESULT_DENY; 239 break; 240 241 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { 242 struct timespec *ts = arg1; 243 struct timespec *delta = arg2; 244 245 if (securelevel > 1 && time_wraps(ts, delta)) 246 result = KAUTH_RESULT_DENY; 247 248 break; 249 } 250 251 default: 252 break; 253 } 254 break; 255 256 case KAUTH_SYSTEM_MODULE: 257 if (securelevel > 0) 258 result = KAUTH_RESULT_DENY; 259 break; 260 261 case KAUTH_SYSTEM_MOUNT: 262 switch (req) { 263 case KAUTH_REQ_SYSTEM_MOUNT_NEW: 264 if (securelevel > 1) 265 result = KAUTH_RESULT_DENY; 266 267 break; 268 269 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: 270 if (securelevel > 1) { 271 struct mount *mp = arg1; 272 u_long flags = (u_long)arg2; 273 274 /* Can only degrade from read/write to read-only. */ 275 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD | 276 MNT_FORCE | MNT_UPDATE)) 277 result = KAUTH_RESULT_DENY; 278 } 279 280 break; 281 282 default: 283 break; 284 } 285 286 break; 287 288 case KAUTH_SYSTEM_SYSCTL: 289 switch (req) { 290 case KAUTH_REQ_SYSTEM_SYSCTL_ADD: 291 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: 292 case KAUTH_REQ_SYSTEM_SYSCTL_DESC: 293 if (securelevel > 0) 294 result = KAUTH_RESULT_DENY; 295 break; 296 297 default: 298 break; 299 } 300 break; 301 302 case KAUTH_SYSTEM_SETIDCORE: 303 if (securelevel > 0) 304 result = KAUTH_RESULT_DENY; 305 break; 306 307 case KAUTH_SYSTEM_DEBUG: 308 switch (req) { 309 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB: 310 if (securelevel > 0) 311 result = KAUTH_RESULT_DENY; 312 break; 313 314 default: 315 break; 316 } 317 break; 318 319 default: 320 break; 321 } 322 323 return (result); 324 } 325 326 /* 327 * kauth(9) listener 328 * 329 * Security model: Traditional NetBSD 330 * Scope: Process 331 * Responsibility: Securelevel 332 */ 333 int 334 secmodel_securelevel_process_cb(kauth_cred_t cred, kauth_action_t action, 335 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 336 { 337 struct proc *p; 338 int result; 339 340 result = KAUTH_RESULT_DEFER; 341 p = arg0; 342 343 switch (action) { 344 case KAUTH_PROCESS_PROCFS: { 345 enum kauth_process_req req; 346 347 req = (enum kauth_process_req)arg2; 348 switch (req) { 349 case KAUTH_REQ_PROCESS_PROCFS_READ: 350 break; 351 352 case KAUTH_REQ_PROCESS_PROCFS_RW: 353 case KAUTH_REQ_PROCESS_PROCFS_WRITE: 354 if ((p == initproc) && (securelevel > -1)) 355 result = KAUTH_RESULT_DENY; 356 357 break; 358 359 default: 360 break; 361 } 362 363 break; 364 } 365 366 case KAUTH_PROCESS_PTRACE: 367 if ((p == initproc) && (securelevel > -1)) 368 result = KAUTH_RESULT_DENY; 369 370 break; 371 372 case KAUTH_PROCESS_CORENAME: 373 if (securelevel > 1) 374 result = KAUTH_RESULT_DENY; 375 break; 376 377 default: 378 break; 379 } 380 381 return (result); 382 } 383 384 /* 385 * kauth(9) listener 386 * 387 * Security model: Traditional NetBSD 388 * Scope: Network 389 * Responsibility: Securelevel 390 */ 391 int 392 secmodel_securelevel_network_cb(kauth_cred_t cred, kauth_action_t action, 393 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 394 { 395 int result; 396 enum kauth_network_req req; 397 398 result = KAUTH_RESULT_DEFER; 399 req = (enum kauth_network_req)arg0; 400 401 switch (action) { 402 case KAUTH_NETWORK_FIREWALL: 403 switch (req) { 404 case KAUTH_REQ_NETWORK_FIREWALL_FW: 405 case KAUTH_REQ_NETWORK_FIREWALL_NAT: 406 if (securelevel > 1) 407 result = KAUTH_RESULT_DENY; 408 break; 409 410 default: 411 break; 412 } 413 break; 414 415 case KAUTH_NETWORK_FORWSRCRT: 416 if (securelevel > 0) 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: Machdep 432 * Responsibility: Securelevel 433 */ 434 int 435 secmodel_securelevel_machdep_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 440 result = KAUTH_RESULT_DEFER; 441 442 switch (action) { 443 case KAUTH_MACHDEP_IOPERM_SET: 444 case KAUTH_MACHDEP_IOPL: 445 if (securelevel > 0) 446 result = KAUTH_RESULT_DENY; 447 break; 448 449 case KAUTH_MACHDEP_UNMANAGEDMEM: 450 if (securelevel > 0) 451 result = KAUTH_RESULT_DENY; 452 break; 453 454 default: 455 break; 456 } 457 458 return (result); 459 } 460 461 /* 462 * kauth(9) listener 463 * 464 * Security model: Traditional NetBSD 465 * Scope: Device 466 * Responsibility: Securelevel 467 */ 468 int 469 secmodel_securelevel_device_cb(kauth_cred_t cred, kauth_action_t action, 470 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 471 { 472 int result; 473 474 result = KAUTH_RESULT_DEFER; 475 476 switch (action) { 477 case KAUTH_DEVICE_RAWIO_SPEC: { 478 struct vnode *vp; 479 enum kauth_device_req req; 480 481 req = (enum kauth_device_req)arg0; 482 vp = arg1; 483 484 KASSERT(vp != NULL); 485 486 /* Handle /dev/mem and /dev/kmem. */ 487 if (iskmemvp(vp)) { 488 switch (req) { 489 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 490 break; 491 492 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 493 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 494 if (securelevel > 0) 495 result = KAUTH_RESULT_DENY; 496 497 break; 498 499 default: 500 break; 501 } 502 503 break; 504 } 505 506 switch (req) { 507 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 508 break; 509 510 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 511 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: { 512 int error; 513 514 error = rawdev_mounted(vp, NULL); 515 516 /* Not a disk. */ 517 if (error == EINVAL) 518 break; 519 520 if (error && securelevel > 0) 521 result = KAUTH_RESULT_DENY; 522 523 if (securelevel > 1) 524 result = KAUTH_RESULT_DENY; 525 526 break; 527 } 528 529 default: 530 break; 531 } 532 533 break; 534 } 535 536 case KAUTH_DEVICE_RAWIO_PASSTHRU: 537 if (securelevel > 0) { 538 u_long bits; 539 540 bits = (u_long)arg0; 541 542 KASSERT(bits != 0); 543 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0); 544 545 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) 546 result = KAUTH_RESULT_DENY; 547 } 548 549 break; 550 551 case KAUTH_DEVICE_GPIO_PINSET: 552 if (securelevel > 0) 553 result = KAUTH_RESULT_DENY; 554 break; 555 556 default: 557 break; 558 } 559 560 return (result); 561 } 562 563 int 564 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action, 565 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 566 { 567 int result; 568 569 result = KAUTH_RESULT_DEFER; 570 571 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) && 572 (action & KAUTH_VNODE_HAS_SYSFLAGS)) { 573 if (securelevel > 0) 574 result = KAUTH_RESULT_DENY; 575 } 576 577 return (result); 578 } 579 580