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