1 /* $NetBSD: secmodel_overlay.c,v 1.12 2011/12/04 19:25:00 jym 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 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: secmodel_overlay.c,v 1.12 2011/12/04 19:25:00 jym Exp $"); 31 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/kauth.h> 35 #include <sys/module.h> 36 37 #include <sys/sysctl.h> 38 39 #include <secmodel/secmodel.h> 40 41 #include <secmodel/overlay/overlay.h> 42 #include <secmodel/bsd44/bsd44.h> 43 #include <secmodel/suser/suser.h> 44 #include <secmodel/securelevel/securelevel.h> 45 46 MODULE(MODULE_CLASS_SECMODEL, secmodel_overlay, "secmodel_bsd44"); 47 48 /* 49 * Fall-back settings. 50 */ 51 #define OVERLAY_ISCOPE_GENERIC "org.netbsd.kauth.overlay.generic" 52 #define OVERLAY_ISCOPE_SYSTEM "org.netbsd.kauth.overlay.system" 53 #define OVERLAY_ISCOPE_PROCESS "org.netbsd.kauth.overlay.process" 54 #define OVERLAY_ISCOPE_NETWORK "org.netbsd.kauth.overlay.network" 55 #define OVERLAY_ISCOPE_MACHDEP "org.netbsd.kauth.overlay.machdep" 56 #define OVERLAY_ISCOPE_DEVICE "org.netbsd.kauth.overlay.device" 57 #define OVERLAY_ISCOPE_VNODE "org.netbsd.kauth.overlay.vnode" 58 59 static kauth_scope_t secmodel_overlay_iscope_generic; 60 static kauth_scope_t secmodel_overlay_iscope_system; 61 static kauth_scope_t secmodel_overlay_iscope_process; 62 static kauth_scope_t secmodel_overlay_iscope_network; 63 static kauth_scope_t secmodel_overlay_iscope_machdep; 64 static kauth_scope_t secmodel_overlay_iscope_device; 65 static kauth_scope_t secmodel_overlay_iscope_vnode; 66 67 static kauth_listener_t l_generic, l_system, l_process, l_network, l_machdep, 68 l_device, l_vnode; 69 70 static secmodel_t overlay_sm; 71 static struct sysctllog *sysctl_overlay_log; 72 73 /* 74 * Initialize the overlay security model. 75 */ 76 void 77 secmodel_overlay_init(void) 78 { 79 /* 80 * Register internal fall-back scopes. 81 */ 82 secmodel_overlay_iscope_generic = kauth_register_scope( 83 OVERLAY_ISCOPE_GENERIC, NULL, NULL); 84 secmodel_overlay_iscope_system = kauth_register_scope( 85 OVERLAY_ISCOPE_SYSTEM, NULL, NULL); 86 secmodel_overlay_iscope_process = kauth_register_scope( 87 OVERLAY_ISCOPE_PROCESS, NULL, NULL); 88 secmodel_overlay_iscope_network = kauth_register_scope( 89 OVERLAY_ISCOPE_NETWORK, NULL, NULL); 90 secmodel_overlay_iscope_machdep = kauth_register_scope( 91 OVERLAY_ISCOPE_MACHDEP, NULL, NULL); 92 secmodel_overlay_iscope_device = kauth_register_scope( 93 OVERLAY_ISCOPE_DEVICE, NULL, NULL); 94 secmodel_overlay_iscope_vnode = kauth_register_scope( 95 OVERLAY_ISCOPE_VNODE, NULL, NULL); 96 97 /* 98 * Register fall-back listeners, from suser and securelevel, to each 99 * internal scope. 100 */ 101 kauth_listen_scope(OVERLAY_ISCOPE_GENERIC, 102 secmodel_suser_generic_cb, NULL); 103 104 kauth_listen_scope(OVERLAY_ISCOPE_SYSTEM, 105 secmodel_suser_system_cb, NULL); 106 kauth_listen_scope(OVERLAY_ISCOPE_SYSTEM, 107 secmodel_securelevel_system_cb, NULL); 108 109 kauth_listen_scope(OVERLAY_ISCOPE_PROCESS, 110 secmodel_suser_process_cb, NULL); 111 kauth_listen_scope(OVERLAY_ISCOPE_PROCESS, 112 secmodel_securelevel_process_cb, NULL); 113 114 kauth_listen_scope(OVERLAY_ISCOPE_NETWORK, 115 secmodel_suser_network_cb, NULL); 116 kauth_listen_scope(OVERLAY_ISCOPE_NETWORK, 117 secmodel_securelevel_network_cb, NULL); 118 119 kauth_listen_scope(OVERLAY_ISCOPE_MACHDEP, 120 secmodel_suser_machdep_cb, NULL); 121 kauth_listen_scope(OVERLAY_ISCOPE_MACHDEP, 122 secmodel_securelevel_machdep_cb, NULL); 123 124 kauth_listen_scope(OVERLAY_ISCOPE_DEVICE, 125 secmodel_suser_device_cb, NULL); 126 kauth_listen_scope(OVERLAY_ISCOPE_DEVICE, 127 secmodel_securelevel_device_cb, NULL); 128 } 129 130 void 131 sysctl_security_overlay_setup(struct sysctllog **clog) 132 { 133 const struct sysctlnode *rnode; 134 135 sysctl_createv(clog, 0, NULL, &rnode, 136 CTLFLAG_PERMANENT, 137 CTLTYPE_NODE, "security", NULL, 138 NULL, 0, NULL, 0, 139 CTL_SECURITY, CTL_EOL); 140 141 sysctl_createv(clog, 0, &rnode, &rnode, 142 CTLFLAG_PERMANENT, 143 CTLTYPE_NODE, "models", NULL, 144 NULL, 0, NULL, 0, 145 CTL_CREATE, CTL_EOL); 146 147 sysctl_createv(clog, 0, &rnode, &rnode, 148 CTLFLAG_PERMANENT, 149 CTLTYPE_NODE, "overlay", 150 SYSCTL_DESCR("Overlay security model on-top of bsd44"), 151 NULL, 0, NULL, 0, 152 CTL_CREATE, CTL_EOL); 153 154 sysctl_createv(clog, 0, &rnode, NULL, 155 CTLFLAG_PERMANENT, 156 CTLTYPE_STRING, "name", NULL, 157 NULL, 0, __UNCONST(SECMODEL_OVERLAY_NAME), 0, 158 CTL_CREATE, CTL_EOL); 159 } 160 161 /* 162 * Start the overlay security model. 163 */ 164 void 165 secmodel_overlay_start(void) 166 { 167 l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC, 168 secmodel_overlay_generic_cb, NULL); 169 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 170 secmodel_overlay_system_cb, NULL); 171 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 172 secmodel_overlay_process_cb, NULL); 173 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 174 secmodel_overlay_network_cb, NULL); 175 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 176 secmodel_overlay_machdep_cb, NULL); 177 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 178 secmodel_overlay_device_cb, NULL); 179 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE, 180 secmodel_overlay_vnode_cb, NULL); 181 } 182 183 /* 184 * Stop the overlay security model. 185 */ 186 void 187 secmodel_overlay_stop(void) 188 { 189 kauth_unlisten_scope(l_generic); 190 kauth_unlisten_scope(l_system); 191 kauth_unlisten_scope(l_process); 192 kauth_unlisten_scope(l_network); 193 kauth_unlisten_scope(l_machdep); 194 kauth_unlisten_scope(l_device); 195 kauth_unlisten_scope(l_vnode); 196 } 197 198 static int 199 secmodel_overlay_modcmd(modcmd_t cmd, void *arg) 200 { 201 int error = 0; 202 203 switch (cmd) { 204 case MODULE_CMD_INIT: 205 error = secmodel_register(&overlay_sm, 206 SECMODEL_OVERLAY_ID, SECMODEL_OVERLAY_NAME, 207 NULL, NULL, NULL); 208 if (error != 0) 209 printf("secmodel_overlay_modcmd::init: " 210 "secmodel_register returned %d\n", error); 211 212 secmodel_overlay_init(); 213 secmodel_suser_stop(); 214 secmodel_securelevel_stop(); 215 secmodel_overlay_start(); 216 sysctl_security_overlay_setup(&sysctl_overlay_log); 217 break; 218 219 case MODULE_CMD_FINI: 220 sysctl_teardown(&sysctl_overlay_log); 221 secmodel_overlay_stop(); 222 223 error = secmodel_deregister(overlay_sm); 224 if (error != 0) 225 printf("secmodel_overlay_modcmd::fini: " 226 "secmodel_deregister returned %d\n", error); 227 break; 228 229 case MODULE_CMD_AUTOUNLOAD: 230 error = EPERM; 231 break; 232 233 default: 234 error = ENOTTY; 235 break; 236 } 237 238 return error; 239 } 240 241 /* 242 * Overlay listener for the generic scope. 243 */ 244 int 245 secmodel_overlay_generic_cb(kauth_cred_t cred, kauth_action_t action, 246 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 247 { 248 int result; 249 250 result = KAUTH_RESULT_DEFER; 251 252 switch (action) { 253 default: 254 result = KAUTH_RESULT_DEFER; 255 break; 256 } 257 258 if (result == KAUTH_RESULT_DEFER) { 259 result = kauth_authorize_action( 260 secmodel_overlay_iscope_generic, cred, action, 261 arg0, arg1, arg2, arg3); 262 } 263 264 return (result); 265 } 266 267 /* 268 * Overlay listener for the system scope. 269 */ 270 int 271 secmodel_overlay_system_cb(kauth_cred_t cred, kauth_action_t action, 272 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 273 { 274 int result; 275 276 result = KAUTH_RESULT_DEFER; 277 278 switch (action) { 279 default: 280 result = KAUTH_RESULT_DEFER; 281 break; 282 } 283 284 if (result == KAUTH_RESULT_DEFER) { 285 result = kauth_authorize_action( 286 secmodel_overlay_iscope_system, cred, action, 287 arg0, arg1, arg2, arg3); 288 } 289 290 return (result); 291 } 292 293 /* 294 * Overlay listener for the process scope. 295 */ 296 int 297 secmodel_overlay_process_cb(kauth_cred_t cred, kauth_action_t action, 298 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 299 { 300 int result; 301 302 result = KAUTH_RESULT_DEFER; 303 304 switch (action) { 305 default: 306 result = KAUTH_RESULT_DEFER; 307 break; 308 } 309 310 if (result == KAUTH_RESULT_DEFER) { 311 result = kauth_authorize_action( 312 secmodel_overlay_iscope_process, cred, action, 313 arg0, arg1, arg2, arg3); 314 } 315 316 return (result); 317 } 318 319 /* 320 * Overlay listener for the network scope. 321 */ 322 int 323 secmodel_overlay_network_cb(kauth_cred_t cred, kauth_action_t action, 324 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 325 { 326 int result; 327 328 result = KAUTH_RESULT_DEFER; 329 330 switch (action) { 331 default: 332 result = KAUTH_RESULT_DEFER; 333 break; 334 } 335 336 if (result == KAUTH_RESULT_DEFER) { 337 result = kauth_authorize_action( 338 secmodel_overlay_iscope_network, cred, action, 339 arg0, arg1, arg2, arg3); 340 } 341 342 return (result); 343 } 344 345 /* 346 * Overlay listener for the machdep scope. 347 */ 348 int 349 secmodel_overlay_machdep_cb(kauth_cred_t cred, kauth_action_t action, 350 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 351 { 352 int result; 353 354 result = KAUTH_RESULT_DEFER; 355 356 switch (action) { 357 default: 358 result = KAUTH_RESULT_DEFER; 359 break; 360 } 361 362 if (result == KAUTH_RESULT_DEFER) { 363 result = kauth_authorize_action( 364 secmodel_overlay_iscope_machdep, cred, action, 365 arg0, arg1, arg2, arg3); 366 } 367 368 return (result); 369 } 370 371 /* 372 * Overlay listener for the device scope. 373 */ 374 int 375 secmodel_overlay_device_cb(kauth_cred_t cred, kauth_action_t action, 376 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 377 { 378 int result; 379 380 result = KAUTH_RESULT_DEFER; 381 382 switch (action) { 383 default: 384 result = KAUTH_RESULT_DEFER; 385 break; 386 } 387 388 if (result == KAUTH_RESULT_DEFER) { 389 result = kauth_authorize_action( 390 secmodel_overlay_iscope_device, cred, action, 391 arg0, arg1, arg2, arg3); 392 } 393 394 return (result); 395 } 396 397 /* 398 * Overlay listener for the vnode scope. 399 */ 400 int 401 secmodel_overlay_vnode_cb(kauth_cred_t cred, kauth_action_t action, 402 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 403 { 404 int result; 405 406 result = KAUTH_RESULT_DEFER; 407 408 switch (action) { 409 default: 410 result = KAUTH_RESULT_DEFER; 411 break; 412 } 413 414 if (result == KAUTH_RESULT_DEFER) { 415 result = kauth_authorize_action( 416 secmodel_overlay_iscope_vnode, cred, action, 417 arg0, arg1, arg2, arg3); 418 } 419 420 return (result); 421 } 422