1 /* $NetBSD: secmodel_keylock.c,v 1.8 2014/02/25 18:30:13 pooka Exp $ */ 2 /*- 3 * Copyright (c) 2009 Marc Balmer <marc@msys.ch> 4 * Copyright (c) 2006 Elad Efrat <elad@NetBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * This file contains kauth(9) listeners needed to implement an experimental 32 * keylock based security scheme. 33 * 34 * The position of the keylock is a system-global indication on what 35 * operations are allowed or not. It affects all users, including root. 36 * 37 * Rules: 38 * 39 * - If the number of possible keylock positions is 0, assume there is no 40 * keylock present, do not dissallow any action, i.e. do nothing 41 * 42 * - If the number of possible keylock positions is greater than 0, but the 43 * current lock position is 0, assume tampering with the lock and forbid 44 * all actions. 45 * 46 * - If the lock is in the lowest position, assume the system is locked and 47 * forbid most actions. 48 * 49 * - If the lock is in the highest position, assume the system to be open and 50 * forbid nothing. 51 * 52 * - If the security.models.keylock.order sysctl is set to a value != 0, 53 * reverse this order. 54 */ 55 56 #include <sys/cdefs.h> 57 __KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.8 2014/02/25 18:30:13 pooka Exp $"); 58 59 #include <sys/types.h> 60 #include <sys/param.h> 61 #include <sys/kauth.h> 62 63 #include <sys/conf.h> 64 #include <sys/mount.h> 65 #include <sys/sysctl.h> 66 #include <sys/vnode.h> 67 #include <sys/timevar.h> 68 69 #include <dev/keylock.h> 70 71 #include <miscfs/specfs/specdev.h> 72 73 #include <secmodel/secmodel.h> 74 #include <secmodel/keylock/keylock.h> 75 76 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device; 77 78 static secmodel_t keylock_sm; 79 80 SYSCTL_SETUP(sysctl_security_keylock_setup, 81 "sysctl security keylock setup") 82 { 83 const struct sysctlnode *rnode; 84 85 sysctl_createv(clog, 0, NULL, &rnode, 86 CTLFLAG_PERMANENT, 87 CTLTYPE_NODE, "models", NULL, 88 NULL, 0, NULL, 0, 89 CTL_SECURITY, CTL_CREATE, CTL_EOL); 90 91 sysctl_createv(clog, 0, &rnode, &rnode, 92 CTLFLAG_PERMANENT, 93 CTLTYPE_NODE, "keylock", 94 SYSCTL_DESCR("Keylock security model"), 95 NULL, 0, NULL, 0, 96 CTL_CREATE, CTL_EOL); 97 98 sysctl_createv(clog, 0, &rnode, NULL, 99 CTLFLAG_PERMANENT, 100 CTLTYPE_STRING, "name", NULL, 101 NULL, 0, __UNCONST("Keylock"), 0, 102 CTL_CREATE, CTL_EOL); 103 } 104 105 void 106 secmodel_keylock_init(void) 107 { 108 int error = secmodel_register(&keylock_sm, 109 "org.netbsd.secmodel.keylock", 110 "NetBSD Security Model: Keylock", NULL, NULL, NULL); 111 if (error != 0) 112 printf("secmodel_keylock_init: secmodel_register " 113 "returned %d\n", error); 114 } 115 116 void 117 secmodel_keylock_start(void) 118 { 119 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 120 secmodel_keylock_system_cb, NULL); 121 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 122 secmodel_keylock_process_cb, NULL); 123 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 124 secmodel_keylock_network_cb, NULL); 125 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 126 secmodel_keylock_machdep_cb, NULL); 127 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 128 secmodel_keylock_device_cb, NULL); 129 } 130 131 void 132 secmodel_keylock_stop(void) 133 { 134 int error; 135 136 kauth_unlisten_scope(l_system); 137 kauth_unlisten_scope(l_process); 138 kauth_unlisten_scope(l_network); 139 kauth_unlisten_scope(l_machdep); 140 kauth_unlisten_scope(l_device); 141 142 error = secmodel_deregister(keylock_sm); 143 if (error != 0) 144 printf("secmodel_keylock_stop: secmodel_deregister " 145 "returned %d\n", error); 146 } 147 148 /* 149 * kauth(9) listener 150 * 151 * Security model: Multi-position keylock 152 * Scope: System 153 * Responsibility: Keylock 154 */ 155 int 156 secmodel_keylock_system_cb(kauth_cred_t cred, 157 kauth_action_t action, void *cookie, void *arg0, void *arg1, 158 void *arg2, void *arg3) 159 { 160 int result; 161 enum kauth_system_req req; 162 int kstate; 163 164 kstate = keylock_state(); 165 if (kstate == KEYLOCK_ABSENT) 166 return KAUTH_RESULT_DEFER; 167 else if (kstate == KEYLOCK_TAMPER) 168 return KAUTH_RESULT_DENY; 169 170 result = KAUTH_RESULT_DEFER; 171 req = (enum kauth_system_req)arg0; 172 173 switch (action) { 174 case KAUTH_SYSTEM_CHSYSFLAGS: 175 if (kstate == KEYLOCK_CLOSE) 176 result = KAUTH_RESULT_DENY; 177 break; 178 179 case KAUTH_SYSTEM_TIME: 180 switch (req) { 181 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: 182 if (kstate == KEYLOCK_CLOSE) 183 result = KAUTH_RESULT_DENY; 184 break; 185 186 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { 187 struct timespec *ts = arg1; 188 struct timespec *delta = arg2; 189 190 if (keylock_position() > 1 && time_wraps(ts, delta)) 191 result = KAUTH_RESULT_DENY; 192 break; 193 } 194 default: 195 break; 196 } 197 break; 198 199 case KAUTH_SYSTEM_MODULE: 200 if (kstate == KEYLOCK_CLOSE) 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 (kstate == KEYLOCK_CLOSE) 208 result = KAUTH_RESULT_DENY; 209 210 break; 211 212 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: 213 if (kstate == KEYLOCK_CLOSE) { 214 struct mount *mp = arg1; 215 u_long flags = (u_long)arg2; 216 217 /* 218 * Can only degrade from read/write to 219 * read-only. 220 */ 221 if (flags != (mp->mnt_flag | MNT_RDONLY | 222 MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) 223 result = KAUTH_RESULT_DENY; 224 } 225 break; 226 default: 227 break; 228 } 229 230 break; 231 232 case KAUTH_SYSTEM_SYSCTL: 233 switch (req) { 234 case KAUTH_REQ_SYSTEM_SYSCTL_ADD: 235 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: 236 case KAUTH_REQ_SYSTEM_SYSCTL_DESC: 237 if (kstate == KEYLOCK_CLOSE) 238 result = KAUTH_RESULT_DENY; 239 break; 240 default: 241 break; 242 } 243 break; 244 245 case KAUTH_SYSTEM_SETIDCORE: 246 if (kstate == KEYLOCK_CLOSE) 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 (kstate == KEYLOCK_CLOSE) 254 result = KAUTH_RESULT_DENY; 255 break; 256 default: 257 break; 258 } 259 break; 260 } 261 262 return result; 263 } 264 265 /* 266 * kauth(9) listener 267 * 268 * Security model: Multi-position keylock 269 * Scope: Process 270 * Responsibility: Keylock 271 */ 272 int 273 secmodel_keylock_process_cb(kauth_cred_t cred, 274 kauth_action_t action, void *cookie, void *arg0, 275 void *arg1, void *arg2, void *arg3) 276 { 277 struct proc *p; 278 int result, kstate; 279 280 kstate = keylock_state(); 281 if (kstate == KEYLOCK_ABSENT) 282 return KAUTH_RESULT_DEFER; 283 else if (kstate == KEYLOCK_TAMPER) 284 return KAUTH_RESULT_DENY; 285 286 result = KAUTH_RESULT_DEFER; 287 p = arg0; 288 289 switch (action) { 290 case KAUTH_PROCESS_PROCFS: { 291 enum kauth_process_req req; 292 293 req = (enum kauth_process_req)arg2; 294 switch (req) { 295 case KAUTH_REQ_PROCESS_PROCFS_READ: 296 break; 297 298 case KAUTH_REQ_PROCESS_PROCFS_RW: 299 case KAUTH_REQ_PROCESS_PROCFS_WRITE: 300 if ((p == initproc) && (kstate != KEYLOCK_OPEN)) 301 result = KAUTH_RESULT_DENY; 302 303 break; 304 default: 305 break; 306 } 307 308 break; 309 } 310 311 case KAUTH_PROCESS_PTRACE: 312 if ((p == initproc) && (kstate != KEYLOCK_OPEN)) 313 result = KAUTH_RESULT_DENY; 314 315 break; 316 317 case KAUTH_PROCESS_CORENAME: 318 if (kstate == KEYLOCK_CLOSE) 319 result = KAUTH_RESULT_DENY; 320 break; 321 } 322 return result; 323 } 324 325 /* 326 * kauth(9) listener 327 * 328 * Security model: Multi-position keylock 329 * Scope: Network 330 * Responsibility: Keylock 331 */ 332 int 333 secmodel_keylock_network_cb(kauth_cred_t cred, 334 kauth_action_t action, void *cookie, void *arg0, 335 void *arg1, void *arg2, void *arg3) 336 { 337 int result, kstate; 338 enum kauth_network_req req; 339 340 kstate = keylock_state(); 341 if (kstate == KEYLOCK_ABSENT) 342 return KAUTH_RESULT_DEFER; 343 else if (kstate == KEYLOCK_TAMPER) 344 return KAUTH_RESULT_DENY; 345 346 result = KAUTH_RESULT_DEFER; 347 req = (enum kauth_network_req)arg0; 348 349 switch (action) { 350 case KAUTH_NETWORK_FIREWALL: 351 switch (req) { 352 case KAUTH_REQ_NETWORK_FIREWALL_FW: 353 case KAUTH_REQ_NETWORK_FIREWALL_NAT: 354 if (kstate == KEYLOCK_CLOSE) 355 result = KAUTH_RESULT_DENY; 356 break; 357 358 default: 359 break; 360 } 361 break; 362 363 case KAUTH_NETWORK_FORWSRCRT: 364 if (kstate != KEYLOCK_OPEN) 365 result = KAUTH_RESULT_DENY; 366 break; 367 } 368 369 return result; 370 } 371 372 /* 373 * kauth(9) listener 374 * 375 * Security model: Multi-position keylock 376 * Scope: Machdep 377 * Responsibility: Keylock 378 */ 379 int 380 secmodel_keylock_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, kstate; 385 386 kstate = keylock_state(); 387 if (kstate == KEYLOCK_ABSENT) 388 return KAUTH_RESULT_DEFER; 389 else if (kstate == KEYLOCK_TAMPER) 390 return KAUTH_RESULT_DENY; 391 392 result = KAUTH_RESULT_DEFER; 393 394 switch (action) { 395 case KAUTH_MACHDEP_IOPERM_SET: 396 case KAUTH_MACHDEP_IOPL: 397 if (kstate != KEYLOCK_OPEN) 398 result = KAUTH_RESULT_DENY; 399 break; 400 401 case KAUTH_MACHDEP_UNMANAGEDMEM: 402 if (kstate != KEYLOCK_OPEN) 403 result = KAUTH_RESULT_DENY; 404 break; 405 } 406 407 return result; 408 } 409 410 /* 411 * kauth(9) listener 412 * 413 * Security model: Multi-position keylock 414 * Scope: Device 415 * Responsibility: Keylock 416 */ 417 int 418 secmodel_keylock_device_cb(kauth_cred_t cred, 419 kauth_action_t action, void *cookie, void *arg0, 420 void *arg1, void *arg2, void *arg3) 421 { 422 int result, kstate, error; 423 424 kstate = keylock_state(); 425 if (kstate == KEYLOCK_ABSENT) 426 return KAUTH_RESULT_DEFER; 427 else if (kstate == KEYLOCK_TAMPER) 428 return KAUTH_RESULT_DENY; 429 430 result = KAUTH_RESULT_DEFER; 431 432 switch (action) { 433 case KAUTH_DEVICE_RAWIO_SPEC: { 434 struct vnode *vp; 435 enum kauth_device_req req; 436 437 req = (enum kauth_device_req)arg0; 438 vp = arg1; 439 440 KASSERT(vp != NULL); 441 442 /* Handle /dev/mem and /dev/kmem. */ 443 if (iskmemvp(vp)) { 444 switch (req) { 445 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 446 break; 447 448 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 449 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 450 if (kstate != KEYLOCK_OPEN) 451 result = KAUTH_RESULT_DENY; 452 break; 453 default: 454 break; 455 } 456 break; 457 } 458 459 switch (req) { 460 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 461 break; 462 463 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 464 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 465 error = rawdev_mounted(vp, NULL); 466 467 if (error == EINVAL) 468 break; 469 470 if (error && (kstate != KEYLOCK_OPEN)) 471 break; 472 473 if (kstate == KEYLOCK_CLOSE) 474 result = KAUTH_RESULT_DENY; 475 476 break; 477 default: 478 break; 479 } 480 break; 481 } 482 483 case KAUTH_DEVICE_RAWIO_PASSTHRU: 484 if (kstate != KEYLOCK_OPEN) { 485 u_long bits; 486 487 bits = (u_long)arg0; 488 489 KASSERT(bits != 0); 490 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) 491 == 0); 492 493 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) 494 result = KAUTH_RESULT_DENY; 495 } 496 break; 497 498 case KAUTH_DEVICE_GPIO_PINSET: 499 if (kstate != KEYLOCK_OPEN) 500 result = KAUTH_RESULT_DENY; 501 break; 502 default: 503 break; 504 } 505 return result; 506 } 507