ia64/xen-unstable

view xen/acm/acm_chinesewall_hooks.c @ 14858:249de074617f

Added documentation, C bindings, and test for VM_metrics.VCPUs_flags.

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