direct-io.hg

view xen/include/acm/acm_hooks.h @ 5517:10e9028c8e3d

bitkeeper revision 1.1718.1.10 (42b7b19aqOS_1M8I4pIOFjiTPYWV-g)

Merge bk://xenbits.xensource.com/xen-unstable.bk
into spot.cl.cam.ac.uk:C:/Documents and Settings/iap10/xen-unstable.bk
author iap10@spot.cl.cam.ac.uk
date Tue Jun 21 06:20:10 2005 +0000 (2005-06-21)
parents aa52b853c28b
children 649cd37aa1ab
line source
1 /****************************************************************
2 * acm_hooks.h
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * acm header file implementing the global (policy-independent)
15 * sHype hooks that are called throughout Xen.
16 *
17 */
18 #ifndef _ACM_HOOKS_H
19 #define _ACM_HOOKS_H
21 #include <xen/config.h>
22 #include <xen/errno.h>
23 #include <xen/types.h>
24 #include <xen/lib.h>
25 #include <xen/delay.h>
26 #include <xen/sched.h>
27 #include <public/acm.h>
28 #include <acm/acm_core.h>
29 #include <public/dom0_ops.h>
30 #include <public/event_channel.h>
31 #include <asm/current.h>
33 /* if ACM_TRACE_MODE defined, all hooks should
34 * print a short trace message */
35 /* #define ACM_TRACE_MODE */
37 #ifdef ACM_TRACE_MODE
38 # define traceprintk(fmt, args...) printk(fmt,## args)
39 #else
40 # define traceprintk(fmt, args...)
41 #endif
43 /* global variables */
44 extern struct acm_operations *acm_primary_ops;
45 extern struct acm_operations *acm_secondary_ops;
47 /**********************************************************************************************
48 * HOOK structure and meaning (justifies a few words about our model):
49 *
50 * General idea: every policy-controlled system operation is reflected in a
51 * transaction in the system's security state
52 *
53 * Keeping the security state consistent requires "atomic" transactions.
54 * The name of the hooks to place around policy-controlled transactions
55 * reflects this. If authorizations do not involve security state changes,
56 * then and only then POST and FAIL hooks remain empty since we don't care
57 * about the eventual outcome of the operation from a security viewpoint.
58 *
59 * PURPOSE of hook types:
60 * ======================
61 * PRE-Hooks
62 * a) general authorization to guard a controlled system operation
63 * b) prepare security state change (means: fail hook must be able to "undo" this)
64 *
65 * POST-Hooks
66 * a) commit prepared state change
67 *
68 * FAIL-Hooks
69 * a) roll-back prepared security state change from PRE-Hook
70 *
71 *
72 * PLACEMENT of hook types:
73 * ========================
74 * PRE-Hooks must be called:
75 * a) before a guarded/controlled system operation is started
76 * (return is ACM_ACCESS_PERMITTED or ACM_ACCESS_DENIED or error)
77 * --> operation must be aborted if return is != ACM_ACCESS_PERMITTED
78 *
79 * POST-Hooks must be called:
80 * a) after successful transaction (no return value; commit shall never fail)
81 *
82 * FAIL-Hooks must be called:
83 * a) if system transaction (operation) fails somewhen after calling the PRE-hook
84 * (obviously the POST-Hook is not called in this case)
85 * b) if another (secondary) policy denies access in its PRE-Hook
86 * (policy layering is useful but requires additional handling)
87 *
88 *
89 *
90 * Hook model from a security transaction viewpoint:
91 *
92 * start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success
93 * (pre-hook) \ (post-hook)
94 * \
95 * fail
96 * \
97 * \
98 * roll-back
99 * (fail-hook)
100 * \
101 * sys-ops error
102 *
103 *************************************************************************************************/
105 struct acm_operations {
106 /* policy management functions (must always be defined!) */
107 int (*init_domain_ssid) (void **ssid, ssidref_t ssidref);
108 void (*free_domain_ssid) (void *ssid);
109 int (*dump_binary_policy) (u8 *buffer, u16 buf_size);
110 int (*set_binary_policy) (u8 *buffer, u16 buf_size);
111 int (*dump_statistics) (u8 *buffer, u16 buf_size);
112 /* domain management control hooks (can be NULL) */
113 int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref);
114 void (*post_domain_create) (domid_t domid, ssidref_t ssidref);
115 void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref);
116 void (*post_domain_destroy) (void *object_ssid, domid_t id);
117 /* event channel control hooks (can be NULL) */
118 int (*pre_eventchannel_unbound) (domid_t id);
119 void (*fail_eventchannel_unbound) (domid_t id);
120 int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2);
121 int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2);
122 /* grant table control hooks (can be NULL) */
123 int (*pre_grant_map_ref) (domid_t id);
124 void (*fail_grant_map_ref) (domid_t id);
125 int (*pre_grant_setup) (domid_t id);
126 void (*fail_grant_setup) (domid_t id);
127 };
129 static inline int acm_pre_domain_create (void *subject_ssid, ssidref_t ssidref)
130 {
131 if ((acm_primary_ops->pre_domain_create != NULL) &&
132 acm_primary_ops->pre_domain_create (subject_ssid, ssidref))
133 return ACM_ACCESS_DENIED;
134 else if ((acm_secondary_ops->pre_domain_create != NULL) &&
135 acm_secondary_ops->pre_domain_create (subject_ssid, ssidref)) {
136 /* roll-back primary */
137 if (acm_primary_ops->fail_domain_create != NULL)
138 acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
139 return ACM_ACCESS_DENIED;
140 } else
141 return ACM_ACCESS_PERMITTED;
142 }
144 static inline void acm_post_domain_create (domid_t domid, ssidref_t ssidref)
145 {
146 if (acm_primary_ops->post_domain_create != NULL)
147 acm_primary_ops->post_domain_create (domid, ssidref);
148 if (acm_secondary_ops->post_domain_create != NULL)
149 acm_secondary_ops->post_domain_create (domid, ssidref);
150 }
152 static inline void acm_fail_domain_create (void *subject_ssid, ssidref_t ssidref)
153 {
154 if (acm_primary_ops->fail_domain_create != NULL)
155 acm_primary_ops->fail_domain_create (subject_ssid, ssidref);
156 if (acm_secondary_ops->fail_domain_create != NULL)
157 acm_secondary_ops->fail_domain_create (subject_ssid, ssidref);
158 }
160 static inline void acm_post_domain_destroy (void *object_ssid, domid_t id)
161 {
162 if (acm_primary_ops->post_domain_destroy != NULL)
163 acm_primary_ops->post_domain_destroy (object_ssid, id);
164 if (acm_secondary_ops->post_domain_destroy != NULL)
165 acm_secondary_ops->post_domain_destroy (object_ssid, id);
166 return;
167 }
169 /* event channel ops */
171 static inline int acm_pre_eventchannel_unbound (domid_t id)
172 {
173 if ((acm_primary_ops->pre_eventchannel_unbound != NULL) &&
174 acm_primary_ops->pre_eventchannel_unbound (id))
175 return ACM_ACCESS_DENIED;
176 else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) &&
177 acm_secondary_ops->pre_eventchannel_unbound (id)) {
178 /* roll-back primary */
179 if (acm_primary_ops->fail_eventchannel_unbound != NULL)
180 acm_primary_ops->fail_eventchannel_unbound (id);
181 return ACM_ACCESS_DENIED;
182 } else
183 return ACM_ACCESS_PERMITTED;
184 }
186 static inline int acm_pre_eventchannel_interdomain (domid_t id1, domid_t id2)
187 {
188 if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
189 acm_primary_ops->pre_eventchannel_interdomain (id1, id2))
190 return ACM_ACCESS_DENIED;
191 else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
192 acm_secondary_ops->pre_eventchannel_interdomain (id1, id2)) {
193 /* roll-back primary */
194 if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
195 acm_primary_ops->fail_eventchannel_interdomain (id1, id2);
196 return ACM_ACCESS_DENIED;
197 } else
198 return ACM_ACCESS_PERMITTED;
199 }
201 /************ Xen inline hooks ***************/
203 /* small macro to make the hooks more readable
204 * (eliminates hooks if NULL policy is active)
205 */
206 #if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
207 static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
208 { return 0; }
209 #else
210 static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
211 {
212 int ret = -EACCES;
213 struct domain *d;
215 switch(op->cmd) {
216 case DOM0_CREATEDOMAIN:
217 ret = acm_pre_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
218 break;
219 case DOM0_DESTROYDOMAIN:
220 d = find_domain_by_id(op->u.destroydomain.domain);
221 if (d != NULL) {
222 *ssid = d->ssid; /* save for post destroy when d is gone */
223 /* no policy-specific hook */
224 put_domain(d);
225 ret = 0;
226 }
227 break;
228 default:
229 ret = 0; /* ok */
230 }
231 return ret;
232 }
233 #endif
236 #if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
237 static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
238 { return; }
239 #else
240 static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
241 {
242 switch(op->cmd) {
243 case DOM0_CREATEDOMAIN:
244 /* initialialize shared sHype security labels for new domain */
245 acm_init_domain_ssid(op->u.createdomain.domain, op->u.createdomain.ssidref);
246 acm_post_domain_create(op->u.createdomain.domain, op->u.createdomain.ssidref);
247 break;
248 case DOM0_DESTROYDOMAIN:
249 acm_post_domain_destroy(ssid, op->u.destroydomain.domain);
250 /* free security ssid for the destroyed domain (also if running null policy */
251 acm_free_domain_ssid((struct acm_ssid_domain *)ssid);
252 break;
253 }
254 }
255 #endif
258 #if (ACM_USE_SECURITY_POLICy == ACM_NULL_POLICY)
259 static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
260 { return; }
261 #else
262 static inline void acm_fail_dom0_op(dom0_op_t *op, void *ssid)
263 {
264 switch(op->cmd) {
265 case DOM0_CREATEDOMAIN:
266 acm_fail_domain_create(current->domain->ssid, op->u.createdomain.ssidref);
267 break;
268 }
269 }
270 #endif
273 #if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
274 static inline int acm_pre_event_channel(evtchn_op_t *op)
275 { return 0; }
276 #else
277 static inline int acm_pre_event_channel(evtchn_op_t *op)
278 {
279 int ret = -EACCES;
281 switch(op->cmd) {
282 case EVTCHNOP_alloc_unbound:
283 ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom);
284 break;
285 case EVTCHNOP_bind_interdomain:
286 ret = acm_pre_eventchannel_interdomain(op->u.bind_interdomain.dom1, op->u.bind_interdomain.dom2);
287 break;
288 default:
289 ret = 0; /* ok */
290 }
291 return ret;
292 }
293 #endif
295 #if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
296 static inline int acm_pre_grant_map_ref(domid_t id)
297 { return 0; }
298 #else
299 static inline int acm_pre_grant_map_ref (domid_t id)
300 {
301 if ((acm_primary_ops->pre_grant_map_ref != NULL) &&
302 acm_primary_ops->pre_grant_map_ref (id))
303 return ACM_ACCESS_DENIED;
304 else if ((acm_secondary_ops->pre_grant_map_ref != NULL) &&
305 acm_secondary_ops->pre_grant_map_ref (id)) {
306 /* roll-back primary */
307 if (acm_primary_ops->fail_grant_map_ref != NULL)
308 acm_primary_ops->fail_grant_map_ref (id);
309 return ACM_ACCESS_DENIED;
310 } else
311 return ACM_ACCESS_PERMITTED;
312 }
313 #endif
316 #if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
317 static inline int acm_pre_grant_setup(domid_t id)
318 { return 0; }
319 #else
320 static inline int acm_pre_grant_setup (domid_t id)
321 {
322 if ((acm_primary_ops->pre_grant_setup != NULL) &&
323 acm_primary_ops->pre_grant_setup (id))
324 return ACM_ACCESS_DENIED;
325 else if ((acm_secondary_ops->pre_grant_setup != NULL) &&
326 acm_secondary_ops->pre_grant_setup (id)) {
327 /* roll-back primary */
328 if (acm_primary_ops->fail_grant_setup != NULL)
329 acm_primary_ops->fail_grant_setup (id);
330 return ACM_ACCESS_DENIED;
331 } else
332 return ACM_ACCESS_PERMITTED;
333 }
334 #endif
337 #endif