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