1 /* $NetBSD: secmodel_securelevel.c,v 1.12 2009/07/25 16:08:02 mbalmer 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.12 2009/07/25 16:08:02 mbalmer 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 53 #include <miscfs/specfs/specdev.h> 54 55 #include <secmodel/securelevel/securelevel.h> 56 57 static int securelevel; 58 59 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device; 60 61 /* 62 * sysctl helper routine for securelevel. ensures that the value 63 * only rises unless the caller has pid 1 (assumed to be init). 64 */ 65 int 66 secmodel_securelevel_sysctl(SYSCTLFN_ARGS) 67 { 68 int newsecurelevel, error; 69 struct sysctlnode node; 70 71 newsecurelevel = securelevel; 72 node = *rnode; 73 node.sysctl_data = &newsecurelevel; 74 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 75 if (error || newp == NULL) 76 return (error); 77 78 if (newsecurelevel < securelevel && l && l->l_proc->p_pid != 1) 79 return (EPERM); 80 81 securelevel = newsecurelevel; 82 83 return (error); 84 } 85 86 void 87 secmodel_securelevel_init(void) 88 { 89 #ifdef INSECURE 90 securelevel = -1; 91 #else 92 securelevel = 0; 93 #endif /* INSECURE */ 94 } 95 96 SYSCTL_SETUP(sysctl_security_securelevel_setup, 97 "sysctl security securelevel setup") 98 { 99 /* 100 * For compatibility, we create a kern.securelevel variable. 101 */ 102 sysctl_createv(clog, 0, NULL, NULL, 103 CTLFLAG_PERMANENT, 104 CTLTYPE_NODE, "kern", NULL, 105 NULL, 0, NULL, 0, 106 CTL_KERN, CTL_EOL); 107 108 sysctl_createv(clog, 0, NULL, NULL, 109 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 110 CTLTYPE_INT, "securelevel", 111 SYSCTL_DESCR("System security level"), 112 secmodel_securelevel_sysctl, 0, NULL, 0, 113 CTL_KERN, KERN_SECURELVL, CTL_EOL); 114 } 115 116 void 117 secmodel_securelevel_start(void) 118 { 119 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 120 secmodel_securelevel_system_cb, NULL); 121 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 122 secmodel_securelevel_process_cb, NULL); 123 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 124 secmodel_securelevel_network_cb, NULL); 125 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 126 secmodel_securelevel_machdep_cb, NULL); 127 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 128 secmodel_securelevel_device_cb, NULL); 129 } 130 131 #if defined(_LKM) 132 void 133 secmodel_securelevel_stop(void) 134 { 135 kauth_unlisten_scope(l_system); 136 kauth_unlisten_scope(l_process); 137 kauth_unlisten_scope(l_network); 138 kauth_unlisten_scope(l_machdep); 139 kauth_unlisten_scope(l_device); 140 } 141 #endif /* _LKM */ 142 143 /* 144 * kauth(9) listener 145 * 146 * Security model: Traditional NetBSD 147 * Scope: System 148 * Responsibility: Securelevel 149 */ 150 int 151 secmodel_securelevel_system_cb(kauth_cred_t cred, 152 kauth_action_t action, void *cookie, void *arg0, void *arg1, 153 void *arg2, void *arg3) 154 { 155 int result; 156 enum kauth_system_req req; 157 158 result = KAUTH_RESULT_DEFER; 159 req = (enum kauth_system_req)arg0; 160 161 switch (action) { 162 case KAUTH_SYSTEM_CHSYSFLAGS: 163 if (securelevel > 0) 164 result = KAUTH_RESULT_DENY; 165 break; 166 167 case KAUTH_SYSTEM_TIME: 168 switch (req) { 169 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: 170 if (securelevel > 0) 171 result = KAUTH_RESULT_DENY; 172 break; 173 174 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { 175 struct timespec *ts = arg1; 176 struct timespec *delta = arg2; 177 178 /* 179 * Don't allow the time to be set forward so far it 180 * will wrap and become negative, thus allowing an 181 * attacker to bypass the next check below. The 182 * cutoff is 1 year before rollover occurs, so even 183 * if the attacker uses adjtime(2) to move the time 184 * past the cutoff, it will take a very long time 185 * to get to the wrap point. 186 */ 187 if (securelevel > 1 && 188 ((ts->tv_sec > LLONG_MAX - 365*24*60*60) || 189 (delta->tv_sec < 0 || delta->tv_nsec < 0))) 190 result = KAUTH_RESULT_DENY; 191 break; 192 } 193 194 default: 195 break; 196 } 197 break; 198 199 case KAUTH_SYSTEM_MODULE: 200 if (securelevel > 0) 201 result = KAUTH_RESULT_DENY; 202 break; 203 204 case KAUTH_SYSTEM_MOUNT: 205 switch (req) { 206 case KAUTH_REQ_SYSTEM_MOUNT_NEW: 207 if (securelevel > 1) 208 result = KAUTH_RESULT_DENY; 209 210 break; 211 212 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: 213 if (securelevel > 1) { 214 struct mount *mp = arg1; 215 u_long flags = (u_long)arg2; 216 217 /* Can only degrade from read/write to read-only. */ 218 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD | 219 MNT_FORCE | MNT_UPDATE)) 220 result = KAUTH_RESULT_DENY; 221 } 222 223 break; 224 225 default: 226 break; 227 } 228 229 break; 230 231 case KAUTH_SYSTEM_SYSCTL: 232 switch (req) { 233 case KAUTH_REQ_SYSTEM_SYSCTL_ADD: 234 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: 235 case KAUTH_REQ_SYSTEM_SYSCTL_DESC: 236 if (securelevel > 0) 237 result = KAUTH_RESULT_DENY; 238 break; 239 240 default: 241 break; 242 } 243 break; 244 245 case KAUTH_SYSTEM_SETIDCORE: 246 if (securelevel > 0) 247 result = KAUTH_RESULT_DENY; 248 break; 249 250 case KAUTH_SYSTEM_DEBUG: 251 switch (req) { 252 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB: 253 if (securelevel > 0) 254 result = KAUTH_RESULT_DENY; 255 break; 256 257 default: 258 break; 259 } 260 break; 261 262 default: 263 break; 264 } 265 266 return (result); 267 } 268 269 /* 270 * kauth(9) listener 271 * 272 * Security model: Traditional NetBSD 273 * Scope: Process 274 * Responsibility: Securelevel 275 */ 276 int 277 secmodel_securelevel_process_cb(kauth_cred_t cred, 278 kauth_action_t action, void *cookie, void *arg0, 279 void *arg1, void *arg2, void *arg3) 280 { 281 struct proc *p; 282 int result; 283 284 result = KAUTH_RESULT_DEFER; 285 p = arg0; 286 287 switch (action) { 288 case KAUTH_PROCESS_PROCFS: { 289 enum kauth_process_req req; 290 291 req = (enum kauth_process_req)arg2; 292 switch (req) { 293 case KAUTH_REQ_PROCESS_PROCFS_READ: 294 break; 295 296 case KAUTH_REQ_PROCESS_PROCFS_RW: 297 case KAUTH_REQ_PROCESS_PROCFS_WRITE: 298 if ((p == initproc) && (securelevel > -1)) 299 result = KAUTH_RESULT_DENY; 300 301 break; 302 303 default: 304 break; 305 } 306 307 break; 308 } 309 310 case KAUTH_PROCESS_PTRACE: 311 if ((p == initproc) && (securelevel >= 0)) 312 result = KAUTH_RESULT_DENY; 313 314 break; 315 316 case KAUTH_PROCESS_CORENAME: 317 if (securelevel > 1) 318 result = KAUTH_RESULT_DENY; 319 break; 320 321 default: 322 break; 323 } 324 325 return (result); 326 } 327 328 /* 329 * kauth(9) listener 330 * 331 * Security model: Traditional NetBSD 332 * Scope: Network 333 * Responsibility: Securelevel 334 */ 335 int 336 secmodel_securelevel_network_cb(kauth_cred_t cred, 337 kauth_action_t action, void *cookie, void *arg0, 338 void *arg1, void *arg2, void *arg3) 339 { 340 int result; 341 enum kauth_network_req req; 342 343 result = KAUTH_RESULT_DEFER; 344 req = (enum kauth_network_req)arg0; 345 346 switch (action) { 347 case KAUTH_NETWORK_FIREWALL: 348 switch (req) { 349 case KAUTH_REQ_NETWORK_FIREWALL_FW: 350 case KAUTH_REQ_NETWORK_FIREWALL_NAT: 351 if (securelevel > 1) 352 result = KAUTH_RESULT_DENY; 353 break; 354 355 default: 356 break; 357 } 358 break; 359 360 case KAUTH_NETWORK_FORWSRCRT: 361 if (securelevel > 0) 362 result = KAUTH_RESULT_DENY; 363 break; 364 365 default: 366 break; 367 } 368 369 return (result); 370 } 371 372 /* 373 * kauth(9) listener 374 * 375 * Security model: Traditional NetBSD 376 * Scope: Machdep 377 * Responsibility: Securelevel 378 */ 379 int 380 secmodel_securelevel_machdep_cb(kauth_cred_t cred, 381 kauth_action_t action, void *cookie, void *arg0, 382 void *arg1, void *arg2, void *arg3) 383 { 384 int result; 385 386 result = KAUTH_RESULT_DEFER; 387 388 switch (action) { 389 case KAUTH_MACHDEP_IOPERM_SET: 390 case KAUTH_MACHDEP_IOPL: 391 if (securelevel > 0) 392 result = KAUTH_RESULT_DENY; 393 break; 394 395 case KAUTH_MACHDEP_UNMANAGEDMEM: 396 if (securelevel > 0) 397 result = KAUTH_RESULT_DENY; 398 break; 399 400 default: 401 break; 402 } 403 404 return (result); 405 } 406 407 /* 408 * kauth(9) listener 409 * 410 * Security model: Traditional NetBSD 411 * Scope: Device 412 * Responsibility: Securelevel 413 */ 414 int 415 secmodel_securelevel_device_cb(kauth_cred_t cred, 416 kauth_action_t action, void *cookie, void *arg0, 417 void *arg1, void *arg2, void *arg3) 418 { 419 int result; 420 421 result = KAUTH_RESULT_DEFER; 422 423 switch (action) { 424 case KAUTH_DEVICE_RAWIO_SPEC: { 425 struct vnode *vp, *bvp; 426 enum kauth_device_req req; 427 dev_t dev; 428 int d_type; 429 430 req = (enum kauth_device_req)arg0; 431 vp = arg1; 432 433 KASSERT(vp != NULL); 434 435 dev = vp->v_rdev; 436 d_type = D_OTHER; 437 bvp = NULL; 438 439 /* Handle /dev/mem and /dev/kmem. */ 440 if ((vp->v_type == VCHR) && iskmemdev(dev)) { 441 switch (req) { 442 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 443 break; 444 445 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 446 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 447 if (securelevel > 0) 448 result = KAUTH_RESULT_DENY; 449 break; 450 451 default: 452 break; 453 } 454 455 break; 456 } 457 458 switch (req) { 459 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 460 break; 461 462 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 463 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 464 switch (vp->v_type) { 465 case VCHR: { 466 const struct cdevsw *cdev; 467 468 cdev = cdevsw_lookup(dev); 469 if (cdev != NULL) { 470 dev_t blkdev; 471 472 blkdev = devsw_chr2blk(dev); 473 if (blkdev != NODEV) { 474 vfinddev(blkdev, VBLK, &bvp); 475 if (bvp != NULL) 476 d_type = (cdev->d_flag 477 & D_TYPEMASK); 478 } 479 } 480 481 break; 482 } 483 case VBLK: { 484 const struct bdevsw *bdev; 485 486 bdev = bdevsw_lookup(dev); 487 if (bdev != NULL) 488 d_type = (bdev->d_flag & D_TYPEMASK); 489 490 bvp = vp; 491 492 break; 493 } 494 495 default: 496 break; 497 } 498 499 if (d_type != D_DISK) 500 break; 501 502 /* 503 * XXX: This is bogus. We should be failing the request 504 * XXX: not only if this specific slice is mounted, but 505 * XXX: if it's on a disk with any other mounted slice. 506 */ 507 if (vfs_mountedon(bvp) && (securelevel > 0)) 508 break; 509 510 if (securelevel > 1) 511 result = KAUTH_RESULT_DENY; 512 513 break; 514 515 default: 516 break; 517 } 518 519 break; 520 } 521 522 case KAUTH_DEVICE_RAWIO_PASSTHRU: 523 if (securelevel > 0) { 524 u_long bits; 525 526 bits = (u_long)arg0; 527 528 KASSERT(bits != 0); 529 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0); 530 531 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) 532 result = KAUTH_RESULT_DENY; 533 } 534 535 break; 536 537 case KAUTH_DEVICE_GPIO_PINSET: 538 if (securelevel > 0) 539 result = KAUTH_RESULT_DENY; 540 break; 541 542 default: 543 break; 544 } 545 546 return (result); 547 } 548