xref: /netbsd-src/share/man/man9/secmodel.9 (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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