1 /* $NetBSD: secmodel_overlay.c,v 1.13 2014/02/25 18:30:13 pooka 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.13 2014/02/25 18:30:13 pooka 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, "models", NULL, 138 NULL, 0, NULL, 0, 139 CTL_SECURITY, CTL_CREATE, CTL_EOL); 140 141 sysctl_createv(clog, 0, &rnode, &rnode, 142 CTLFLAG_PERMANENT, 143 CTLTYPE_NODE, "overlay", 144 SYSCTL_DESCR("Overlay security model on-top of bsd44"), 145 NULL, 0, NULL, 0, 146 CTL_CREATE, CTL_EOL); 147 148 sysctl_createv(clog, 0, &rnode, NULL, 149 CTLFLAG_PERMANENT, 150 CTLTYPE_STRING, "name", NULL, 151 NULL, 0, __UNCONST(SECMODEL_OVERLAY_NAME), 0, 152 CTL_CREATE, CTL_EOL); 153 } 154 155 /* 156 * Start the overlay security model. 157 */ 158 void 159 secmodel_overlay_start(void) 160 { 161 l_generic = kauth_listen_scope(KAUTH_SCOPE_GENERIC, 162 secmodel_overlay_generic_cb, NULL); 163 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 164 secmodel_overlay_system_cb, NULL); 165 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, 166 secmodel_overlay_process_cb, NULL); 167 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, 168 secmodel_overlay_network_cb, NULL); 169 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, 170 secmodel_overlay_machdep_cb, NULL); 171 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, 172 secmodel_overlay_device_cb, NULL); 173 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE, 174 secmodel_overlay_vnode_cb, NULL); 175 } 176 177 /* 178 * Stop the overlay security model. 179 */ 180 void 181 secmodel_overlay_stop(void) 182 { 183 kauth_unlisten_scope(l_generic); 184 kauth_unlisten_scope(l_system); 185 kauth_unlisten_scope(l_process); 186 kauth_unlisten_scope(l_network); 187 kauth_unlisten_scope(l_machdep); 188 kauth_unlisten_scope(l_device); 189 kauth_unlisten_scope(l_vnode); 190 } 191 192 static int 193 secmodel_overlay_modcmd(modcmd_t cmd, void *arg) 194 { 195 int error = 0; 196 197 switch (cmd) { 198 case MODULE_CMD_INIT: 199 error = secmodel_register(&overlay_sm, 200 SECMODEL_OVERLAY_ID, SECMODEL_OVERLAY_NAME, 201 NULL, NULL, NULL); 202 if (error != 0) 203 printf("secmodel_overlay_modcmd::init: " 204 "secmodel_register returned %d\n", error); 205 206 secmodel_overlay_init(); 207 secmodel_suser_stop(); 208 secmodel_securelevel_stop(); 209 secmodel_overlay_start(); 210 sysctl_security_overlay_setup(&sysctl_overlay_log); 211 break; 212 213 case MODULE_CMD_FINI: 214 sysctl_teardown(&sysctl_overlay_log); 215 secmodel_overlay_stop(); 216 217 error = secmodel_deregister(overlay_sm); 218 if (error != 0) 219 printf("secmodel_overlay_modcmd::fini: " 220 "secmodel_deregister returned %d\n", error); 221 break; 222 223 case MODULE_CMD_AUTOUNLOAD: 224 error = EPERM; 225 break; 226 227 default: 228 error = ENOTTY; 229 break; 230 } 231 232 return error; 233 } 234 235 /* 236 * Overlay listener for the generic scope. 237 */ 238 int 239 secmodel_overlay_generic_cb(kauth_cred_t cred, kauth_action_t action, 240 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 241 { 242 int result; 243 244 result = KAUTH_RESULT_DEFER; 245 246 switch (action) { 247 default: 248 result = KAUTH_RESULT_DEFER; 249 break; 250 } 251 252 if (result == KAUTH_RESULT_DEFER) { 253 result = kauth_authorize_action( 254 secmodel_overlay_iscope_generic, cred, action, 255 arg0, arg1, arg2, arg3); 256 } 257 258 return (result); 259 } 260 261 /* 262 * Overlay listener for the system scope. 263 */ 264 int 265 secmodel_overlay_system_cb(kauth_cred_t cred, kauth_action_t action, 266 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 267 { 268 int result; 269 270 result = KAUTH_RESULT_DEFER; 271 272 switch (action) { 273 default: 274 result = KAUTH_RESULT_DEFER; 275 break; 276 } 277 278 if (result == KAUTH_RESULT_DEFER) { 279 result = kauth_authorize_action( 280 secmodel_overlay_iscope_system, cred, action, 281 arg0, arg1, arg2, arg3); 282 } 283 284 return (result); 285 } 286 287 /* 288 * Overlay listener for the process scope. 289 */ 290 int 291 secmodel_overlay_process_cb(kauth_cred_t cred, kauth_action_t action, 292 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 293 { 294 int result; 295 296 result = KAUTH_RESULT_DEFER; 297 298 switch (action) { 299 default: 300 result = KAUTH_RESULT_DEFER; 301 break; 302 } 303 304 if (result == KAUTH_RESULT_DEFER) { 305 result = kauth_authorize_action( 306 secmodel_overlay_iscope_process, cred, action, 307 arg0, arg1, arg2, arg3); 308 } 309 310 return (result); 311 } 312 313 /* 314 * Overlay listener for the network scope. 315 */ 316 int 317 secmodel_overlay_network_cb(kauth_cred_t cred, kauth_action_t action, 318 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 319 { 320 int result; 321 322 result = KAUTH_RESULT_DEFER; 323 324 switch (action) { 325 default: 326 result = KAUTH_RESULT_DEFER; 327 break; 328 } 329 330 if (result == KAUTH_RESULT_DEFER) { 331 result = kauth_authorize_action( 332 secmodel_overlay_iscope_network, cred, action, 333 arg0, arg1, arg2, arg3); 334 } 335 336 return (result); 337 } 338 339 /* 340 * Overlay listener for the machdep scope. 341 */ 342 int 343 secmodel_overlay_machdep_cb(kauth_cred_t cred, kauth_action_t action, 344 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 345 { 346 int result; 347 348 result = KAUTH_RESULT_DEFER; 349 350 switch (action) { 351 default: 352 result = KAUTH_RESULT_DEFER; 353 break; 354 } 355 356 if (result == KAUTH_RESULT_DEFER) { 357 result = kauth_authorize_action( 358 secmodel_overlay_iscope_machdep, cred, action, 359 arg0, arg1, arg2, arg3); 360 } 361 362 return (result); 363 } 364 365 /* 366 * Overlay listener for the device scope. 367 */ 368 int 369 secmodel_overlay_device_cb(kauth_cred_t cred, kauth_action_t action, 370 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 371 { 372 int result; 373 374 result = KAUTH_RESULT_DEFER; 375 376 switch (action) { 377 default: 378 result = KAUTH_RESULT_DEFER; 379 break; 380 } 381 382 if (result == KAUTH_RESULT_DEFER) { 383 result = kauth_authorize_action( 384 secmodel_overlay_iscope_device, cred, action, 385 arg0, arg1, arg2, arg3); 386 } 387 388 return (result); 389 } 390 391 /* 392 * Overlay listener for the vnode scope. 393 */ 394 int 395 secmodel_overlay_vnode_cb(kauth_cred_t cred, kauth_action_t action, 396 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 397 { 398 int result; 399 400 result = KAUTH_RESULT_DEFER; 401 402 switch (action) { 403 default: 404 result = KAUTH_RESULT_DEFER; 405 break; 406 } 407 408 if (result == KAUTH_RESULT_DEFER) { 409 result = kauth_authorize_action( 410 secmodel_overlay_iscope_vnode, cred, action, 411 arg0, arg1, arg2, arg3); 412 } 413 414 return (result); 415 } 416