1.\" $NetBSD: secmodel.9,v 1.16 2009/05/10 21:23:48 wiz 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.Dd May 10, 2009 29.Dt SECMODEL 9 30.Os 31.Sh NAME 32.Nm secmodel 33.Nd security model development guidelines 34.Sh SYNOPSIS 35.In secmodel/secmodel.h 36.Sh DESCRIPTION 37.Nx 38provides a complete abstraction of the underlying security model used with 39the operating system to a set of 40.Xr kauth 9 41scopes and actions. 42.Pp 43It is possible to modify the security model -- either slightly or using an 44entirely different model -- by attaching/detaching 45.Xr kauth 9 46listeners. 47This document describes this process. 48.Ss Background 49In 50.Nx 4.0 , 51Kernel Authorization -- 52.Xr kauth 9 53-- was introduced as the subsystem responsible for authorization and 54credential management. 55Before its introduction, there were several ways for providing resource access 56control: 57.Bl -dash -offset indent -compact 58.It 59Checking if the user in question is the superuser via 60.Fn suser . 61.It 62Comparing the user-id against hard-coded values, often zero, 63.It 64Checking the system securelevel. 65.El 66.Pp 67The problem with the above is that the interface ("can X do Y?") was 68tightly coupled with the implementation ("is X Z?"). 69.Xr kauth 9 70allowed us to separate them, dispatching requests with highly detailed 71context using 72a consistent and clear KPI. 73.Pp 74The result is a pluggable framework for attaching "listeners" that can 75modify the behavior of the system, security-wise. 76It allows us to maintain the existing security model (based on a single 77superuser and above-superuser restrictions known as securelevel) but easily 78decouple it from the system, given we want to use a different one. 79.Pp 80The different security model can be implemented in the kernel or loaded as a 81module, base its decisions on available information, dispatch the decision to a 82userspace daemon, or even to a centralized network authorization server. 83.Ss The kauth(9) KPI 84Before writing a new security model, one should be familiar with the 85.Xr kauth 9 86KPI, its limitations, requirements, and so on. 87.Pp 88First, some terminology. 89According to 90.Xr kauth 9 , 91the system is logically divided to scopes, where each scope denotes a 92different area of interest in the system -- something like a namespace. 93For example, 94.Nx 95has the process, network, and machdep scopes, representing process-related, 96network-related, and machdep-related actions. 97.Pp 98Each scope has a collection of actions -- or requests -- forming the high 99level indication of the request type. 100Each request is automatically associated with credentials and between zero 101to four arguments providing the request context. 102.Pp 103For example, in the process scope there are requests such as "can signal", 104"can change rlimits", and "can change corename". 105.Pp 106Each scope in the system is associated with listeners, which are actually 107callback routines, that get called when an authorization request on the 108relevant scope takes place. 109.Pp 110Every listener receives the request and its context, and can make a decision 111of either "allow", "deny", or "defer" (if it doesn't want to be the one 112deciding). 113.Pp 114It is important to note that a single "deny" is enough to fail a request, 115and at least a single "allow" is required to allow it. 116In other words, it is impossible to attach listeners that weaken the security 117of the system or override decisions made by other listeners. 118.Pp 119At last, there are several things you should remember about 120.Xr kauth 9 : 121.Bl -dash -offset indent 122.It 123Authorization requests can not be issued when the kernel is holding any 124locks. 125This is a requirement from kernel code, to allow designing security models 126where the request should be dispatched to userspace or a different host. 127.It 128Private listener data -- such as internal data-structures -- is entirely 129under the responsibility of the developer. 130Locking, synchronization, and garbage collection are all things that 131.Xr kauth 9 132does 133.Em not 134take care of for you! 135.El 136.Ss Writing a new security model 137A security model is composed of (code-wise) the following components: 138.Bl -enum -offset indent 139.It 140Entry routines, named 141.Fn secmodel_\*[Lt]model\*[Gt]_init 142and 143.Fn secmodel_\*[Lt]model\*[Gt]_start , 144used to initialize and start the security model. 145.Pp 146If the security model is to be started automatically by the kernel and is 147compiled in it, a function called 148.Fn secmodel_start 149can be added to call the model's start routine. 150.Pp 151If the security model is to be built and used as a module, another function 152called 153.Fn secmodel_\*[Lt]model\*[Gt]_stop , 154to stop the security model in case the module is to be unloaded. 155.It 156A sysctl(9) setup routine for the model. 157This should create an entry for the model in the 158.Xr sysctl 9 159namespace, under the "security.models.\*[Lt]model\*[Gt]" hierarchy. 160.Pp 161All "knobs" for the model should be located under the new node, as well 162as a mandatory "name" variable, indicating a descriptive human-readable 163name for the model. 164.Pp 165If the module is to be used as a module, explicit calls to the setup 166routine and 167.Fn sysctl_teardown 168are to be used to create and destroy the 169.Xr sysctl 9 170tree. 171.It 172If the model uses any private data inside credentials, listening on 173the credentials scope, 174.Dv KAUTH_SCOPE_CRED , 175is required. 176.It 177Optionally, internal data-structures used by the model. 178These must all be prefixed with "secmodel_\*[Lt]model\*[Gt]_". 179.It 180A set of listeners, attached to various scopes, used to enforce the policy 181the model intends to implement. 182.It 183Finally, a security model should register itself when loaded using 184.Fn secmodel_register 185and deregister it when unloaded (if used as a module) using 186.Fn secmodel_deregister . 187.El 188.Pp 189Below is sample code for a 190.Xr kauth 9 191network scope listener for the 192.Em jenna 193security model. 194It is used to allow users with a user-id below 1000 bind to reserved ports 195(for example, 22/TCP): 196.Bd -literal -offset indent 197int 198secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 199 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 200{ 201 int result; 202 203 /* Default defer. */ 204 result = KAUTH_RESULT_DEFER; 205 206 switch (action) { 207 case KAUTH_NETWORK_BIND: 208 /* 209 * We only care about bind(2) requests to privileged 210 * ports. 211 */ 212 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 213 /* 214 * If the user-id is below 1000, which may 215 * indicate a "reserved" user-id, allow the 216 * request. 217 */ 218 if (kauth_cred_geteuid(cred) \*[Lt] 1000) 219 result = KAUTH_RESULT_ALLOW; 220 } 221 break; 222 } 223 224 return (result); 225} 226.Ed 227.Pp 228There are two main issues, however, with that listener, that you should be 229aware of when approaching to write your own security model: 230.Bl -enum -offset indent 231.It 232As mentioned, 233.Xr kauth 9 234uses restrictive decisions: if you attach this listener on-top of an existing 235security model, even if it would allow the request, it could still be failed. 236.It 237If you attach this listener as the only listener for the network scope, 238there are many other requests that will be deferred and, eventually, 239denied -- which may not be desired. 240.El 241.Pp 242That's why before implementing listeners, it should be clear whether they 243implement an entirely new from scratch security model, or add on-top of an 244existing one. 245.Ss Adding on-top of an existing security model 246One of the shortcomings of 247.Xr kauth 9 248is that it does not provide any stacking mechanism, similar to Linux Security 249Modules (LSM). 250This, however, is considered a feature in reducing dependency on other people's 251code. 252.Pp 253To properly "stack" minor adjustments on-top of an existing security model, 254one could use one of two approaches: 255.Bl -dash 256.It 257Registering an internal scope for the security model to be used as a 258fall-back when requests are deferred. 259.Pp 260This requires the security model developer to add an internal scope for 261every scope the model partly covers, and registering the fall-back 262listeners to it. 263In the model's listener(s) for the scope, when a defer decision is made, the 264request is passed to be authorized on the internal scope, effectively using 265the fall-back security model. 266.Pp 267Here's example code that implements the above: 268.Bd -literal -offset indent 269#include \*[Lt]secmodel/bsd44/bsd44.h\*[Gt] 270 271/* 272 * Internal fall-back scope for the network scope. 273 */ 274#define JENNA_ISCOPE_NETWORK "jenna.iscope.network" 275static kauth_scope_t secmodel_jenna_iscope_network; 276 277/* 278 * Jenna's entry point. Register internal scope for the network scope 279 * which we partly cover for fall-back authorization. 280 */ 281void 282secmodel_jenna_start(void) 283{ 284 secmodel_jenna_iscope_network = kauth_register_scope( 285 JENNA_ISCOPE_NETWORK, NULL, NULL); 286 287 kauth_listen_scope(JENNA_ISCOPE_NETWORK, 288 secmodel_bsd44_suser_network_cb, NULL); 289 kauth_listen_scope(JENNA_ISCOPE_NETWORK, 290 secmodel_securelevel_network_cb, NULL); 291} 292 293/* 294 * Jenna sits on top of another model, effectively filtering requests. 295 * If it has nothing to say, it discards the request. This is a good 296 * example for fine-tuning a security model for a special need. 297 */ 298int 299secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 300 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 301{ 302 int result; 303 304 /* Default defer. */ 305 result = KAUTH_RESULT_DEFER; 306 307 switch (action) { 308 case KAUTH_NETWORK_BIND: 309 /* 310 * We only care about bind(2) requests to privileged 311 * ports. 312 */ 313 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 314 if (kauth_cred_geteuid(cred) \*[Lt] 1000) 315 result = KAUTH_RESULT_ALLOW; 316 } 317 break; 318 } 319 320 /* 321 * If we have don't have a decision, fall-back to the bsd44 322 * security model. 323 */ 324 if (result == KAUTH_RESULT_DEFER) 325 result = kauth_authorize_action( 326 secmodel_jenna_iscope_network, cred, action, 327 arg0, arg1, arg2, arg3); 328 329 return (result); 330} 331.Ed 332.It 333If the above is not desired, or cannot be used for any reason, there is 334always the ability to manually call the fall-back routine: 335.Bd -literal -offset indent 336int 337secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 338 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 339{ 340 int result; 341 342 /* Default defer. */ 343 result = KAUTH_RESULT_DEFER; 344 345 switch (action) { 346 case KAUTH_NETWORK_BIND: 347 /* 348 * We only care about bind(2) requests to privileged 349 * ports. 350 */ 351 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 352 if (kauth_cred_geteuid(cred) \*[Lt] 1000) 353 result = KAUTH_RESULT_ALLOW; 354 } 355 break; 356 } 357 358 /* 359 * If we have don't have a decision, fall-back to the bsd44 360 * security model's suser behavior. 361 */ 362 if (result == KAUTH_RESULT_DEFER) 363 result = secmodel_bsd44_suser_network_cb(cred, action, 364 cookie, arg0, arg1, arg2, arg3); 365 366 return (result); 367} 368.Ed 369.El 370.Ss Writing a new security model from scratch 371When writing a security model from scratch, aside from the obvious issues of 372carefully following the desired policy to be implemented and paying attention 373to all of the issues outlined above, one must also remember that any unhandled 374requests will be denied by default. 375.Pp 376To make it easier on developers to write new security models from scratch, 377.Nx 378maintains skeleton listeners that contain every possible request and 379arguments. 380.Ss Available security models 381The following is a list of security models available in the default 382.Nx 383distribution. 384To choose, one should edit 385.Pa /usr/src/sys/conf/std . 386.Bl -tag -width secmodel_overlay 387.It secmodel_bsd44 388Traditional 389.Nx 390security model, derived from 391.Bx 4.4 . 392.It secmodel_overlay 393Sample overlay security model, sitting on-top of 394.Xr secmodel_bsd44 9 . 395.El 396.Sh FILES 397.Pa /usr/share/examples/secmodel 398.Sh SEE ALSO 399.Xr kauth 9 , 400.Xr secmodel_bsd44 9 , 401.Xr secmodel_overlay 9 402.Sh AUTHORS 403.An Elad Efrat Aq elad@NetBSD.org 404