secmodel_keylock.c revision 1.6
1/* $NetBSD: secmodel_keylock.c,v 1.6 2011/12/04 19:25:00 jym 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.6 2011/12/04 19:25:00 jym 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/keylock/keylock.h> 74 75static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device; 76 77SYSCTL_SETUP(sysctl_security_keylock_setup, 78 "sysctl security keylock setup") 79{ 80 const struct sysctlnode *rnode; 81 82 sysctl_createv(clog, 0, NULL, &rnode, 83 CTLFLAG_PERMANENT, 84 CTLTYPE_NODE, "security", NULL, 85 NULL, 0, NULL, 0, 86 CTL_SECURITY, CTL_EOL); 87 88 sysctl_createv(clog, 0, &rnode, &rnode, 89 CTLFLAG_PERMANENT, 90 CTLTYPE_NODE, "models", NULL, 91 NULL, 0, NULL, 0, 92 CTL_CREATE, CTL_EOL); 93 94 sysctl_createv(clog, 0, &rnode, &rnode, 95 CTLFLAG_PERMANENT, 96 CTLTYPE_NODE, "keylock", 97 SYSCTL_DESCR("Keylock security model"), 98 NULL, 0, NULL, 0, 99 CTL_CREATE, CTL_EOL); 100 101 sysctl_createv(clog, 0, &rnode, NULL, 102 CTLFLAG_PERMANENT, 103 CTLTYPE_STRING, "name", NULL, 104 NULL, 0, __UNCONST("Keylock"), 0, 105 CTL_CREATE, CTL_EOL); 106} 107 108void 109secmodel_keylock_init(void) 110{ 111 int error = secmodel_register(&keylock_sm, 112 "org.netbsd.secmodel.keylock", 113 "NetBSD Security Model: Keylock", NULL, NULL, NULL); 114 if (error != 0) 115 printf("secmodel_keylock_init: secmodel_register " 116 "returned %d\n", error); 117} 118 119void 120secmodel_keylock_start(void) 121{ 122 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 123 secmodel_keylock_system_cb, NULL); 124 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 125 secmodel_keylock_process_cb, NULL); 126 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 127 secmodel_keylock_network_cb, NULL); 128 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 129 secmodel_keylock_machdep_cb, NULL); 130 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 131 secmodel_keylock_device_cb, NULL); 132} 133 134void 135secmodel_keylock_stop(void) 136{ 137 int error; 138 139 kauth_unlisten_scope(l_system); 140 kauth_unlisten_scope(l_process); 141 kauth_unlisten_scope(l_network); 142 kauth_unlisten_scope(l_machdep); 143 kauth_unlisten_scope(l_device); 144 145 error = secmodel_deregister(&keylock_sm); 146 if (error != 0) 147 printf("secmodel_keylock_stop: secmodel_deregister " 148 "returned %d\n", error); 149} 150 151/* 152 * kauth(9) listener 153 * 154 * Security model: Multi-position keylock 155 * Scope: System 156 * Responsibility: Keylock 157 */ 158int 159secmodel_keylock_system_cb(kauth_cred_t cred, 160 kauth_action_t action, void *cookie, void *arg0, void *arg1, 161 void *arg2, void *arg3) 162{ 163 int result; 164 enum kauth_system_req req; 165 int kstate; 166 167 kstate = keylock_state(); 168 if (kstate == KEYLOCK_ABSENT) 169 return KAUTH_RESULT_DEFER; 170 else if (kstate == KEYLOCK_TAMPER) 171 return KAUTH_RESULT_DENY; 172 173 result = KAUTH_RESULT_DEFER; 174 req = (enum kauth_system_req)arg0; 175 176 switch (action) { 177 case KAUTH_SYSTEM_CHSYSFLAGS: 178 if (kstate == KEYLOCK_CLOSE) 179 result = KAUTH_RESULT_DENY; 180 break; 181 182 case KAUTH_SYSTEM_TIME: 183 switch (req) { 184 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: 185 if (kstate == KEYLOCK_CLOSE) 186 result = KAUTH_RESULT_DENY; 187 break; 188 189 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { 190 struct timespec *ts = arg1; 191 struct timespec *delta = arg2; 192 193 if (keylock_position() > 1 && time_wraps(ts, delta)) 194 result = KAUTH_RESULT_DENY; 195 break; 196 } 197 default: 198 break; 199 } 200 break; 201 202 case KAUTH_SYSTEM_MODULE: 203 if (kstate == KEYLOCK_CLOSE) 204 result = KAUTH_RESULT_DENY; 205 break; 206 207 case KAUTH_SYSTEM_MOUNT: 208 switch (req) { 209 case KAUTH_REQ_SYSTEM_MOUNT_NEW: 210 if (kstate == KEYLOCK_CLOSE) 211 result = KAUTH_RESULT_DENY; 212 213 break; 214 215 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: 216 if (kstate == KEYLOCK_CLOSE) { 217 struct mount *mp = arg1; 218 u_long flags = (u_long)arg2; 219 220 /* 221 * Can only degrade from read/write to 222 * read-only. 223 */ 224 if (flags != (mp->mnt_flag | MNT_RDONLY | 225 MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) 226 result = KAUTH_RESULT_DENY; 227 } 228 break; 229 default: 230 break; 231 } 232 233 break; 234 235 case KAUTH_SYSTEM_SYSCTL: 236 switch (req) { 237 case KAUTH_REQ_SYSTEM_SYSCTL_ADD: 238 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: 239 case KAUTH_REQ_SYSTEM_SYSCTL_DESC: 240 if (kstate == KEYLOCK_CLOSE) 241 result = KAUTH_RESULT_DENY; 242 break; 243 default: 244 break; 245 } 246 break; 247 248 case KAUTH_SYSTEM_SETIDCORE: 249 if (kstate == KEYLOCK_CLOSE) 250 result = KAUTH_RESULT_DENY; 251 break; 252 253 case KAUTH_SYSTEM_DEBUG: 254 switch (req) { 255 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB: 256 if (kstate == KEYLOCK_CLOSE) 257 result = KAUTH_RESULT_DENY; 258 break; 259 default: 260 break; 261 } 262 break; 263 } 264 265 return result; 266} 267 268/* 269 * kauth(9) listener 270 * 271 * Security model: Multi-position keylock 272 * Scope: Process 273 * Responsibility: Keylock 274 */ 275int 276secmodel_keylock_process_cb(kauth_cred_t cred, 277 kauth_action_t action, void *cookie, void *arg0, 278 void *arg1, void *arg2, void *arg3) 279{ 280 struct proc *p; 281 int result, kstate; 282 283 kstate = keylock_state(); 284 if (kstate == KEYLOCK_ABSENT) 285 return KAUTH_RESULT_DEFER; 286 else if (kstate == KEYLOCK_TAMPER) 287 return KAUTH_RESULT_DENY; 288 289 result = KAUTH_RESULT_DEFER; 290 p = arg0; 291 292 switch (action) { 293 case KAUTH_PROCESS_PROCFS: { 294 enum kauth_process_req req; 295 296 req = (enum kauth_process_req)arg2; 297 switch (req) { 298 case KAUTH_REQ_PROCESS_PROCFS_READ: 299 break; 300 301 case KAUTH_REQ_PROCESS_PROCFS_RW: 302 case KAUTH_REQ_PROCESS_PROCFS_WRITE: 303 if ((p == initproc) && (kstate != KEYLOCK_OPEN)) 304 result = KAUTH_RESULT_DENY; 305 306 break; 307 default: 308 break; 309 } 310 311 break; 312 } 313 314 case KAUTH_PROCESS_PTRACE: 315 if ((p == initproc) && (kstate != KEYLOCK_OPEN)) 316 result = KAUTH_RESULT_DENY; 317 318 break; 319 320 case KAUTH_PROCESS_CORENAME: 321 if (kstate == KEYLOCK_CLOSE) 322 result = KAUTH_RESULT_DENY; 323 break; 324 } 325 return result; 326} 327 328/* 329 * kauth(9) listener 330 * 331 * Security model: Multi-position keylock 332 * Scope: Network 333 * Responsibility: Keylock 334 */ 335int 336secmodel_keylock_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, kstate; 341 enum kauth_network_req req; 342 343 kstate = keylock_state(); 344 if (kstate == KEYLOCK_ABSENT) 345 return KAUTH_RESULT_DEFER; 346 else if (kstate == KEYLOCK_TAMPER) 347 return KAUTH_RESULT_DENY; 348 349 result = KAUTH_RESULT_DEFER; 350 req = (enum kauth_network_req)arg0; 351 352 switch (action) { 353 case KAUTH_NETWORK_FIREWALL: 354 switch (req) { 355 case KAUTH_REQ_NETWORK_FIREWALL_FW: 356 case KAUTH_REQ_NETWORK_FIREWALL_NAT: 357 if (kstate == KEYLOCK_CLOSE) 358 result = KAUTH_RESULT_DENY; 359 break; 360 361 default: 362 break; 363 } 364 break; 365 366 case KAUTH_NETWORK_FORWSRCRT: 367 if (kstate != KEYLOCK_OPEN) 368 result = KAUTH_RESULT_DENY; 369 break; 370 } 371 372 return result; 373} 374 375/* 376 * kauth(9) listener 377 * 378 * Security model: Multi-position keylock 379 * Scope: Machdep 380 * Responsibility: Keylock 381 */ 382int 383secmodel_keylock_machdep_cb(kauth_cred_t cred, 384 kauth_action_t action, void *cookie, void *arg0, 385 void *arg1, void *arg2, void *arg3) 386{ 387 int result, kstate; 388 389 kstate = keylock_state(); 390 if (kstate == KEYLOCK_ABSENT) 391 return KAUTH_RESULT_DEFER; 392 else if (kstate == KEYLOCK_TAMPER) 393 return KAUTH_RESULT_DENY; 394 395 result = KAUTH_RESULT_DEFER; 396 397 switch (action) { 398 case KAUTH_MACHDEP_IOPERM_SET: 399 case KAUTH_MACHDEP_IOPL: 400 if (kstate != KEYLOCK_OPEN) 401 result = KAUTH_RESULT_DENY; 402 break; 403 404 case KAUTH_MACHDEP_UNMANAGEDMEM: 405 if (kstate != KEYLOCK_OPEN) 406 result = KAUTH_RESULT_DENY; 407 break; 408 } 409 410 return result; 411} 412 413/* 414 * kauth(9) listener 415 * 416 * Security model: Multi-position keylock 417 * Scope: Device 418 * Responsibility: Keylock 419 */ 420int 421secmodel_keylock_device_cb(kauth_cred_t cred, 422 kauth_action_t action, void *cookie, void *arg0, 423 void *arg1, void *arg2, void *arg3) 424{ 425 int result, kstate, error; 426 427 kstate = keylock_state(); 428 if (kstate == KEYLOCK_ABSENT) 429 return KAUTH_RESULT_DEFER; 430 else if (kstate == KEYLOCK_TAMPER) 431 return KAUTH_RESULT_DENY; 432 433 result = KAUTH_RESULT_DEFER; 434 435 switch (action) { 436 case KAUTH_DEVICE_RAWIO_SPEC: { 437 struct vnode *vp; 438 enum kauth_device_req req; 439 440 req = (enum kauth_device_req)arg0; 441 vp = arg1; 442 443 KASSERT(vp != NULL); 444 445 /* Handle /dev/mem and /dev/kmem. */ 446 if (iskmemvp(vp)) { 447 switch (req) { 448 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 449 break; 450 451 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 452 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 453 if (kstate != KEYLOCK_OPEN) 454 result = KAUTH_RESULT_DENY; 455 break; 456 default: 457 break; 458 } 459 break; 460 } 461 462 switch (req) { 463 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: 464 break; 465 466 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: 467 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: 468 error = rawdev_mounted(vp, NULL); 469 470 if (error == EINVAL) 471 break; 472 473 if (error && (kstate != KEYLOCK_OPEN)) 474 break; 475 476 if (kstate == KEYLOCK_CLOSE) 477 result = KAUTH_RESULT_DENY; 478 479 break; 480 default: 481 break; 482 } 483 break; 484 } 485 486 case KAUTH_DEVICE_RAWIO_PASSTHRU: 487 if (kstate != KEYLOCK_OPEN) { 488 u_long bits; 489 490 bits = (u_long)arg0; 491 492 KASSERT(bits != 0); 493 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) 494 == 0); 495 496 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) 497 result = KAUTH_RESULT_DENY; 498 } 499 break; 500 501 case KAUTH_DEVICE_GPIO_PINSET: 502 if (kstate != KEYLOCK_OPEN) 503 result = KAUTH_RESULT_DENY; 504 break; 505 default: 506 break; 507 } 508 return result; 509} 510