direct-io.hg

view xen/acm/acm_simple_type_enforcement_hooks.c @ 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_simple_type_enforcement_hooks.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * Contributors:
10 * Stefan Berger <stefanb@watson.ibm.com>
11 * support for network order binary policies
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation, version 2 of the
16 * License.
17 *
18 * sHype Simple Type Enforcement for Xen
19 * STE allows to control which domains can setup sharing
20 * (eventchannels right now) with which other domains. Hooks
21 * are defined and called throughout Xen when domains bind to
22 * shared resources (setup eventchannels) and a domain is allowed
23 * to setup sharing with another domain if and only if both domains
24 * share at least on common type.
25 *
26 */
27 #include <xen/lib.h>
28 #include <asm/types.h>
29 #include <asm/current.h>
30 #include <acm/acm_hooks.h>
31 #include <asm/atomic.h>
32 #include <acm/acm_endian.h>
34 /* local cache structures for chinese wall policy */
35 struct ste_binary_policy ste_bin_pol;
37 static inline int have_common_type (ssidref_t ref1, ssidref_t ref2) {
38 int i;
39 for(i=0; i< ste_bin_pol.max_types; i++)
40 if ( ste_bin_pol.ssidrefs[ref1*ste_bin_pol.max_types + i] &&
41 ste_bin_pol.ssidrefs[ref2*ste_bin_pol.max_types + i]) {
42 printkd("%s: common type #%02x.\n", __func__, i);
43 return 1;
44 }
45 return 0;
46 }
48 /* Helper function: return = (subj and obj share a common type) */
49 static int share_common_type(struct domain *subj, struct domain *obj)
50 {
51 ssidref_t ref_s, ref_o;
52 int ret;
54 if ((subj == NULL) || (obj == NULL) || (subj->ssid == NULL) || (obj->ssid == NULL))
55 return 0;
56 read_lock(&acm_bin_pol_rwlock);
57 /* lookup the policy-local ssids */
58 ref_s = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
59 (struct acm_ssid_domain *)subj->ssid)))->ste_ssidref;
60 ref_o = ((struct ste_ssid *)(GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
61 (struct acm_ssid_domain *)obj->ssid)))->ste_ssidref;
62 /* check whether subj and obj share a common ste type */
63 ret = have_common_type(ref_s, ref_o);
64 read_unlock(&acm_bin_pol_rwlock);
65 return ret;
66 }
68 /*
69 * Initializing chinese wall policy (will be filled by policy partition
70 * using setpolicy command)
71 */
72 int acm_init_ste_policy(void)
73 {
74 /* minimal startup policy; policy write-locked already */
75 ste_bin_pol.max_types = 1;
76 ste_bin_pol.max_ssidrefs = 1;
77 ste_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, 1);
79 if (ste_bin_pol.ssidrefs == NULL)
80 return ACM_INIT_SSID_ERROR;
82 /* initialize state */
83 ste_bin_pol.ssidrefs[0] = 1;
85 /* init stats */
86 atomic_set(&(ste_bin_pol.ec_eval_count), 0);
87 atomic_set(&(ste_bin_pol.ec_denied_count), 0);
88 atomic_set(&(ste_bin_pol.ec_cachehit_count), 0);
89 atomic_set(&(ste_bin_pol.gt_eval_count), 0);
90 atomic_set(&(ste_bin_pol.gt_denied_count), 0);
91 atomic_set(&(ste_bin_pol.gt_cachehit_count), 0);
92 return ACM_OK;
93 }
96 /* ste initialization function hooks */
97 static int
98 ste_init_domain_ssid(void **ste_ssid, ssidref_t ssidref)
99 {
100 int i;
101 struct ste_ssid *ste_ssidp = xmalloc(struct ste_ssid);
102 traceprintk("%s.\n", __func__);
104 if (ste_ssidp == NULL)
105 return ACM_INIT_SSID_ERROR;
107 /* get policy-local ssid reference */
108 ste_ssidp->ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
109 if (ste_ssidp->ste_ssidref >= ste_bin_pol.max_ssidrefs) {
110 printkd("%s: ERROR ste_ssidref (%x) > max(%x).\n",
111 __func__, ste_ssidp->ste_ssidref, ste_bin_pol.max_ssidrefs-1);
112 xfree(ste_ssidp);
113 return ACM_INIT_SSID_ERROR;
114 }
115 /* clean ste cache */
116 for (i=0; i<ACM_TE_CACHE_SIZE; i++)
117 ste_ssidp->ste_cache[i].valid = FREE;
119 (*ste_ssid) = ste_ssidp;
120 printkd("%s: determined ste_ssidref to %x.\n",
121 __func__, ste_ssidp->ste_ssidref);
122 return ACM_OK;
123 }
126 static void
127 ste_free_domain_ssid(void *ste_ssid)
128 {
129 traceprintk("%s.\n", __func__);
130 if (ste_ssid != NULL)
131 xfree(ste_ssid);
132 return;
133 }
135 /* dump type enforcement cache; policy read-locked already */
136 static int
137 ste_dump_policy(u8 *buf, u16 buf_size) {
138 struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
139 int ret = 0;
141 ste_buf->ste_max_types = htons(ste_bin_pol.max_types);
142 ste_buf->ste_max_ssidrefs = htons(ste_bin_pol.max_ssidrefs);
143 ste_buf->policy_code = htons(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
144 ste_buf->ste_ssid_offset = htons(sizeof(struct acm_ste_policy_buffer));
145 ret = ntohs(ste_buf->ste_ssid_offset) +
146 sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
148 /* now copy buffer over */
149 arrcpy(buf + ntohs(ste_buf->ste_ssid_offset),
150 ste_bin_pol.ssidrefs,
151 sizeof(domaintype_t),
152 ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types);
154 return ret;
155 }
157 /* ste_init_state is called when a policy is changed to detect violations (return != 0).
158 * from a security point of view, we simulate that all running domains are re-started and
159 * all sharing decisions are replayed to detect violations or current sharing behavior
160 * (right now: event_channels, future: also grant_tables)
161 */
162 static int
163 ste_init_state(struct acm_ste_policy_buffer *ste_buf, domaintype_t *ssidrefs)
164 {
165 int violation = 1;
166 struct ste_ssid *ste_ssid, *ste_rssid;
167 ssidref_t ste_ssidref, ste_rssidref;
168 struct domain **pd, *rdom;
169 domid_t rdomid;
170 grant_entry_t sha_copy;
171 int port, i;
173 read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
174 /* go through all domains and adjust policy as if this domain was started now */
175 pd = &domain_list;
176 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
177 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
178 (struct acm_ssid_domain *)(*pd)->ssid);
179 ste_ssidref = ste_ssid->ste_ssidref;
180 traceprintk("%s: validating policy for eventch domain %x (ste-Ref=%x).\n",
181 __func__, (*pd)->domain_id, ste_ssidref);
182 /* a) check for event channel conflicts */
183 for (port=0; port < NR_EVTCHN_BUCKETS; port++) {
184 spin_lock(&(*pd)->evtchn_lock);
185 if ((*pd)->evtchn[port] == NULL) {
186 spin_unlock(&(*pd)->evtchn_lock);
187 continue;
188 }
189 if ((*pd)->evtchn[port]->state == ECS_INTERDOMAIN) {
190 rdom = (*pd)->evtchn[port]->u.interdomain.remote_dom;
191 rdomid = rdom->domain_id;
192 /* rdom now has remote domain */
193 ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
194 (struct acm_ssid_domain *)(rdom->ssid));
195 ste_rssidref = ste_rssid->ste_ssidref;
196 } else if ((*pd)->evtchn[port]->state == ECS_UNBOUND) {
197 rdomid = (*pd)->evtchn[port]->u.unbound.remote_domid;
198 if ((rdom = find_domain_by_id(rdomid)) == NULL) {
199 printk("%s: Error finding domain to id %x!\n", __func__, rdomid);
200 goto out;
201 }
202 /* rdom now has remote domain */
203 ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
204 (struct acm_ssid_domain *)(rdom->ssid));
205 ste_rssidref = ste_rssid->ste_ssidref;
206 put_domain(rdom);
207 } else {
208 spin_unlock(&(*pd)->evtchn_lock);
209 continue; /* port unused */
210 }
211 spin_unlock(&(*pd)->evtchn_lock);
213 /* rdom now has remote domain */
214 ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
215 (struct acm_ssid_domain *)(rdom->ssid));
216 ste_rssidref = ste_rssid->ste_ssidref;
217 traceprintk("%s: eventch: domain %x (ssidref %x) --> domain %x (rssidref %x) used (port %x).\n",
218 __func__, (*pd)->domain_id, ste_ssidref, rdom->domain_id, ste_rssidref, port);
219 /* check whether on subj->ssid, obj->ssid share a common type*/
220 if (!have_common_type(ste_ssidref, ste_rssidref)) {
221 printkd("%s: Policy violation in event channel domain %x -> domain %x.\n",
222 __func__, (*pd)->domain_id, rdomid);
223 goto out;
224 }
225 }
226 /* b) check for grant table conflicts on shared pages */
227 if ((*pd)->grant_table->shared == NULL) {
228 printkd("%s: Grant ... sharing for domain %x not setup!\n", __func__, (*pd)->domain_id);
229 continue;
230 }
231 for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) {
232 sha_copy = (*pd)->grant_table->shared[i];
233 if ( sha_copy.flags ) {
234 printkd("%s: grant dom (%hu) SHARED (%d) flags:(%hx) dom:(%hu) frame:(%lx)\n",
235 __func__, (*pd)->domain_id, i, sha_copy.flags, sha_copy.domid,
236 (unsigned long)sha_copy.frame);
237 rdomid = sha_copy.domid;
238 if ((rdom = find_domain_by_id(rdomid)) == NULL) {
239 printkd("%s: domain not found ERROR!\n", __func__);
240 goto out;
241 };
242 /* rdom now has remote domain */
243 ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
244 (struct acm_ssid_domain *)(rdom->ssid));
245 ste_rssidref = ste_rssid->ste_ssidref;
246 put_domain(rdom);
247 if (!have_common_type(ste_ssidref, ste_rssidref)) {
248 printkd("%s: Policy violation in grant table sharing domain %x -> domain %x.\n",
249 __func__, (*pd)->domain_id, rdomid);
250 goto out;
251 }
252 }
253 }
254 }
255 violation = 0;
256 out:
257 read_unlock(&domlist_lock);
258 return violation;
259 /* returning "violation != 0" means that existing sharing between domains would not
260 * have been allowed if the new policy had been enforced before the sharing; for ste,
261 * this means that there are at least 2 domains that have established sharing through
262 * event-channels or grant-tables but these two domains don't have no longer a common
263 * type in their typesets referenced by their ssidrefs */
264 }
266 /* set new policy; policy write-locked already */
267 static int
268 ste_set_policy(u8 *buf, u16 buf_size)
269 {
270 struct acm_ste_policy_buffer *ste_buf = (struct acm_ste_policy_buffer *)buf;
271 void *ssidrefsbuf;
272 struct ste_ssid *ste_ssid;
273 struct domain **pd;
274 int i;
276 /* Convert endianess of policy */
277 ste_buf->policy_code = ntohs(ste_buf->policy_code);
278 ste_buf->ste_max_types = ntohs(ste_buf->ste_max_types);
279 ste_buf->ste_max_ssidrefs = ntohs(ste_buf->ste_max_ssidrefs);
280 ste_buf->ste_ssid_offset = ntohs(ste_buf->ste_ssid_offset);
282 /* 1. create and copy-in new ssidrefs buffer */
283 ssidrefsbuf = xmalloc_array(u8, sizeof(domaintype_t)*ste_buf->ste_max_types*ste_buf->ste_max_ssidrefs);
284 if (ssidrefsbuf == NULL) {
285 return -ENOMEM;
286 }
287 if (ste_buf->ste_ssid_offset + sizeof(domaintype_t) * ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types > buf_size)
288 goto error_free;
290 arrcpy(ssidrefsbuf,
291 buf + ste_buf->ste_ssid_offset,
292 sizeof(domaintype_t),
293 ste_buf->ste_max_ssidrefs*ste_buf->ste_max_types);
295 /* 2. now re-calculate sharing decisions based on running domains;
296 * this can fail if new policy is conflicting with sharing of running domains
297 * now: reject violating new policy; future: adjust sharing through revoking sharing */
298 if (ste_init_state(ste_buf, (domaintype_t *)ssidrefsbuf)) {
299 printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
300 goto error_free; /* new policy conflicts with sharing of running domains */
301 }
302 /* 3. replace old policy (activate new policy) */
303 ste_bin_pol.max_types = ste_buf->ste_max_types;
304 ste_bin_pol.max_ssidrefs = ste_buf->ste_max_ssidrefs;
305 if (ste_bin_pol.ssidrefs)
306 xfree(ste_bin_pol.ssidrefs);
307 ste_bin_pol.ssidrefs = (domaintype_t *)ssidrefsbuf;
309 /* clear all ste caches */
310 read_lock(&domlist_lock);
311 pd = &domain_list;
312 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
313 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
314 (struct acm_ssid_domain *)(*pd)->ssid);
315 for (i=0; i<ACM_TE_CACHE_SIZE; i++)
316 ste_ssid->ste_cache[i].valid = FREE;
317 }
318 read_unlock(&domlist_lock);
319 return ACM_OK;
321 error_free:
322 printk("%s: ERROR setting policy.\n", __func__);
323 if (ssidrefsbuf != NULL) xfree(ssidrefsbuf);
324 return -EFAULT;
325 }
327 static int
328 ste_dump_stats(u8 *buf, u16 buf_len)
329 {
330 struct acm_ste_stats_buffer stats;
332 #ifdef ACM_DEBUG
333 int i;
334 struct ste_ssid *ste_ssid;
335 struct domain **pd;
337 printk("ste: Decision caches:\n");
338 /* go through all domains and adjust policy as if this domain was started now */
339 read_lock(&domlist_lock); /* go by domain? or directly by global? event/grant list */
340 pd = &domain_list;
341 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
342 printk("ste: Cache Domain %02x.\n", (*pd)->domain_id);
343 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
344 (struct acm_ssid_domain *)(*pd)->ssid);
345 for (i=0; i<ACM_TE_CACHE_SIZE; i++)
346 printk("\t\tcache[%02x] = %s, domid=%x.\n", i,
347 (ste_ssid->ste_cache[i].valid == VALID) ?
348 "VALID" : "FREE",
349 (ste_ssid->ste_cache[i].valid == VALID) ?
350 ste_ssid->ste_cache[i].id : 0xffffffff);
351 }
352 read_unlock(&domlist_lock);
353 /* init stats */
354 printk("STE-Policy Security Hook Statistics:\n");
355 printk("ste: event_channel eval_count = %x\n", atomic_read(&(ste_bin_pol.ec_eval_count)));
356 printk("ste: event_channel denied_count = %x\n", atomic_read(&(ste_bin_pol.ec_denied_count)));
357 printk("ste: event_channel cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.ec_cachehit_count)));
358 printk("ste:\n");
359 printk("ste: grant_table eval_count = %x\n", atomic_read(&(ste_bin_pol.gt_eval_count)));
360 printk("ste: grant_table denied_count = %x\n", atomic_read(&(ste_bin_pol.gt_denied_count)));
361 printk("ste: grant_table cache_hit_count = %x\n", atomic_read(&(ste_bin_pol.gt_cachehit_count)));
362 #endif
364 if (buf_len < sizeof(struct acm_ste_stats_buffer))
365 return -ENOMEM;
367 /* now send the hook counts to user space */
368 stats.ec_eval_count = htonl(atomic_read(&ste_bin_pol.ec_eval_count));
369 stats.gt_eval_count = htonl(atomic_read(&ste_bin_pol.gt_eval_count));
370 stats.ec_denied_count = htonl(atomic_read(&ste_bin_pol.ec_denied_count));
371 stats.gt_denied_count = htonl(atomic_read(&ste_bin_pol.gt_denied_count));
372 stats.ec_cachehit_count = htonl(atomic_read(&ste_bin_pol.ec_cachehit_count));
373 stats.gt_cachehit_count = htonl(atomic_read(&ste_bin_pol.gt_cachehit_count));
374 memcpy(buf, &stats, sizeof(struct acm_ste_stats_buffer));
375 return sizeof(struct acm_ste_stats_buffer);
376 }
379 /* we need to go through this before calling the hooks,
380 * returns 1 == cache hit */
381 static int inline
382 check_cache(struct domain *dom, domid_t rdom) {
383 struct ste_ssid *ste_ssid;
384 int i;
386 printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
387 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
388 (struct acm_ssid_domain *)(dom)->ssid);
390 for(i=0; i< ACM_TE_CACHE_SIZE; i++) {
391 if ((ste_ssid->ste_cache[i].valid == VALID) &&
392 (ste_ssid->ste_cache[i].id == rdom)) {
393 printkd("cache hit (entry %x, id= %x!\n", i, ste_ssid->ste_cache[i].id);
394 return 1;
395 }
396 }
397 return 0;
398 }
401 /* we only get here if there is NO entry yet; no duplication check! */
402 static void inline
403 cache_result(struct domain *subj, struct domain *obj) {
404 struct ste_ssid *ste_ssid;
405 int i;
406 printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id);
407 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
408 (struct acm_ssid_domain *)(subj)->ssid);
409 for(i=0; i< ACM_TE_CACHE_SIZE; i++)
410 if (ste_ssid->ste_cache[i].valid == FREE)
411 break;
412 if (i< ACM_TE_CACHE_SIZE) {
413 ste_ssid->ste_cache[i].valid = VALID;
414 ste_ssid->ste_cache[i].id = obj->domain_id;
415 } else
416 printk ("Cache of dom %x is full!\n", subj->domain_id);
417 }
419 /* deletes entries for domain 'id' from all caches (re-use) */
420 static void inline
421 clean_id_from_cache(domid_t id)
422 {
423 struct ste_ssid *ste_ssid;
424 int i;
425 struct domain **pd;
427 printkd("deleting cache for dom %x.\n", id);
429 read_lock(&domlist_lock); /* look through caches of all domains */
430 pd = &domain_list;
431 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
432 ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
433 (struct acm_ssid_domain *)(*pd)->ssid);
434 for (i=0; i<ACM_TE_CACHE_SIZE; i++)
435 if ((ste_ssid->ste_cache[i].valid == VALID) &&
436 (ste_ssid->ste_cache[i].id = id))
437 ste_ssid->ste_cache[i].valid = FREE;
438 }
439 read_unlock(&domlist_lock);
440 }
442 /***************************
443 * Authorization functions
444 **************************/
446 static int
447 ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
448 {
449 /* check for ssidref in range for policy */
450 ssidref_t ste_ssidref;
451 traceprintk("%s.\n", __func__);
453 read_lock(&acm_bin_pol_rwlock);
454 ste_ssidref = GET_SSIDREF(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssidref);
455 if (ste_ssidref == ACM_DEFAULT_LOCAL_SSID) {
456 printk("%s: ERROR STE SSID is NOT SET but policy enforced.\n", __func__);
457 read_unlock(&acm_bin_pol_rwlock);
458 return ACM_ACCESS_DENIED; /* catching and indicating config error */
459 }
460 if (ste_ssidref >= ste_bin_pol.max_ssidrefs) {
461 printk("%s: ERROR ste_ssidref > max(%x).\n",
462 __func__, ste_bin_pol.max_ssidrefs-1);
463 read_unlock(&acm_bin_pol_rwlock);
464 return ACM_ACCESS_DENIED;
465 }
466 read_unlock(&acm_bin_pol_rwlock);
467 return ACM_ACCESS_PERMITTED;
468 }
470 static void
471 ste_post_domain_destroy(void *subject_ssid, domid_t id)
472 {
473 /* clean all cache entries for destroyed domain (might be re-used) */
474 clean_id_from_cache(id);
475 }
477 /* -------- EVENTCHANNEL OPERATIONS -----------*/
478 static int
479 ste_pre_eventchannel_unbound(domid_t id) {
480 struct domain *subj, *obj;
481 int ret;
482 traceprintk("%s: dom%x-->dom%x.\n",
483 __func__, current->domain->domain_id, id);
485 if (check_cache(current->domain, id)) {
486 atomic_inc(&ste_bin_pol.ec_cachehit_count);
487 return ACM_ACCESS_PERMITTED;
488 }
489 atomic_inc(&ste_bin_pol.ec_eval_count);
490 subj = current->domain;
491 obj = find_domain_by_id(id);
493 if (share_common_type(subj, obj)) {
494 cache_result(subj, obj);
495 ret = ACM_ACCESS_PERMITTED;
496 } else {
497 atomic_inc(&ste_bin_pol.ec_denied_count);
498 ret = ACM_ACCESS_DENIED;
499 }
500 if (obj != NULL)
501 put_domain(obj);
502 return ret;
503 }
505 static int
506 ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
507 {
508 struct domain *subj, *obj;
509 int ret;
510 traceprintk("%s: dom%x-->dom%x.\n", __func__,
511 (id1 == DOMID_SELF) ? current->domain->domain_id : id1,
512 (id2 == DOMID_SELF) ? current->domain->domain_id : id2);
514 /* following is a bit longer but ensures that we
515 * "put" only domains that we where "find"-ing
516 */
517 if (id1 == DOMID_SELF) id1 = current->domain->domain_id;
518 if (id2 == DOMID_SELF) id2 = current->domain->domain_id;
520 subj = find_domain_by_id(id1);
521 obj = find_domain_by_id(id2);
522 if ((subj == NULL) || (obj == NULL)) {
523 ret = ACM_ACCESS_DENIED;
524 goto out;
525 }
526 /* cache check late, but evtchn is not on performance critical path */
527 if (check_cache(subj, obj->domain_id)) {
528 atomic_inc(&ste_bin_pol.ec_cachehit_count);
529 ret = ACM_ACCESS_PERMITTED;
530 goto out;
531 }
532 atomic_inc(&ste_bin_pol.ec_eval_count);
534 if (share_common_type(subj, obj)) {
535 cache_result(subj, obj);
536 ret = ACM_ACCESS_PERMITTED;
537 } else {
538 atomic_inc(&ste_bin_pol.ec_denied_count);
539 ret = ACM_ACCESS_DENIED;
540 }
541 out:
542 if (obj != NULL)
543 put_domain(obj);
544 if (subj != NULL)
545 put_domain(subj);
546 return ret;
547 }
549 /* -------- SHARED MEMORY OPERATIONS -----------*/
551 static int
552 ste_pre_grant_map_ref (domid_t id) {
553 struct domain *obj, *subj;
554 int ret;
555 traceprintk("%s: dom%x-->dom%x.\n", __func__,
556 current->domain->domain_id, id);
558 if (check_cache(current->domain, id)) {
559 atomic_inc(&ste_bin_pol.gt_cachehit_count);
560 return ACM_ACCESS_PERMITTED;
561 }
562 atomic_inc(&ste_bin_pol.gt_eval_count);
563 subj = current->domain;
564 obj = find_domain_by_id(id);
566 if (share_common_type(subj, obj)) {
567 cache_result(subj, obj);
568 ret = ACM_ACCESS_PERMITTED;
569 } else {
570 atomic_inc(&ste_bin_pol.gt_denied_count);
571 printkd("%s: ACCESS DENIED!\n", __func__);
572 ret = ACM_ACCESS_DENIED;
573 }
574 if (obj != NULL)
575 put_domain(obj);
576 return ret;
577 }
579 /* since setting up grant tables involves some implicit information
580 flow from the creating domain to the domain that is setup, we
581 check types in addition to the general authorization */
582 static int
583 ste_pre_grant_setup (domid_t id) {
584 struct domain *obj, *subj;
585 int ret;
586 traceprintk("%s: dom%x-->dom%x.\n", __func__,
587 current->domain->domain_id, id);
589 if (check_cache(current->domain, id)) {
590 atomic_inc(&ste_bin_pol.gt_cachehit_count);
591 return ACM_ACCESS_PERMITTED;
592 }
593 atomic_inc(&ste_bin_pol.gt_eval_count);
594 /* a) check authorization (eventually use specific capabilities) */
595 if (!IS_PRIV(current->domain)) {
596 printk("%s: Grant table management authorization denied ERROR!\n", __func__);
597 return ACM_ACCESS_DENIED;
598 }
599 /* b) check types */
600 subj = current->domain;
601 obj = find_domain_by_id(id);
603 if (share_common_type(subj, obj)) {
604 cache_result(subj, obj);
605 ret = ACM_ACCESS_PERMITTED;
606 } else {
607 atomic_inc(&ste_bin_pol.gt_denied_count);
608 ret = ACM_ACCESS_DENIED;
609 }
610 if (obj != NULL)
611 put_domain(obj);
612 return ret;
613 }
615 /* now define the hook structure similarly to LSM */
616 struct acm_operations acm_simple_type_enforcement_ops = {
617 /* policy management services */
618 .init_domain_ssid = ste_init_domain_ssid,
619 .free_domain_ssid = ste_free_domain_ssid,
620 .dump_binary_policy = ste_dump_policy,
621 .set_binary_policy = ste_set_policy,
622 .dump_statistics = ste_dump_stats,
623 /* domain management control hooks */
624 .pre_domain_create = ste_pre_domain_create,
625 .post_domain_create = NULL,
626 .fail_domain_create = NULL,
627 .post_domain_destroy = ste_post_domain_destroy,
628 /* event channel control hooks */
629 .pre_eventchannel_unbound = ste_pre_eventchannel_unbound,
630 .fail_eventchannel_unbound = NULL,
631 .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain,
632 .fail_eventchannel_interdomain = NULL,
633 /* grant table control hooks */
634 .pre_grant_map_ref = ste_pre_grant_map_ref,
635 .fail_grant_map_ref = NULL,
636 .pre_grant_setup = ste_pre_grant_setup,
637 .fail_grant_setup = NULL,
638 };