Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
.\" $NetBSD: secmodel.9,v 1.22 2017/07/03 21:28:48 wiz Exp $
.\"
.\" Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\"    derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd December 4, 2011
.Dt SECMODEL 9
.Os
.Sh NAME
.Nm secmodel
.Nd security model development guidelines
.Sh SYNOPSIS
.In secmodel/secmodel.h
.Ft int
.Fn secmodel_register "secmodel_t *sm" "const char *id" "const char *name" \
    "prop_dictionary_t behavior" "secmodel_eval_t sm_eval" \
    "secmodel_setinfo_t sm_setinfo"
.Ft int
.Fn secmodel_deregister "secmodel_t sm"
.Ft int
.Fn secmodel_eval "const char *id" "const char *what" "void *arg" "void *ret"
.Ft static int
.Fn secmodel_<model>_eval "const char *what" "void *arg" \
    "void *ret"
.Sh DESCRIPTION
.Nx
provides a complete abstraction of the underlying security model used within
the operating system through a set of
.Xr kauth 9
scopes and actions.
It allows maintaining the traditional security model (based on a single
.Em super-user
and above-super-user restrictions known as
.Em securelevel )
while decoupling it easily from the system.
.Pp
It is possible to modify the security model \(em either slightly or
using an entirely different model \(em by attaching/detaching
.Xr kauth 9
listeners.
This can be done via the
.Nm
pluggable framework.
.Pp
A
.Nm
is typically implemented as a kernel
.Xr module 9 ,
and can be either built-in statically or loaded dynamically at run-time.
They base their decisions on available information, either directly from
kernel, from a userspace daemon or even from a centralized network
authorization server.
.Sh DATA TYPES
The
.Nm
framework offers the following data types:
.Bl -tag -width secmodel_t
.It Fa secmodel_t
An opaque type that describes a
.Nm .
.El
.Sh FUNCTIONS
.Bl -tag -width xxxxxxx
.It Fn secmodel_register "sm" "id" "name" "behavior" "sm_eval" "sm_setinfo"
Register a security model to the
.Nm
framework and stores its description inside
.Fa sm .
.Bl -tag -width sm_setinfo
.It Fa sm
The
.Nm
description.
.It Fa id
The unique identifier of the
.Nm .
.It Fa name
The descriptive human-readable name of the
.Nm .
.It Fa behavior
(optional) a
.Xr prop_dictionary 3
that declares the behavior of this security model, like
.Do copy credentials on fork . Dc
.It Fa sm_eval
(optional) the
.Fn secmodel_<model>_eval
callback used by a
.Nm
to register an evaluation routine that can be queried later
by another security model.
.It Fa sm_setinfo
(optional) the
.Fn secmodel_<model>_setinfo
callback used by a
.Nm
to register a routine that permits other security models to
alter the
.Nm
internals.
Currently not implemented.
.El
.It Fn secmodel_deregister "sm"
Deregister the
.Nm
described by
.Fa sm .
.It Fn secmodel_eval "id" "what" "arg" "ret"
Call the evaluation callback implemented by a security model.
The return value can be either:
.Bl -dash -compact -offset xxxxxx
.It
zero (0), when the call succeeded.
.It
positive, when the error comes directly from the
.Nm
framework.
.It
negative, when the error comes from the evaluation callback
implemented in the targetted security model.
The value is then implementation-defined.
.El
.Pp
.Bl -tag -width what
.It Fa id
The unique identifier of the targetted
.Nm .
.It Fa what
The query that will be passed down to the targetted
.Nm .
.It Fa arg
The arguments passed to the evaluation routine of the targetted
.Nm .
.It Fa ret
The answer of the evaluation routine.
.El
.El
.Sh RETURN VALUES
If successful, functions return 0.
Otherwise, the following error values are returned:
.Bl -tag -width [EINVAL]
.It Bq Er EEXIST
The
.Nm
is already registered.
.It Bq Er EFAULT
An invalid address or reference was passed as parameter.
.It Bq Er EINVAL
An invalid value was passed as parameter.
.It Bq Er ENOENT
The targetted
.Nm
does not exist, or it does not implement an evaluation callback.
.El
.Sh WRITING A SECURITY MODEL
Before writing a security model one should be familiar with the
.Xr kauth 9
KPI, its limitations, requirements, and so on.
See
.Xr kauth 9
for details.
.Pp
A security model is based on the kernel
.Xr module 9
framework, and can be built-in statically inside kernel or
loaded dynamically at run-time.
It is composed of (code-wise) the following components:
.Bl -enum -offset indent
.It
.Xr module 9
routines, especially a
.Fn MODULE
declaration and a
.Fn secmodel_<model>_modcmd
function used to start
.Po through Dv MODULE_CMD_INIT Pc
and stop
.Po through Dv MODULE_CMD_FINI Pc
the
.Nm .
.It
Entry routines, named
.Fn secmodel_<model>_init
and
.Fn secmodel_<model>_start ,
used to initialize and start the security model, and another
function called
.Fn secmodel_<model>_stop ,
to stop the security model in case the module is to be unloaded.
.It
A
.Xr sysctl 9
setup routine for the model.
This should create an entry for the model in the
.Xr sysctl 7
namespace, under the "security.models.<model>" hierarchy.
.Pp
All "knobs" for the model should be located under the new node, as well
as a mandatory
.Fa name
variable, indicating a descriptive human-readable
name for the model.
.It
A
.Xr sysctl 9
teardown routine used to destroy the
.Xr sysctl 7
tree associated with the model.
.It
If the model uses any private data inside credentials, listening on
the credentials scope,
.Dv KAUTH_SCOPE_CRED ,
is required.
.It
Optionally, internal data-structures used by the model.
These must all be prefixed with "secmodel_<model>_".
.It
A set of listeners, attached to various scopes, used to enforce the policy
the model intends to implement.
.It
Finally, a security model should register itself after being
initialized using
.Fn secmodel_register ,
and deregister itself before being stopped using
.Fn secmodel_deregister .
.El
.Sh EXAMPLES
Below is sample code for a
.Xr kauth 9
network scope listener for the
.Em jenna
security model.
It is used to allow users with a user-id below 1000 to bind to reserved ports
(for example, 22/TCP):
.Bd -literal
int
secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	int result;

	/* Default defer. */
	result = KAUTH_RESULT_DEFER;

	switch (action) {
	case KAUTH_NETWORK_BIND:
		/*
		 * We only care about bind(2) requests to privileged
		 * ports.
		 */
		if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) {
			/*
			 * If the user-id is below 1000, which may
			 * indicate a "reserved" user-id, allow the
			 * request.
			 */
			if (kauth_cred_geteuid(cred) < 1000)
				result = KAUTH_RESULT_ALLOW;
		}
		break;
	}

	return (result);
}
.Ed
.Pp
There are two main issues, however, with that listener, that you should be
aware of when approaching to write your own security model:
.Bl -enum -offset indent
.It
.Xr kauth 9
uses restrictive decisions: if you attach this listener on-top of an existing
security model, even if it would allow the request, it could still be denied.
.It
If you attach this listener as the only listener for the network scope,
there are many other requests that will be deferred and, eventually,
denied \(em which may not be desired.
.El
.Pp
That's why before implementing listeners, it should be clear whether they
implement an entirely new from scratch security model, or add on-top of an
existing one.
.Sh PROGRAMMING CONSIDERATIONS
There are several things you should remember when writing a security model:
.Bl -dash -offset indent
.It
Pay attention to the correctness of your
.Nm
implementation of the desired policy.
Certain rights can grant more privileges on the system than others,
like allowing calls to
.Xr chroot 2
or mounting a file-system.
.It
All unhandled requests are denied by default.
.It
Authorization requests can not be issued when the kernel is holding any
locks.
This is a requirement from kernel code to allow designing security models
where the request should be dispatched to userspace or a different host.
.It
Private listener data \(em such as internal data structures \(em is
entirely under the responsibility of the developer.
Locking, synchronization, and garbage collection are all things that
.Xr kauth 9
does
.Em not
take care of for you!
.El
.Ss STACKING ON AN EXISTING SECURITY MODEL
One of the shortcomings of
.Xr kauth 9
is that it does not provide any stacking mechanism, similar to Linux Security
Modules (LSM).
This, however, is considered a feature in reducing dependency on other people's
code.
.Pp
To properly "stack" minor adjustments on-top of an existing security model,
one could use one of two approaches:
.Bl -enum
.It
Register an internal scope for the security model to be used as a
fall-back when requests are deferred.
.Pp
This requires the security model developer to add an internal scope for
every scope the model partly covers, and register the fall-back
listeners to it.
In the model's listener(s) for the scope, when a defer decision is made, the
request is passed to be authorized on the internal scope, effectively using
the fall-back security model.
.Pp
Here is example code that implements the above:
.Bd -literal
#include <secmodel/bsd44/bsd44.h>

/*
 * Internal fall-back scope for the network scope.
 */
#define	JENNA_ISCOPE_NETWORK "jenna.iscope.network"
static kauth_scope_t secmodel_jenna_iscope_network;

/*
 * Jenna's entry point. Register internal scope for the network scope
 * which we partly cover for fall-back authorization.
 */
void
secmodel_jenna_start(void)
{
	secmodel_jenna_iscope_network = kauth_register_scope(
	    JENNA_ISCOPE_NETWORK, NULL, NULL);

	kauth_listen_scope(JENNA_ISCOPE_NETWORK,
	    secmodel_bsd44_suser_network_cb, NULL);
	kauth_listen_scope(JENNA_ISCOPE_NETWORK,
	    secmodel_securelevel_network_cb, NULL);
}

/*
 * Jenna sits on top of another model, effectively filtering requests.
 * If it has nothing to say, it discards the request. This is a good
 * example for fine-tuning a security model for a special need.
 */
int
secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	int result;

	/* Default defer. */
	result = KAUTH_RESULT_DEFER;

	switch (action) {
	case KAUTH_NETWORK_BIND:
		/*
		 * We only care about bind(2) requests to privileged
		 * ports.
		 */
		if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) {
			if (kauth_cred_geteuid(cred) < 1000)
				result = KAUTH_RESULT_ALLOW;
		}
		break;
	}

	/*
	 * If we have don't have a decision, fall-back to the bsd44
	 * security model.
	 */
	if (result == KAUTH_RESULT_DEFER)
		result = kauth_authorize_action(
		    secmodel_jenna_iscope_network, cred, action,
		    arg0, arg1, arg2, arg3);

	return (result);
}
.Ed
.It
If the above is not desired, or cannot be used for any reason, there is
always the ability to manually call the fall-back routine:
.Bd -literal
int
secmodel_jenna_network_cb(kauth_cred_t cred, kauth_action_t action,
    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
{
	int result;

	/* Default defer. */
	result = KAUTH_RESULT_DEFER;

	switch (action) {
	case KAUTH_NETWORK_BIND:
		/*
		 * We only care about bind(2) requests to privileged
		 * ports.
		 */
		if ((u_long)arg0 == KAUTH_REQ_NETWORK_BIND_PRIVPORT) {
			if (kauth_cred_geteuid(cred) < 1000)
				result = KAUTH_RESULT_ALLOW;
		}
		break;
	}

	/*
	 * If we have don't have a decision, fall-back to the bsd44
	 * security model's suser behavior.
	 */
	if (result == KAUTH_RESULT_DEFER)
		result = secmodel_bsd44_suser_network_cb(cred, action,
		    cookie, arg0, arg1, arg2, arg3);

	return (result);
}
.Ed
.El
.Sh AVAILABLE SECURITY MODELS
The following is a list of security models available in the default
.Nx
distribution.
.Bl -tag -width xxxxxxxx
.It Xr secmodel_suser 9
Implements the
.Em super-user
(root) security policy.
.It Xr secmodel_securelevel 9
Implements the
.Em securelevel
security model.
.It Xr secmodel_extensions 9
Implements extensions to the traditional
.Bx 4.4
security model, like usermounts.
.It Xr secmodel_bsd44 9
Traditional
.Nx
security model, derived from
.Bx 4.4 .
.It Xr secmodel_overlay 9
Sample overlay security model, sitting on-top of
.Xr secmodel_bsd44 9 .
.El
.Sh CODE REFERENCES
The core of the
.Nm
implementation is in
.Pa sys/secmodel/secmodel.c .
.Pp
The header file
.In secmodel/secmodel.h
describes the public interface.
.Pp
To make it easier on developers to write new security models from scratch,
.Nx
maintains an example
.Nm
under
.Pa share/examples/secmodel/ .
.Sh SEE ALSO
.Xr kauth 9 ,
.Xr module 9 ,
.Xr secmodel_bsd44 9 ,
.Xr secmodel_extensions 9 ,
.Xr secmodel_overlay 9 ,
.Xr secmodel_securelevel 9 ,
.Xr secmodel_suser 9
.Sh HISTORY
Kernel Authorization was introduced in
.Nx 4.0
as the subsystem responsible for authorization and
credential management.
Before its introduction, there were several ways for providing resource access
control:
.Bl -dash -offset indent -compact
.It
Checking if the user in question is the super-user via
.Fn suser .
.It
Comparing the user-id against hard-coded values, often zero.
.It
Checking the system securelevel.
.El
.Pp
The problem with the above is that the interface ("can X do Y?") was
tightly coupled with the implementation ("is X Z?").
.Xr kauth 9
allows separating them, dispatching requests with highly detailed
context using a consistent and clear KPI.
.Pp
The
.Nm
framework was extended in
.Nx 6.0
to implement
.Nm
registration and evaluation procedure calls.
.Sh AUTHORS
.An Elad Efrat Aq Mt elad@NetBSD.org