ia64/xen-unstable

view xen/acm/acm_chinesewall_hooks.c @ 5704:9b73afea874e

Certain types of event channel are now auto-bound to vcpu0 by Xen.
Make sure that xenolinux agrees with this.
author sos22@douglas.cl.cam.ac.uk
date Fri Jul 08 15:35:43 2005 +0000 (2005-07-08)
parents 8ad10be47849
children d18f732c0a5f e173a853dc46
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 */
30 #include <xen/config.h>
31 #include <xen/errno.h>
32 #include <xen/types.h>
33 #include <xen/lib.h>
34 #include <xen/delay.h>
35 #include <xen/sched.h>
36 #include <public/acm.h>
37 #include <asm/atomic.h>
38 #include <acm/acm_core.h>
39 #include <acm/acm_hooks.h>
40 #include <acm/acm_endian.h>
42 /* local cache structures for chinese wall policy */
43 struct chwall_binary_policy chwall_bin_pol;
45 /*
46 * Initializing chinese wall policy (will be filled by policy partition
47 * using setpolicy command)
48 */
49 int acm_init_chwall_policy(void)
50 {
51 /* minimal startup policy; policy write-locked already */
52 chwall_bin_pol.max_types = 1;
53 chwall_bin_pol.max_ssidrefs = 2;
54 chwall_bin_pol.max_conflictsets = 1;
55 chwall_bin_pol.ssidrefs = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types);
56 chwall_bin_pol.conflict_sets = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types);
57 chwall_bin_pol.running_types = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
58 chwall_bin_pol.conflict_aggregate_set = (domaintype_t *)xmalloc_array(domaintype_t, chwall_bin_pol.max_types);
60 if ((chwall_bin_pol.conflict_sets == NULL) || (chwall_bin_pol.running_types == NULL) ||
61 (chwall_bin_pol.ssidrefs == NULL) || (chwall_bin_pol.conflict_aggregate_set == NULL))
62 return ACM_INIT_SSID_ERROR;
64 /* initialize state */
65 memset((void *)chwall_bin_pol.ssidrefs, 0, chwall_bin_pol.max_ssidrefs*chwall_bin_pol.max_types*sizeof(domaintype_t));
66 memset((void *)chwall_bin_pol.conflict_sets, 0, chwall_bin_pol.max_conflictsets*chwall_bin_pol.max_types*sizeof(domaintype_t));
67 memset((void *)chwall_bin_pol.running_types, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
68 memset((void *)chwall_bin_pol.conflict_aggregate_set, 0, chwall_bin_pol.max_types*sizeof(domaintype_t));
69 return ACM_OK;
70 }
72 static int
73 chwall_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref)
74 {
75 struct chwall_ssid *chwall_ssidp = xmalloc(struct chwall_ssid);
76 traceprintk("%s.\n", __func__);
77 if (chwall_ssidp == NULL)
78 return ACM_INIT_SSID_ERROR;
79 /*
80 * depending on wheter chwall is primary or secondary, get the respective
81 * part of the global ssidref (same way we'll get the partial ssid pointer)
82 */
83 chwall_ssidp->chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
84 if ((chwall_ssidp->chwall_ssidref >= chwall_bin_pol.max_ssidrefs) ||
85 (chwall_ssidp->chwall_ssidref == ACM_DEFAULT_LOCAL_SSID)) {
86 printkd("%s: ERROR chwall_ssidref(%x) undefined (>max) or unset (0).\n",
87 __func__, chwall_ssidp->chwall_ssidref);
88 xfree(chwall_ssidp);
89 return ACM_INIT_SSID_ERROR;
90 }
91 (*chwall_ssid) = chwall_ssidp;
92 printkd("%s: determined chwall_ssidref to %x.\n",
93 __func__, chwall_ssidp->chwall_ssidref);
94 return ACM_OK;
95 }
97 static void
98 chwall_free_domain_ssid(void *chwall_ssid)
99 {
100 traceprintk("%s.\n", __func__);
101 if (chwall_ssid != NULL)
102 xfree(chwall_ssid);
103 return;
104 }
107 /* dump chinese wall cache; policy read-locked already */
108 static int
109 chwall_dump_policy(u8 *buf, u16 buf_size) {
110 struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
111 int ret = 0;
113 chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types);
114 chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs);
115 chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY);
116 chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
117 chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets);
118 chwall_buf->chwall_conflict_sets_offset =
119 htons(
120 ntohs(chwall_buf->chwall_ssid_offset) +
121 sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
122 chwall_bin_pol.max_types);
124 chwall_buf->chwall_running_types_offset =
125 htons(
126 ntohs(chwall_buf->chwall_conflict_sets_offset) +
127 sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
128 chwall_bin_pol.max_types);
130 chwall_buf->chwall_conflict_aggregate_offset =
131 htons(
132 ntohs(chwall_buf->chwall_running_types_offset) +
133 sizeof(domaintype_t) * chwall_bin_pol.max_types);
135 ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) +
136 sizeof(domaintype_t) * chwall_bin_pol.max_types;
138 /* now copy buffers over */
139 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)),
140 chwall_bin_pol.ssidrefs,
141 chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
143 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)),
144 chwall_bin_pol.conflict_sets,
145 chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
147 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)),
148 chwall_bin_pol.running_types,
149 chwall_bin_pol.max_types);
151 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)),
152 chwall_bin_pol.conflict_aggregate_set,
153 chwall_bin_pol.max_types);
154 return ret;
155 }
157 /* adapt security state (running_types and conflict_aggregate_set) to all running
158 * domains; chwall_init_state is called when a policy is changed to bring the security
159 * information into a consistent state and to detect violations (return != 0).
160 * from a security point of view, we simulate that all running domains are re-started
161 */
162 static int
163 chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, domaintype_t *ssidrefs, domaintype_t *conflict_sets,
164 domaintype_t *running_types, domaintype_t *conflict_aggregate_set)
165 {
166 int violation = 0, i, j;
167 struct chwall_ssid *chwall_ssid;
168 ssidref_t chwall_ssidref;
169 struct domain **pd;
171 write_lock(&domlist_lock);
172 /* go through all domains and adjust policy as if this domain was started now */
173 pd = &domain_list;
174 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
175 chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid);
176 chwall_ssidref = chwall_ssid->chwall_ssidref;
177 traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
178 __func__, (*pd)->domain_id, chwall_ssidref);
179 /* a) adjust types ref-count for running domains */
180 for (i=0; i< chwall_buf->chwall_max_types; i++)
181 running_types[i] +=
182 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i];
184 /* b) check for conflict */
185 for (i=0; i< chwall_buf->chwall_max_types; i++)
186 if (conflict_aggregate_set[i] &&
187 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]) {
188 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
189 violation = 1;
190 goto out;
191 }
192 /* set violation and break out of the loop */
193 /* c) adapt conflict aggregate set for this domain (notice conflicts) */
194 for (i=0; i<chwall_buf->chwall_max_conflictsets; i++) {
195 int common = 0;
196 /* check if conflict_set_i and ssidref have common types */
197 for (j=0; j<chwall_buf->chwall_max_types; j++)
198 if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
199 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) {
200 common = 1;
201 break;
202 }
203 if (common == 0)
204 continue; /* try next conflict set */
205 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
206 for (j=0; j<chwall_buf->chwall_max_types; j++)
207 if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
208 !ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j])
209 conflict_aggregate_set[j]++;
210 }
211 }
212 out:
213 write_unlock(&domlist_lock);
214 return violation;
215 /* returning "violation != 0" means that the currently running set of domains would
216 * not be possible if the new policy had been enforced before starting them; for chinese
217 * wall, this means that the new policy includes at least one conflict set of which
218 * more than one type is currently running */
219 }
221 static int
222 chwall_set_policy(u8 *buf, u16 buf_size)
223 {
224 /* policy write-locked already */
225 struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
226 void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL;
228 /* rewrite the policy due to endianess */
229 chwall_buf->policy_code = ntohs(chwall_buf->policy_code);
230 chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types);
231 chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs);
232 chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets);
233 chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset);
234 chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset);
235 chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset);
236 chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset);
238 /* 1. allocate new buffers */
239 ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs);
240 conflict_sets = xmalloc_array(domaintype_t, chwall_buf->chwall_max_conflictsets*chwall_buf->chwall_max_types);
241 running_types = xmalloc_array(domaintype_t,chwall_buf->chwall_max_types);
242 conflict_aggregate_set = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
244 if ((ssids == NULL)||(conflict_sets == NULL)||(running_types == NULL)||(conflict_aggregate_set == NULL))
245 goto error_free;
247 /* 2. set new policy */
248 if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
249 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > buf_size)
250 goto error_free;
251 arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
252 sizeof(domaintype_t),
253 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
255 if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
256 chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets > buf_size)
257 goto error_free;
259 arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
260 sizeof(domaintype_t),
261 chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets);
263 /* we also use new state buffers since max_types can change */
264 memset(running_types, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
265 memset(conflict_aggregate_set, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
267 /* 3. now re-calculate the state for the new policy based on running domains;
268 * this can fail if new policy is conflicting with running domains */
269 if (chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set)) {
270 printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
271 goto error_free; /* new policy conflicts with running domains */
272 }
273 /* 4. free old policy buffers, replace with new ones */
274 chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
275 chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
276 chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
277 if (chwall_bin_pol.ssidrefs != NULL)
278 xfree(chwall_bin_pol.ssidrefs);
279 if (chwall_bin_pol.conflict_aggregate_set != NULL)
280 xfree(chwall_bin_pol.conflict_aggregate_set);
281 if (chwall_bin_pol.running_types != NULL)
282 xfree(chwall_bin_pol.running_types);
283 if (chwall_bin_pol.conflict_sets != NULL)
284 xfree(chwall_bin_pol.conflict_sets);
285 chwall_bin_pol.ssidrefs = ssids;
286 chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
287 chwall_bin_pol.running_types = running_types;
288 chwall_bin_pol.conflict_sets = conflict_sets;
289 return ACM_OK;
291 error_free:
292 printk("%s: ERROR setting policy.\n", __func__);
293 if (ssids != NULL) xfree(ssids);
294 if (conflict_sets != NULL) xfree(conflict_sets);
295 if (running_types != NULL) xfree(running_types);
296 if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set);
297 return -EFAULT;
298 }
300 static int
301 chwall_dump_stats(u8 *buf, u16 len)
302 {
303 /* no stats for Chinese Wall Policy */
304 return 0;
305 }
307 /***************************
308 * Authorization functions
309 ***************************/
312 /* -------- DOMAIN OPERATION HOOKS -----------*/
314 static int
315 chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
316 {
317 ssidref_t chwall_ssidref;
318 int i,j;
319 traceprintk("%s.\n", __func__);
321 read_lock(&acm_bin_pol_rwlock);
322 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
323 if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) {
324 printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__);
325 read_unlock(&acm_bin_pol_rwlock);
326 return ACM_ACCESS_DENIED; /* catching and indicating config error */
327 }
328 if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
329 printk("%s: ERROR chwall_ssidref > max(%x).\n",
330 __func__, chwall_bin_pol.max_ssidrefs-1);
331 read_unlock(&acm_bin_pol_rwlock);
332 return ACM_ACCESS_DENIED;
333 }
334 /* A: chinese wall check for conflicts */
335 for (i=0; i< chwall_bin_pol.max_types; i++)
336 if (chwall_bin_pol.conflict_aggregate_set[i] &&
337 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]) {
338 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
339 read_unlock(&acm_bin_pol_rwlock);
340 return ACM_ACCESS_DENIED;
341 }
343 /* B: chinese wall conflict set adjustment (so that other
344 * other domains simultaneously created are evaluated against this new set)*/
345 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
346 int common = 0;
347 /* check if conflict_set_i and ssidref have common types */
348 for (j=0; j<chwall_bin_pol.max_types; j++)
349 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
350 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
351 common = 1;
352 break;
353 }
354 if (common == 0)
355 continue; /* try next conflict set */
356 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
357 for (j=0; j<chwall_bin_pol.max_types; j++)
358 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
359 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
360 chwall_bin_pol.conflict_aggregate_set[j]++;
361 }
362 read_unlock(&acm_bin_pol_rwlock);
363 return ACM_ACCESS_PERMITTED;
364 }
366 static void
367 chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
368 {
369 int i,j;
370 ssidref_t chwall_ssidref;
371 traceprintk("%s.\n", __func__);
373 read_lock(&acm_bin_pol_rwlock);
374 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
375 /* adjust types ref-count for running domains */
376 for (i=0; i< chwall_bin_pol.max_types; i++)
377 chwall_bin_pol.running_types[i] +=
378 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
379 if (domid) {
380 read_unlock(&acm_bin_pol_rwlock);
381 return;
382 }
383 /* Xen does not call pre-create hook for DOM0;
384 * to consider type conflicts of any domain with DOM0, we need
385 * to adjust the conflict_aggregate for DOM0 here the same way it
386 * is done for non-DOM0 domains in the pre-hook */
387 printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
388 __func__, ssidref, chwall_ssidref);
390 /* chinese wall conflict set adjustment (so that other
391 * other domains simultaneously created are evaluated against this new set)*/
392 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
393 int common = 0;
394 /* check if conflict_set_i and ssidref have common types */
395 for (j=0; j<chwall_bin_pol.max_types; j++)
396 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
397 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
398 common = 1;
399 break;
400 }
401 if (common == 0)
402 continue; /* try next conflict set */
403 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
404 for (j=0; j<chwall_bin_pol.max_types; j++)
405 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
406 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
407 chwall_bin_pol.conflict_aggregate_set[j]++;
408 }
409 read_unlock(&acm_bin_pol_rwlock);
410 return;
411 }
413 static void
414 chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
415 {
416 int i, j;
417 ssidref_t chwall_ssidref;
418 traceprintk("%s.\n", __func__);
420 read_lock(&acm_bin_pol_rwlock);
421 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
422 /* roll-back: re-adjust conflicting types aggregate */
423 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
424 int common = 0;
425 /* check if conflict_set_i and ssidref have common types */
426 for (j=0; j<chwall_bin_pol.max_types; j++)
427 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
428 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
429 common = 1;
430 break;
431 }
432 if (common == 0)
433 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
434 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
435 for (j=0; j<chwall_bin_pol.max_types; j++)
436 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
437 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
438 chwall_bin_pol.conflict_aggregate_set[j]--;
439 }
440 read_unlock(&acm_bin_pol_rwlock);
441 }
444 static void
445 chwall_post_domain_destroy(void *object_ssid, domid_t id)
446 {
447 int i,j;
448 struct chwall_ssid *chwall_ssidp =
449 GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)object_ssid);
450 ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
452 traceprintk("%s.\n", __func__);
454 read_lock(&acm_bin_pol_rwlock);
455 /* adjust running types set */
456 for (i=0; i< chwall_bin_pol.max_types; i++)
457 chwall_bin_pol.running_types[i] -=
458 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
460 /* roll-back: re-adjust conflicting types aggregate */
461 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
462 int common = 0;
463 /* check if conflict_set_i and ssidref have common types */
464 for (j=0; j<chwall_bin_pol.max_types; j++)
465 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
466 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
467 common = 1;
468 break;
469 }
470 if (common == 0)
471 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
472 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
473 for (j=0; j<chwall_bin_pol.max_types; j++)
474 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
475 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
476 chwall_bin_pol.conflict_aggregate_set[j]--;
477 }
478 read_unlock(&acm_bin_pol_rwlock);
479 return;
480 }
482 struct acm_operations acm_chinesewall_ops = {
483 /* policy management services */
484 .init_domain_ssid = chwall_init_domain_ssid,
485 .free_domain_ssid = chwall_free_domain_ssid,
486 .dump_binary_policy = chwall_dump_policy,
487 .set_binary_policy = chwall_set_policy,
488 .dump_statistics = chwall_dump_stats,
489 /* domain management control hooks */
490 .pre_domain_create = chwall_pre_domain_create,
491 .post_domain_create = chwall_post_domain_create,
492 .fail_domain_create = chwall_fail_domain_create,
493 .post_domain_destroy = chwall_post_domain_destroy,
494 /* event channel control hooks */
495 .pre_eventchannel_unbound = NULL,
496 .fail_eventchannel_unbound = NULL,
497 .pre_eventchannel_interdomain = NULL,
498 .fail_eventchannel_interdomain = NULL,
499 /* grant table control hooks */
500 .pre_grant_map_ref = NULL,
501 .fail_grant_map_ref = NULL,
502 .pre_grant_setup = NULL,
503 .fail_grant_setup = NULL,
504 };