direct-io.hg

view xen/acm/acm_chinesewall_hooks.c @ 14149:8e3899a4f62d

Added SXP pretty-printer.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Feb 27 13:58:40 2007 +0000 (2007-02-27)
parents 97826d77bd4d
children 4434d1039a65
line source
1 /****************************************************************
2 * acm_chinesewall_hooks.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * Contributions:
10 * Stefan Berger <stefanb@watson.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation, version 2 of the
15 * License.
16 *
17 * sHype Chinese Wall Policy for Xen
18 * This code implements the hooks that are called
19 * throughout Xen operations and decides authorization
20 * based on domain types and Chinese Wall conflict type
21 * sets. The CHWALL policy decides if a new domain can be started
22 * based on the types of running domains and the type of the
23 * new domain to be started. If the new domain's type is in
24 * conflict with types of running domains, then this new domain
25 * is not allowed to be created. A domain can have multiple types,
26 * in which case all types of a new domain must be conflict-free
27 * with all types of already running domains.
28 *
29 * indent -i4 -kr -nut
30 *
31 */
33 #include <xen/config.h>
34 #include <xen/errno.h>
35 #include <xen/types.h>
36 #include <xen/lib.h>
37 #include <xen/delay.h>
38 #include <xen/sched.h>
39 #include <public/acm.h>
40 #include <asm/atomic.h>
41 #include <acm/acm_core.h>
42 #include <acm/acm_hooks.h>
43 #include <acm/acm_endian.h>
45 /* local cache structures for chinese wall policy */
46 struct chwall_binary_policy chwall_bin_pol;
48 /*
49 * Initializing chinese wall policy (will be filled by policy partition
50 * using setpolicy command)
51 */
52 int acm_init_chwall_policy(void)
53 {
54 /* minimal startup policy; policy write-locked already */
55 chwall_bin_pol.max_types = 1;
56 chwall_bin_pol.max_ssidrefs = 2;
57 chwall_bin_pol.max_conflictsets = 1;
58 chwall_bin_pol.ssidrefs =
59 (domaintype_t *) xmalloc_array(domaintype_t,
60 chwall_bin_pol.max_ssidrefs *
61 chwall_bin_pol.max_types);
62 chwall_bin_pol.conflict_sets =
63 (domaintype_t *) xmalloc_array(domaintype_t,
64 chwall_bin_pol.max_conflictsets *
65 chwall_bin_pol.max_types);
66 chwall_bin_pol.running_types =
67 (domaintype_t *) xmalloc_array(domaintype_t,
68 chwall_bin_pol.max_types);
69 chwall_bin_pol.conflict_aggregate_set =
70 (domaintype_t *) xmalloc_array(domaintype_t,
71 chwall_bin_pol.max_types);
73 if ((chwall_bin_pol.conflict_sets == NULL)
74 || (chwall_bin_pol.running_types == NULL)
75 || (chwall_bin_pol.ssidrefs == NULL)
76 || (chwall_bin_pol.conflict_aggregate_set == NULL))
77 return ACM_INIT_SSID_ERROR;
79 /* initialize state */
80 memset((void *) chwall_bin_pol.ssidrefs, 0,
81 chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types *
82 sizeof(domaintype_t));
83 memset((void *) chwall_bin_pol.conflict_sets, 0,
84 chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types *
85 sizeof(domaintype_t));
86 memset((void *) chwall_bin_pol.running_types, 0,
87 chwall_bin_pol.max_types * sizeof(domaintype_t));
88 memset((void *) chwall_bin_pol.conflict_aggregate_set, 0,
89 chwall_bin_pol.max_types * sizeof(domaintype_t));
90 return ACM_OK;
91 }
93 static int chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
94 {
95 struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
96 traceprintk("%s.\n", __func__);
97 if (chwall_ssidp == NULL)
98 return ACM_INIT_SSID_ERROR;
100 chwall_ssidp->chwall_ssidref =
101 GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
103 if ((chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs)
104 || (chwall_ssidp->chwall_ssidref == ACM_DEFAULT_LOCAL_SSID))
105 {
106 printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset (0).\n",
107 __func__, chwall_ssidp->chwall_ssidref);
108 xfree(chwall_ssidp);
109 return ACM_INIT_SSID_ERROR;
110 }
111 (*chwall_ssid) = chwall_ssidp;
112 printkd("%s: determined chwall_ssidref to %x.\n",
113 __func__, chwall_ssidp->chwall_ssidref);
114 return ACM_OK;
115 }
117 static void chwall_free_domain_ssid(void *chwall_ssid)
118 {
119 traceprintk("%s.\n", __func__);
120 xfree(chwall_ssid);
121 return;
122 }
125 /* dump chinese wall cache; policy read-locked already */
126 static int chwall_dump_policy(u8 * buf, u32 buf_size)
127 {
128 struct acm_chwall_policy_buffer *chwall_buf =
129 (struct acm_chwall_policy_buffer *) buf;
130 int ret = 0;
132 if (buf_size < sizeof(struct acm_chwall_policy_buffer))
133 return -EINVAL;
135 chwall_buf->chwall_max_types = cpu_to_be32(chwall_bin_pol.max_types);
136 chwall_buf->chwall_max_ssidrefs = cpu_to_be32(chwall_bin_pol.max_ssidrefs);
137 chwall_buf->policy_code = cpu_to_be32(ACM_CHINESE_WALL_POLICY);
138 chwall_buf->chwall_ssid_offset =
139 cpu_to_be32(sizeof(struct acm_chwall_policy_buffer));
140 chwall_buf->chwall_max_conflictsets =
141 cpu_to_be32(chwall_bin_pol.max_conflictsets);
142 chwall_buf->chwall_conflict_sets_offset =
143 cpu_to_be32(be32_to_cpu(chwall_buf->chwall_ssid_offset) +
144 sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
145 chwall_bin_pol.max_types);
146 chwall_buf->chwall_running_types_offset =
147 cpu_to_be32(be32_to_cpu(chwall_buf->chwall_conflict_sets_offset) +
148 sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
149 chwall_bin_pol.max_types);
150 chwall_buf->chwall_conflict_aggregate_offset =
151 cpu_to_be32(be32_to_cpu(chwall_buf->chwall_running_types_offset) +
152 sizeof(domaintype_t) * chwall_bin_pol.max_types);
154 ret = be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset) +
155 sizeof(domaintype_t) * chwall_bin_pol.max_types;
157 ret = (ret + 7) & ~7;
159 if (buf_size < ret)
160 return -EINVAL;
162 /* now copy buffers over */
163 arrcpy16((u16 *) (buf + be32_to_cpu(chwall_buf->chwall_ssid_offset)),
164 chwall_bin_pol.ssidrefs,
165 chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
167 arrcpy16((u16 *) (buf +
168 be32_to_cpu(chwall_buf->chwall_conflict_sets_offset)),
169 chwall_bin_pol.conflict_sets,
170 chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
172 arrcpy16((u16 *) (buf +
173 be32_to_cpu(chwall_buf->chwall_running_types_offset)),
174 chwall_bin_pol.running_types, chwall_bin_pol.max_types);
176 arrcpy16((u16 *) (buf +
177 be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset)),
178 chwall_bin_pol.conflict_aggregate_set,
179 chwall_bin_pol.max_types);
180 return ret;
181 }
183 /* adapt security state (running_types and conflict_aggregate_set) to all running
184 * domains; chwall_init_state is called when a policy is changed to bring the security
185 * information into a consistent state and to detect violations (return != 0).
186 * from a security point of view, we simulate that all running domains are re-started
187 */
188 static int
189 chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
190 domaintype_t * ssidrefs, domaintype_t * conflict_sets,
191 domaintype_t * running_types,
192 domaintype_t * conflict_aggregate_set)
193 {
194 int violation = 0, i, j;
195 struct chwall_ssid *chwall_ssid;
196 ssidref_t chwall_ssidref;
197 struct domain *d;
199 spin_lock(&domlist_update_lock);
200 /* go through all domains and adjust policy as if this domain was started now */
201 for_each_domain ( d )
202 {
203 chwall_ssid =
204 GET_SSIDP(ACM_CHINESE_WALL_POLICY,
205 (struct acm_ssid_domain *)d->ssid);
206 chwall_ssidref = chwall_ssid->chwall_ssidref;
207 traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
208 __func__, d->domain_id, chwall_ssidref);
209 /* a) adjust types ref-count for running domains */
210 for (i = 0; i < chwall_buf->chwall_max_types; i++)
211 running_types[i] +=
212 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
214 /* b) check for conflict */
215 for (i = 0; i < chwall_buf->chwall_max_types; i++)
216 if (conflict_aggregate_set[i] &&
217 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i])
218 {
219 printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
220 __func__, i);
221 violation = 1;
222 goto out;
223 }
224 /* set violation and break out of the loop */
225 /* c) adapt conflict aggregate set for this domain (notice conflicts) */
226 for (i = 0; i < chwall_buf->chwall_max_conflictsets; i++)
227 {
228 int common = 0;
229 /* check if conflict_set_i and ssidref have common types */
230 for (j = 0; j < chwall_buf->chwall_max_types; j++)
231 if (conflict_sets[i * chwall_buf->chwall_max_types + j] &&
232 ssidrefs[chwall_ssidref *
233 chwall_buf->chwall_max_types + j])
234 {
235 common = 1;
236 break;
237 }
238 if (common == 0)
239 continue; /* try next conflict set */
240 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
241 for (j = 0; j < chwall_buf->chwall_max_types; j++)
242 if (conflict_sets[i * chwall_buf->chwall_max_types + j] &&
243 !ssidrefs[chwall_ssidref *
244 chwall_buf->chwall_max_types + j])
245 conflict_aggregate_set[j]++;
246 }
247 }
248 out:
249 spin_unlock(&domlist_update_lock);
250 return violation;
251 /* returning "violation != 0" means that the currently running set of domains would
252 * not be possible if the new policy had been enforced before starting them; for chinese
253 * wall, this means that the new policy includes at least one conflict set of which
254 * more than one type is currently running */
255 }
257 static int chwall_set_policy(u8 * buf, u32 buf_size)
258 {
259 /* policy write-locked already */
260 struct acm_chwall_policy_buffer *chwall_buf =
261 (struct acm_chwall_policy_buffer *) buf;
262 void *ssids = NULL, *conflict_sets = NULL, *running_types =
263 NULL, *conflict_aggregate_set = NULL;
265 if (buf_size < sizeof(struct acm_chwall_policy_buffer))
266 return -EINVAL;
268 /* rewrite the policy due to endianess */
269 chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
270 chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
271 chwall_buf->chwall_max_types = be32_to_cpu(chwall_buf->chwall_max_types);
272 chwall_buf->chwall_max_ssidrefs =
273 be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
274 chwall_buf->chwall_max_conflictsets =
275 be32_to_cpu(chwall_buf->chwall_max_conflictsets);
276 chwall_buf->chwall_ssid_offset = be32_to_cpu(chwall_buf->chwall_ssid_offset);
277 chwall_buf->chwall_conflict_sets_offset =
278 be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
279 chwall_buf->chwall_running_types_offset =
280 be32_to_cpu(chwall_buf->chwall_running_types_offset);
281 chwall_buf->chwall_conflict_aggregate_offset =
282 be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
284 /* policy type and version checks */
285 if ((chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
286 (chwall_buf->policy_version != ACM_CHWALL_VERSION))
287 return -EINVAL;
289 /* 1. allocate new buffers */
290 ssids =
291 xmalloc_array(domaintype_t,
292 chwall_buf->chwall_max_types *
293 chwall_buf->chwall_max_ssidrefs);
294 conflict_sets =
295 xmalloc_array(domaintype_t,
296 chwall_buf->chwall_max_conflictsets *
297 chwall_buf->chwall_max_types);
298 running_types =
299 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
300 conflict_aggregate_set =
301 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
303 if ((ssids == NULL) || (conflict_sets == NULL)
304 || (running_types == NULL) || (conflict_aggregate_set == NULL))
305 goto error_free;
307 /* 2. set new policy */
308 if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
309 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
310 buf_size)
311 goto error_free;
313 arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
314 sizeof(domaintype_t),
315 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
317 if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
318 chwall_buf->chwall_max_types *
319 chwall_buf->chwall_max_conflictsets > buf_size)
320 goto error_free;
322 arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
323 sizeof(domaintype_t),
324 chwall_buf->chwall_max_types *
325 chwall_buf->chwall_max_conflictsets);
327 /* we also use new state buffers since max_types can change */
328 memset(running_types, 0,
329 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
330 memset(conflict_aggregate_set, 0,
331 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
333 /* 3. now re-calculate the state for the new policy based on running domains;
334 * this can fail if new policy is conflicting with running domains */
335 if (chwall_init_state(chwall_buf, ssids,
336 conflict_sets, running_types,
337 conflict_aggregate_set))
338 {
339 printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
340 __func__);
341 goto error_free; /* new policy conflicts with running domains */
342 }
343 /* 4. free old policy buffers, replace with new ones */
344 chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
345 chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
346 chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
347 xfree(chwall_bin_pol.ssidrefs);
348 xfree(chwall_bin_pol.conflict_aggregate_set);
349 xfree(chwall_bin_pol.running_types);
350 xfree(chwall_bin_pol.conflict_sets);
351 chwall_bin_pol.ssidrefs = ssids;
352 chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
353 chwall_bin_pol.running_types = running_types;
354 chwall_bin_pol.conflict_sets = conflict_sets;
355 return ACM_OK;
357 error_free:
358 printk("%s: ERROR setting policy.\n", __func__);
359 xfree(ssids);
360 xfree(conflict_sets);
361 xfree(running_types);
362 xfree(conflict_aggregate_set);
363 return -EFAULT;
364 }
366 static int chwall_dump_stats(u8 * buf, u16 len)
367 {
368 /* no stats for Chinese Wall Policy */
369 return 0;
370 }
372 static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
373 {
374 int i;
376 /* fill in buffer */
377 if (chwall_bin_pol.max_types > len)
378 return -EFAULT;
380 if (ssidref >= chwall_bin_pol.max_ssidrefs)
381 return -EFAULT;
383 /* read types for chwall ssidref */
384 for (i = 0; i < chwall_bin_pol.max_types; i++)
385 {
386 if (chwall_bin_pol.
387 ssidrefs[ssidref * chwall_bin_pol.max_types + i])
388 buf[i] = 1;
389 else
390 buf[i] = 0;
391 }
392 return chwall_bin_pol.max_types;
393 }
395 /***************************
396 * Authorization functions
397 ***************************/
399 /* -------- DOMAIN OPERATION HOOKS -----------*/
401 static int chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
402 {
403 ssidref_t chwall_ssidref;
404 int i, j;
405 traceprintk("%s.\n", __func__);
407 read_lock(&acm_bin_pol_rwlock);
408 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
409 if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID)
410 {
411 printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n",
412 __func__);
413 read_unlock(&acm_bin_pol_rwlock);
414 return ACM_ACCESS_DENIED; /* catching and indicating config error */
415 }
416 if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs)
417 {
418 printk("%s: ERROR chwall_ssidref > max(%x).\n",
419 __func__, chwall_bin_pol.max_ssidrefs - 1);
420 read_unlock(&acm_bin_pol_rwlock);
421 return ACM_ACCESS_DENIED;
422 }
423 /* A: chinese wall check for conflicts */
424 for (i = 0; i < chwall_bin_pol.max_types; i++)
425 if (chwall_bin_pol.conflict_aggregate_set[i] &&
426 chwall_bin_pol.ssidrefs[chwall_ssidref *
427 chwall_bin_pol.max_types + i])
428 {
429 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
430 read_unlock(&acm_bin_pol_rwlock);
431 return ACM_ACCESS_DENIED;
432 }
434 /* B: chinese wall conflict set adjustment (so that other
435 * other domains simultaneously created are evaluated against this new set)*/
436 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
437 {
438 int common = 0;
439 /* check if conflict_set_i and ssidref have common types */
440 for (j = 0; j < chwall_bin_pol.max_types; j++)
441 if (chwall_bin_pol.
442 conflict_sets[i * chwall_bin_pol.max_types + j]
443 && chwall_bin_pol.ssidrefs[chwall_ssidref *
444 chwall_bin_pol.max_types + j])
445 {
446 common = 1;
447 break;
448 }
449 if (common == 0)
450 continue; /* try next conflict set */
451 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
452 for (j = 0; j < chwall_bin_pol.max_types; j++)
453 if (chwall_bin_pol.
454 conflict_sets[i * chwall_bin_pol.max_types + j]
455 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
456 chwall_bin_pol.max_types + j])
457 chwall_bin_pol.conflict_aggregate_set[j]++;
458 }
459 read_unlock(&acm_bin_pol_rwlock);
460 return ACM_ACCESS_PERMITTED;
461 }
463 static void chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
464 {
465 int i, j;
466 ssidref_t chwall_ssidref;
467 traceprintk("%s.\n", __func__);
469 read_lock(&acm_bin_pol_rwlock);
470 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
471 /* adjust types ref-count for running domains */
472 for (i = 0; i < chwall_bin_pol.max_types; i++)
473 chwall_bin_pol.running_types[i] +=
474 chwall_bin_pol.ssidrefs[chwall_ssidref *
475 chwall_bin_pol.max_types + i];
476 if (domid)
477 {
478 read_unlock(&acm_bin_pol_rwlock);
479 return;
480 }
481 /* Xen does not call pre-create hook for DOM0;
482 * to consider type conflicts of any domain with DOM0, we need
483 * to adjust the conflict_aggregate for DOM0 here the same way it
484 * is done for non-DOM0 domains in the pre-hook */
485 printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
486 __func__, ssidref, chwall_ssidref);
488 /* chinese wall conflict set adjustment (so that other
489 * other domains simultaneously created are evaluated against this new set)*/
490 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
491 {
492 int common = 0;
493 /* check if conflict_set_i and ssidref have common types */
494 for (j = 0; j < chwall_bin_pol.max_types; j++)
495 if (chwall_bin_pol.
496 conflict_sets[i * chwall_bin_pol.max_types + j]
497 && chwall_bin_pol.ssidrefs[chwall_ssidref *
498 chwall_bin_pol.max_types + j])
499 {
500 common = 1;
501 break;
502 }
503 if (common == 0)
504 continue; /* try next conflict set */
505 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
506 for (j = 0; j < chwall_bin_pol.max_types; j++)
507 if (chwall_bin_pol.
508 conflict_sets[i * chwall_bin_pol.max_types + j]
509 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
510 chwall_bin_pol.max_types + j])
511 chwall_bin_pol.conflict_aggregate_set[j]++;
512 }
513 read_unlock(&acm_bin_pol_rwlock);
514 return;
515 }
517 static void
518 chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
519 {
520 int i, j;
521 ssidref_t chwall_ssidref;
522 traceprintk("%s.\n", __func__);
524 read_lock(&acm_bin_pol_rwlock);
525 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
526 /* roll-back: re-adjust conflicting types aggregate */
527 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
528 {
529 int common = 0;
530 /* check if conflict_set_i and ssidref have common types */
531 for (j = 0; j < chwall_bin_pol.max_types; j++)
532 if (chwall_bin_pol.
533 conflict_sets[i * chwall_bin_pol.max_types + j]
534 && chwall_bin_pol.ssidrefs[chwall_ssidref *
535 chwall_bin_pol.max_types + j])
536 {
537 common = 1;
538 break;
539 }
540 if (common == 0)
541 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
542 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
543 for (j = 0; j < chwall_bin_pol.max_types; j++)
544 if (chwall_bin_pol.
545 conflict_sets[i * chwall_bin_pol.max_types + j]
546 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
547 chwall_bin_pol.max_types + j])
548 chwall_bin_pol.conflict_aggregate_set[j]--;
549 }
550 read_unlock(&acm_bin_pol_rwlock);
551 }
554 static void chwall_post_domain_destroy(void *object_ssid, domid_t id)
555 {
556 int i, j;
557 struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
558 (struct acm_ssid_domain *)
559 object_ssid);
560 ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
562 traceprintk("%s.\n", __func__);
564 read_lock(&acm_bin_pol_rwlock);
565 /* adjust running types set */
566 for (i = 0; i < chwall_bin_pol.max_types; i++)
567 chwall_bin_pol.running_types[i] -=
568 chwall_bin_pol.ssidrefs[chwall_ssidref *
569 chwall_bin_pol.max_types + i];
571 /* roll-back: re-adjust conflicting types aggregate */
572 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
573 {
574 int common = 0;
575 /* check if conflict_set_i and ssidref have common types */
576 for (j = 0; j < chwall_bin_pol.max_types; j++)
577 if (chwall_bin_pol.
578 conflict_sets[i * chwall_bin_pol.max_types + j]
579 && chwall_bin_pol.ssidrefs[chwall_ssidref *
580 chwall_bin_pol.max_types + j])
581 {
582 common = 1;
583 break;
584 }
585 if (common == 0)
586 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
587 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
588 for (j = 0; j < chwall_bin_pol.max_types; j++)
589 if (chwall_bin_pol.
590 conflict_sets[i * chwall_bin_pol.max_types + j]
591 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
592 chwall_bin_pol.max_types + j])
593 chwall_bin_pol.conflict_aggregate_set[j]--;
594 }
595 read_unlock(&acm_bin_pol_rwlock);
596 return;
597 }
599 struct acm_operations acm_chinesewall_ops = {
600 /* policy management services */
601 .init_domain_ssid = chwall_init_domain_ssid,
602 .free_domain_ssid = chwall_free_domain_ssid,
603 .dump_binary_policy = chwall_dump_policy,
604 .set_binary_policy = chwall_set_policy,
605 .dump_statistics = chwall_dump_stats,
606 .dump_ssid_types = chwall_dump_ssid_types,
607 /* domain management control hooks */
608 .pre_domain_create = chwall_pre_domain_create,
609 .post_domain_create = chwall_post_domain_create,
610 .fail_domain_create = chwall_fail_domain_create,
611 .post_domain_destroy = chwall_post_domain_destroy,
612 /* event channel control hooks */
613 .pre_eventchannel_unbound = NULL,
614 .fail_eventchannel_unbound = NULL,
615 .pre_eventchannel_interdomain = NULL,
616 .fail_eventchannel_interdomain = NULL,
617 /* grant table control hooks */
618 .pre_grant_map_ref = NULL,
619 .fail_grant_map_ref = NULL,
620 .pre_grant_setup = NULL,
621 .fail_grant_setup = NULL,
622 /* generic domain-requested decision hooks */
623 .sharing = NULL,
624 };
626 /*
627 * Local variables:
628 * mode: C
629 * c-set-style: "BSD"
630 * c-basic-offset: 4
631 * tab-width: 4
632 * indent-tabs-mode: nil
633 * End:
634 */