1.\" $NetBSD: secmodel.9,v 1.23 2022/01/26 11:48:53 andvar 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 December 4, 2011 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.Ft int 37.Fn secmodel_register "secmodel_t *sm" "const char *id" "const char *name" \ 38 "prop_dictionary_t behavior" "secmodel_eval_t sm_eval" \ 39 "secmodel_setinfo_t sm_setinfo" 40.Ft int 41.Fn secmodel_deregister "secmodel_t sm" 42.Ft int 43.Fn secmodel_eval "const char *id" "const char *what" "void *arg" "void *ret" 44.Ft static int 45.Fn secmodel_<model>_eval "const char *what" "void *arg" \ 46 "void *ret" 47.Sh DESCRIPTION 48.Nx 49provides a complete abstraction of the underlying security model used within 50the operating system through a set of 51.Xr kauth 9 52scopes and actions. 53It allows maintaining the traditional security model (based on a single 54.Em super-user 55and above-super-user restrictions known as 56.Em securelevel ) 57while decoupling it easily from the system. 58.Pp 59It is possible to modify the security model \(em either slightly or 60using an entirely different model \(em by attaching/detaching 61.Xr kauth 9 62listeners. 63This can be done via the 64.Nm 65pluggable framework. 66.Pp 67A 68.Nm 69is typically implemented as a kernel 70.Xr module 9 , 71and can be either built-in statically or loaded dynamically at run-time. 72They base their decisions on available information, either directly from 73kernel, from a userspace daemon or even from a centralized network 74authorization server. 75.Sh DATA TYPES 76The 77.Nm 78framework offers the following data types: 79.Bl -tag -width secmodel_t 80.It Fa secmodel_t 81An opaque type that describes a 82.Nm . 83.El 84.Sh FUNCTIONS 85.Bl -tag -width xxxxxxx 86.It Fn secmodel_register "sm" "id" "name" "behavior" "sm_eval" "sm_setinfo" 87Register a security model to the 88.Nm 89framework and stores its description inside 90.Fa sm . 91.Bl -tag -width sm_setinfo 92.It Fa sm 93The 94.Nm 95description. 96.It Fa id 97The unique identifier of the 98.Nm . 99.It Fa name 100The descriptive human-readable name of the 101.Nm . 102.It Fa behavior 103(optional) a 104.Xr prop_dictionary 3 105that declares the behavior of this security model, like 106.Do copy credentials on fork . Dc 107.It Fa sm_eval 108(optional) the 109.Fn secmodel_<model>_eval 110callback used by a 111.Nm 112to register an evaluation routine that can be queried later 113by another security model. 114.It Fa sm_setinfo 115(optional) the 116.Fn secmodel_<model>_setinfo 117callback used by a 118.Nm 119to register a routine that permits other security models to 120alter the 121.Nm 122internals. 123Currently not implemented. 124.El 125.It Fn secmodel_deregister "sm" 126Deregister the 127.Nm 128described by 129.Fa sm . 130.It Fn secmodel_eval "id" "what" "arg" "ret" 131Call the evaluation callback implemented by a security model. 132The return value can be either: 133.Bl -dash -compact -offset xxxxxx 134.It 135zero (0), when the call succeeded. 136.It 137positive, when the error comes directly from the 138.Nm 139framework. 140.It 141negative, when the error comes from the evaluation callback 142implemented in the targeted security model. 143The value is then implementation-defined. 144.El 145.Pp 146.Bl -tag -width what 147.It Fa id 148The unique identifier of the targeted 149.Nm . 150.It Fa what 151The query that will be passed down to the targeted 152.Nm . 153.It Fa arg 154The arguments passed to the evaluation routine of the targeted 155.Nm . 156.It Fa ret 157The answer of the evaluation routine. 158.El 159.El 160.Sh RETURN VALUES 161If successful, functions return 0. 162Otherwise, the following error values are returned: 163.Bl -tag -width [EINVAL] 164.It Bq Er EEXIST 165The 166.Nm 167is already registered. 168.It Bq Er EFAULT 169An invalid address or reference was passed as parameter. 170.It Bq Er EINVAL 171An invalid value was passed as parameter. 172.It Bq Er ENOENT 173The targeted 174.Nm 175does not exist, or it does not implement an evaluation callback. 176.El 177.Sh WRITING A SECURITY MODEL 178Before writing a security model one should be familiar with the 179.Xr kauth 9 180KPI, its limitations, requirements, and so on. 181See 182.Xr kauth 9 183for details. 184.Pp 185A security model is based on the kernel 186.Xr module 9 187framework, and can be built-in statically inside kernel or 188loaded dynamically at run-time. 189It is composed of (code-wise) the following components: 190.Bl -enum -offset indent 191.It 192.Xr module 9 193routines, especially a 194.Fn MODULE 195declaration and a 196.Fn secmodel_<model>_modcmd 197function used to start 198.Po through Dv MODULE_CMD_INIT Pc 199and stop 200.Po through Dv MODULE_CMD_FINI Pc 201the 202.Nm . 203.It 204Entry routines, named 205.Fn secmodel_<model>_init 206and 207.Fn secmodel_<model>_start , 208used to initialize and start the security model, and another 209function called 210.Fn secmodel_<model>_stop , 211to stop the security model in case the module is to be unloaded. 212.It 213A 214.Xr sysctl 9 215setup routine for the model. 216This should create an entry for the model in the 217.Xr sysctl 7 218namespace, under the "security.models.<model>" hierarchy. 219.Pp 220All "knobs" for the model should be located under the new node, as well 221as a mandatory 222.Fa name 223variable, indicating a descriptive human-readable 224name for the model. 225.It 226A 227.Xr sysctl 9 228teardown routine used to destroy the 229.Xr sysctl 7 230tree associated with the model. 231.It 232If the model uses any private data inside credentials, listening on 233the credentials scope, 234.Dv KAUTH_SCOPE_CRED , 235is required. 236.It 237Optionally, internal data-structures used by the model. 238These must all be prefixed with "secmodel_<model>_". 239.It 240A set of listeners, attached to various scopes, used to enforce the policy 241the model intends to implement. 242.It 243Finally, a security model should register itself after being 244initialized using 245.Fn secmodel_register , 246and deregister itself before being stopped using 247.Fn secmodel_deregister . 248.El 249.Sh EXAMPLES 250Below is sample code for a 251.Xr kauth 9 252network scope listener for the 253.Em jenna 254security model. 255It is used to allow users with a user-id below 1000 to bind to reserved ports 256(for example, 22/TCP): 257.Bd -literal 258int 259secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 260 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 261{ 262 int result; 263 264 /* Default defer. */ 265 result = KAUTH_RESULT_DEFER; 266 267 switch (action) { 268 case KAUTH_NETWORK_BIND: 269 /* 270 * We only care about bind(2) requests to privileged 271 * ports. 272 */ 273 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 274 /* 275 * If the user-id is below 1000, which may 276 * indicate a "reserved" user-id, allow the 277 * request. 278 */ 279 if (kauth_cred_geteuid(cred) < 1000) 280 result = KAUTH_RESULT_ALLOW; 281 } 282 break; 283 } 284 285 return (result); 286} 287.Ed 288.Pp 289There are two main issues, however, with that listener, that you should be 290aware of when approaching to write your own security model: 291.Bl -enum -offset indent 292.It 293.Xr kauth 9 294uses restrictive decisions: if you attach this listener on-top of an existing 295security model, even if it would allow the request, it could still be denied. 296.It 297If you attach this listener as the only listener for the network scope, 298there are many other requests that will be deferred and, eventually, 299denied \(em which may not be desired. 300.El 301.Pp 302That's why before implementing listeners, it should be clear whether they 303implement an entirely new from scratch security model, or add on-top of an 304existing one. 305.Sh PROGRAMMING CONSIDERATIONS 306There are several things you should remember when writing a security model: 307.Bl -dash -offset indent 308.It 309Pay attention to the correctness of your 310.Nm 311implementation of the desired policy. 312Certain rights can grant more privileges on the system than others, 313like allowing calls to 314.Xr chroot 2 315or mounting a file-system. 316.It 317All unhandled requests are denied by default. 318.It 319Authorization requests can not be issued when the kernel is holding any 320locks. 321This is a requirement from kernel code to allow designing security models 322where the request should be dispatched to userspace or a different host. 323.It 324Private listener data \(em such as internal data structures \(em is 325entirely under the responsibility of the developer. 326Locking, synchronization, and garbage collection are all things that 327.Xr kauth 9 328does 329.Em not 330take care of for you! 331.El 332.Ss STACKING ON AN EXISTING SECURITY MODEL 333One of the shortcomings of 334.Xr kauth 9 335is that it does not provide any stacking mechanism, similar to Linux Security 336Modules (LSM). 337This, however, is considered a feature in reducing dependency on other people's 338code. 339.Pp 340To properly "stack" minor adjustments on-top of an existing security model, 341one could use one of two approaches: 342.Bl -enum 343.It 344Register an internal scope for the security model to be used as a 345fall-back when requests are deferred. 346.Pp 347This requires the security model developer to add an internal scope for 348every scope the model partly covers, and register the fall-back 349listeners to it. 350In the model's listener(s) for the scope, when a defer decision is made, the 351request is passed to be authorized on the internal scope, effectively using 352the fall-back security model. 353.Pp 354Here is example code that implements the above: 355.Bd -literal 356#include <secmodel/bsd44/bsd44.h> 357 358/* 359 * Internal fall-back scope for the network scope. 360 */ 361#define JENNA_ISCOPE_NETWORK "jenna.iscope.network" 362static kauth_scope_t secmodel_jenna_iscope_network; 363 364/* 365 * Jenna's entry point. Register internal scope for the network scope 366 * which we partly cover for fall-back authorization. 367 */ 368void 369secmodel_jenna_start(void) 370{ 371 secmodel_jenna_iscope_network = kauth_register_scope( 372 JENNA_ISCOPE_NETWORK, NULL, NULL); 373 374 kauth_listen_scope(JENNA_ISCOPE_NETWORK, 375 secmodel_bsd44_suser_network_cb, NULL); 376 kauth_listen_scope(JENNA_ISCOPE_NETWORK, 377 secmodel_securelevel_network_cb, NULL); 378} 379 380/* 381 * Jenna sits on top of another model, effectively filtering requests. 382 * If it has nothing to say, it discards the request. This is a good 383 * example for fine-tuning a security model for a special need. 384 */ 385int 386secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 387 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 388{ 389 int result; 390 391 /* Default defer. */ 392 result = KAUTH_RESULT_DEFER; 393 394 switch (action) { 395 case KAUTH_NETWORK_BIND: 396 /* 397 * We only care about bind(2) requests to privileged 398 * ports. 399 */ 400 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 401 if (kauth_cred_geteuid(cred) < 1000) 402 result = KAUTH_RESULT_ALLOW; 403 } 404 break; 405 } 406 407 /* 408 * If we have don't have a decision, fall-back to the bsd44 409 * security model. 410 */ 411 if (result == KAUTH_RESULT_DEFER) 412 result = kauth_authorize_action( 413 secmodel_jenna_iscope_network, cred, action, 414 arg0, arg1, arg2, arg3); 415 416 return (result); 417} 418.Ed 419.It 420If the above is not desired, or cannot be used for any reason, there is 421always the ability to manually call the fall-back routine: 422.Bd -literal 423int 424secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action, 425 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) 426{ 427 int result; 428 429 /* Default defer. */ 430 result = KAUTH_RESULT_DEFER; 431 432 switch (action) { 433 case KAUTH_NETWORK_BIND: 434 /* 435 * We only care about bind(2) requests to privileged 436 * ports. 437 */ 438 if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) { 439 if (kauth_cred_geteuid(cred) < 1000) 440 result = KAUTH_RESULT_ALLOW; 441 } 442 break; 443 } 444 445 /* 446 * If we have don't have a decision, fall-back to the bsd44 447 * security model's suser behavior. 448 */ 449 if (result == KAUTH_RESULT_DEFER) 450 result = secmodel_bsd44_suser_network_cb(cred, action, 451 cookie, arg0, arg1, arg2, arg3); 452 453 return (result); 454} 455.Ed 456.El 457.Sh AVAILABLE SECURITY MODELS 458The following is a list of security models available in the default 459.Nx 460distribution. 461.Bl -tag -width xxxxxxxx 462.It Xr secmodel_suser 9 463Implements the 464.Em super-user 465(root) security policy. 466.It Xr secmodel_securelevel 9 467Implements the 468.Em securelevel 469security model. 470.It Xr secmodel_extensions 9 471Implements extensions to the traditional 472.Bx 4.4 473security model, like usermounts. 474.It Xr secmodel_bsd44 9 475Traditional 476.Nx 477security model, derived from 478.Bx 4.4 . 479.It Xr secmodel_overlay 9 480Sample overlay security model, sitting on-top of 481.Xr secmodel_bsd44 9 . 482.El 483.Sh CODE REFERENCES 484The core of the 485.Nm 486implementation is in 487.Pa sys/secmodel/secmodel.c . 488.Pp 489The header file 490.In secmodel/secmodel.h 491describes the public interface. 492.Pp 493To make it easier on developers to write new security models from scratch, 494.Nx 495maintains an example 496.Nm 497under 498.Pa share/examples/secmodel/ . 499.Sh SEE ALSO 500.Xr kauth 9 , 501.Xr module 9 , 502.Xr secmodel_bsd44 9 , 503.Xr secmodel_extensions 9 , 504.Xr secmodel_overlay 9 , 505.Xr secmodel_securelevel 9 , 506.Xr secmodel_suser 9 507.Sh HISTORY 508Kernel Authorization was introduced in 509.Nx 4.0 510as the subsystem responsible for authorization and 511credential management. 512Before its introduction, there were several ways for providing resource access 513control: 514.Bl -dash -offset indent -compact 515.It 516Checking if the user in question is the super-user via 517.Fn suser . 518.It 519Comparing the user-id against hard-coded values, often zero. 520.It 521Checking the system securelevel. 522.El 523.Pp 524The problem with the above is that the interface ("can X do Y?") was 525tightly coupled with the implementation ("is X Z?"). 526.Xr kauth 9 527allows separating them, dispatching requests with highly detailed 528context using a consistent and clear KPI. 529.Pp 530The 531.Nm 532framework was extended in 533.Nx 6.0 534to implement 535.Nm 536registration and evaluation procedure calls. 537.Sh AUTHORS 538.An Elad Efrat Aq Mt elad@NetBSD.org 539