direct-io.hg

view xen/acm/acm_chinesewall_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_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 = 1;
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 printkd("%s: ERROR chwall_ssidref(%x) > max(%x).\n",
86 __func__, chwall_ssidp->chwall_ssidref, chwall_bin_pol.max_ssidrefs-1);
87 xfree(chwall_ssidp);
88 return ACM_INIT_SSID_ERROR;
89 }
90 (*chwall_ssid) = chwall_ssidp;
91 printkd("%s: determined chwall_ssidref to %x.\n",
92 __func__, chwall_ssidp->chwall_ssidref);
93 return ACM_OK;
94 }
96 static void
97 chwall_free_domain_ssid(void *chwall_ssid)
98 {
99 traceprintk("%s.\n", __func__);
100 if (chwall_ssid != NULL)
101 xfree(chwall_ssid);
102 return;
103 }
106 /* dump chinese wall cache; policy read-locked already */
107 static int
108 chwall_dump_policy(u8 *buf, u16 buf_size) {
109 struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
110 int ret = 0;
112 chwall_buf->chwall_max_types = htons(chwall_bin_pol.max_types);
113 chwall_buf->chwall_max_ssidrefs = htons(chwall_bin_pol.max_ssidrefs);
114 chwall_buf->policy_code = htons(ACM_CHINESE_WALL_POLICY);
115 chwall_buf->chwall_ssid_offset = htons(sizeof(struct acm_chwall_policy_buffer));
116 chwall_buf->chwall_max_conflictsets = htons(chwall_bin_pol.max_conflictsets);
117 chwall_buf->chwall_conflict_sets_offset =
118 htons(
119 ntohs(chwall_buf->chwall_ssid_offset) +
120 sizeof(domaintype_t) * chwall_bin_pol.max_ssidrefs *
121 chwall_bin_pol.max_types);
123 chwall_buf->chwall_running_types_offset =
124 htons(
125 ntohs(chwall_buf->chwall_conflict_sets_offset) +
126 sizeof(domaintype_t) * chwall_bin_pol.max_conflictsets *
127 chwall_bin_pol.max_types);
129 chwall_buf->chwall_conflict_aggregate_offset =
130 htons(
131 ntohs(chwall_buf->chwall_running_types_offset) +
132 sizeof(domaintype_t) * chwall_bin_pol.max_types);
134 ret = ntohs(chwall_buf->chwall_conflict_aggregate_offset) +
135 sizeof(domaintype_t) * chwall_bin_pol.max_types;
137 /* now copy buffers over */
138 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_ssid_offset)),
139 chwall_bin_pol.ssidrefs,
140 chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
142 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_sets_offset)),
143 chwall_bin_pol.conflict_sets,
144 chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
146 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_running_types_offset)),
147 chwall_bin_pol.running_types,
148 chwall_bin_pol.max_types);
150 arrcpy16((u16 *)(buf + ntohs(chwall_buf->chwall_conflict_aggregate_offset)),
151 chwall_bin_pol.conflict_aggregate_set,
152 chwall_bin_pol.max_types);
153 return ret;
154 }
156 /* adapt security state (running_types and conflict_aggregate_set) to all running
157 * domains; chwall_init_state is called when a policy is changed to bring the security
158 * information into a consistent state and to detect violations (return != 0).
159 * from a security point of view, we simulate that all running domains are re-started
160 */
161 static int
162 chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf, domaintype_t *ssidrefs, domaintype_t *conflict_sets,
163 domaintype_t *running_types, domaintype_t *conflict_aggregate_set)
164 {
165 int violation = 0, i, j;
166 struct chwall_ssid *chwall_ssid;
167 ssidref_t chwall_ssidref;
168 struct domain **pd;
170 write_lock(&domlist_lock);
171 /* go through all domains and adjust policy as if this domain was started now */
172 pd = &domain_list;
173 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
174 chwall_ssid = GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)(*pd)->ssid);
175 chwall_ssidref = chwall_ssid->chwall_ssidref;
176 traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
177 __func__, (*pd)->domain_id, chwall_ssidref);
178 /* a) adjust types ref-count for running domains */
179 for (i=0; i< chwall_buf->chwall_max_types; i++)
180 running_types[i] +=
181 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i];
183 /* b) check for conflict */
184 for (i=0; i< chwall_buf->chwall_max_types; i++)
185 if (conflict_aggregate_set[i] &&
186 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + i]) {
187 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
188 violation = 1;
189 goto out;
190 }
191 /* set violation and break out of the loop */
192 /* c) adapt conflict aggregate set for this domain (notice conflicts) */
193 for (i=0; i<chwall_buf->chwall_max_conflictsets; i++) {
194 int common = 0;
195 /* check if conflict_set_i and ssidref have common types */
196 for (j=0; j<chwall_buf->chwall_max_types; j++)
197 if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
198 ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j]) {
199 common = 1;
200 break;
201 }
202 if (common == 0)
203 continue; /* try next conflict set */
204 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
205 for (j=0; j<chwall_buf->chwall_max_types; j++)
206 if (conflict_sets[i*chwall_buf->chwall_max_types + j] &&
207 !ssidrefs[chwall_ssidref*chwall_buf->chwall_max_types + j])
208 conflict_aggregate_set[j]++;
209 }
210 }
211 out:
212 write_unlock(&domlist_lock);
213 return violation;
214 /* returning "violation != 0" means that the currently running set of domains would
215 * not be possible if the new policy had been enforced before starting them; for chinese
216 * wall, this means that the new policy includes at least one conflict set of which
217 * more than one type is currently running */
218 }
220 static int
221 chwall_set_policy(u8 *buf, u16 buf_size)
222 {
223 /* policy write-locked already */
224 struct acm_chwall_policy_buffer *chwall_buf = (struct acm_chwall_policy_buffer *)buf;
225 void *ssids = NULL, *conflict_sets = NULL, *running_types = NULL, *conflict_aggregate_set = NULL;
227 /* rewrite the policy due to endianess */
228 chwall_buf->policy_code = ntohs(chwall_buf->policy_code);
229 chwall_buf->chwall_max_types = ntohs(chwall_buf->chwall_max_types);
230 chwall_buf->chwall_max_ssidrefs = ntohs(chwall_buf->chwall_max_ssidrefs);
231 chwall_buf->chwall_max_conflictsets = ntohs(chwall_buf->chwall_max_conflictsets);
232 chwall_buf->chwall_ssid_offset = ntohs(chwall_buf->chwall_ssid_offset);
233 chwall_buf->chwall_conflict_sets_offset = ntohs(chwall_buf->chwall_conflict_sets_offset);
234 chwall_buf->chwall_running_types_offset = ntohs(chwall_buf->chwall_running_types_offset);
235 chwall_buf->chwall_conflict_aggregate_offset = ntohs(chwall_buf->chwall_conflict_aggregate_offset);
237 /* 1. allocate new buffers */
238 ssids = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types*chwall_buf->chwall_max_ssidrefs);
239 conflict_sets = xmalloc_array(domaintype_t, chwall_buf->chwall_max_conflictsets*chwall_buf->chwall_max_types);
240 running_types = xmalloc_array(domaintype_t,chwall_buf->chwall_max_types);
241 conflict_aggregate_set = xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
243 if ((ssids == NULL)||(conflict_sets == NULL)||(running_types == NULL)||(conflict_aggregate_set == NULL))
244 goto error_free;
246 /* 2. set new policy */
247 if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
248 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs > buf_size)
249 goto error_free;
250 arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
251 sizeof(domaintype_t),
252 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
254 if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
255 chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets > buf_size)
256 goto error_free;
258 arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
259 sizeof(domaintype_t),
260 chwall_buf->chwall_max_types * chwall_buf->chwall_max_conflictsets);
262 /* we also use new state buffers since max_types can change */
263 memset(running_types, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
264 memset(conflict_aggregate_set, 0, sizeof(domaintype_t)*chwall_buf->chwall_max_types);
266 /* 3. now re-calculate the state for the new policy based on running domains;
267 * this can fail if new policy is conflicting with running domains */
268 if (chwall_init_state(chwall_buf, ssids, conflict_sets, running_types, conflict_aggregate_set)) {
269 printk("%s: New policy conflicts with running domains. Policy load aborted.\n", __func__);
270 goto error_free; /* new policy conflicts with running domains */
271 }
272 /* 4. free old policy buffers, replace with new ones */
273 chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
274 chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
275 chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
276 if (chwall_bin_pol.ssidrefs != NULL)
277 xfree(chwall_bin_pol.ssidrefs);
278 if (chwall_bin_pol.conflict_aggregate_set != NULL)
279 xfree(chwall_bin_pol.conflict_aggregate_set);
280 if (chwall_bin_pol.running_types != NULL)
281 xfree(chwall_bin_pol.running_types);
282 if (chwall_bin_pol.conflict_sets != NULL)
283 xfree(chwall_bin_pol.conflict_sets);
284 chwall_bin_pol.ssidrefs = ssids;
285 chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
286 chwall_bin_pol.running_types = running_types;
287 chwall_bin_pol.conflict_sets = conflict_sets;
288 return ACM_OK;
290 error_free:
291 printk("%s: ERROR setting policy.\n", __func__);
292 if (ssids != NULL) xfree(ssids);
293 if (conflict_sets != NULL) xfree(conflict_sets);
294 if (running_types != NULL) xfree(running_types);
295 if (conflict_aggregate_set != NULL) xfree(conflict_aggregate_set);
296 return -EFAULT;
297 }
299 static int
300 chwall_dump_stats(u8 *buf, u16 len)
301 {
302 /* no stats for Chinese Wall Policy */
303 return 0;
304 }
306 /***************************
307 * Authorization functions
308 ***************************/
311 /* -------- DOMAIN OPERATION HOOKS -----------*/
313 static int
314 chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
315 {
316 ssidref_t chwall_ssidref;
317 int i,j;
318 traceprintk("%s.\n", __func__);
320 read_lock(&acm_bin_pol_rwlock);
321 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
322 if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID) {
323 printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n", __func__);
324 read_unlock(&acm_bin_pol_rwlock);
325 return ACM_ACCESS_DENIED; /* catching and indicating config error */
326 }
327 if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs) {
328 printk("%s: ERROR chwall_ssidref > max(%x).\n",
329 __func__, chwall_bin_pol.max_ssidrefs-1);
330 read_unlock(&acm_bin_pol_rwlock);
331 return ACM_ACCESS_DENIED;
332 }
333 /* A: chinese wall check for conflicts */
334 for (i=0; i< chwall_bin_pol.max_types; i++)
335 if (chwall_bin_pol.conflict_aggregate_set[i] &&
336 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i]) {
337 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
338 read_unlock(&acm_bin_pol_rwlock);
339 return ACM_ACCESS_DENIED;
340 }
342 /* B: chinese wall conflict set adjustment (so that other
343 * other domains simultaneously created are evaluated against this new set)*/
344 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
345 int common = 0;
346 /* check if conflict_set_i and ssidref have common types */
347 for (j=0; j<chwall_bin_pol.max_types; j++)
348 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
349 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
350 common = 1;
351 break;
352 }
353 if (common == 0)
354 continue; /* try next conflict set */
355 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
356 for (j=0; j<chwall_bin_pol.max_types; j++)
357 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
358 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
359 chwall_bin_pol.conflict_aggregate_set[j]++;
360 }
361 read_unlock(&acm_bin_pol_rwlock);
362 return ACM_ACCESS_PERMITTED;
363 }
365 static void
366 chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
367 {
368 int i,j;
369 ssidref_t chwall_ssidref;
370 traceprintk("%s.\n", __func__);
372 read_lock(&acm_bin_pol_rwlock);
373 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
374 /* adjust types ref-count for running domains */
375 for (i=0; i< chwall_bin_pol.max_types; i++)
376 chwall_bin_pol.running_types[i] +=
377 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
378 if (domid) {
379 read_unlock(&acm_bin_pol_rwlock);
380 return;
381 }
382 /* Xen does not call pre-create hook for DOM0;
383 * to consider type conflicts of any domain with DOM0, we need
384 * to adjust the conflict_aggregate for DOM0 here the same way it
385 * is done for non-DOM0 domains in the pre-hook */
386 printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
387 __func__, ssidref, chwall_ssidref);
389 /* chinese wall conflict set adjustment (so that other
390 * other domains simultaneously created are evaluated against this new set)*/
391 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
392 int common = 0;
393 /* check if conflict_set_i and ssidref have common types */
394 for (j=0; j<chwall_bin_pol.max_types; j++)
395 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
396 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
397 common = 1;
398 break;
399 }
400 if (common == 0)
401 continue; /* try next conflict set */
402 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
403 for (j=0; j<chwall_bin_pol.max_types; j++)
404 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
405 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
406 chwall_bin_pol.conflict_aggregate_set[j]++;
407 }
408 read_unlock(&acm_bin_pol_rwlock);
409 return;
410 }
412 static void
413 chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
414 {
415 int i, j;
416 ssidref_t chwall_ssidref;
417 traceprintk("%s.\n", __func__);
419 read_lock(&acm_bin_pol_rwlock);
420 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
421 /* roll-back: re-adjust conflicting types aggregate */
422 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
423 int common = 0;
424 /* check if conflict_set_i and ssidref have common types */
425 for (j=0; j<chwall_bin_pol.max_types; j++)
426 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
427 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
428 common = 1;
429 break;
430 }
431 if (common == 0)
432 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
433 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
434 for (j=0; j<chwall_bin_pol.max_types; j++)
435 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
436 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
437 chwall_bin_pol.conflict_aggregate_set[j]--;
438 }
439 read_unlock(&acm_bin_pol_rwlock);
440 }
443 static void
444 chwall_post_domain_destroy(void *object_ssid, domid_t id)
445 {
446 int i,j;
447 struct chwall_ssid *chwall_ssidp =
448 GET_SSIDP(ACM_CHINESE_WALL_POLICY, (struct acm_ssid_domain *)object_ssid);
449 ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
451 traceprintk("%s.\n", __func__);
453 read_lock(&acm_bin_pol_rwlock);
454 /* adjust running types set */
455 for (i=0; i< chwall_bin_pol.max_types; i++)
456 chwall_bin_pol.running_types[i] -=
457 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + i];
459 /* roll-back: re-adjust conflicting types aggregate */
460 for (i=0; i<chwall_bin_pol.max_conflictsets; i++) {
461 int common = 0;
462 /* check if conflict_set_i and ssidref have common types */
463 for (j=0; j<chwall_bin_pol.max_types; j++)
464 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
465 chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j]) {
466 common = 1;
467 break;
468 }
469 if (common == 0)
470 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
471 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
472 for (j=0; j<chwall_bin_pol.max_types; j++)
473 if (chwall_bin_pol.conflict_sets[i*chwall_bin_pol.max_types + j] &&
474 !chwall_bin_pol.ssidrefs[chwall_ssidref*chwall_bin_pol.max_types + j])
475 chwall_bin_pol.conflict_aggregate_set[j]--;
476 }
477 read_unlock(&acm_bin_pol_rwlock);
478 return;
479 }
481 struct acm_operations acm_chinesewall_ops = {
482 /* policy management services */
483 .init_domain_ssid = chwall_init_domain_ssid,
484 .free_domain_ssid = chwall_free_domain_ssid,
485 .dump_binary_policy = chwall_dump_policy,
486 .set_binary_policy = chwall_set_policy,
487 .dump_statistics = chwall_dump_stats,
488 /* domain management control hooks */
489 .pre_domain_create = chwall_pre_domain_create,
490 .post_domain_create = chwall_post_domain_create,
491 .fail_domain_create = chwall_fail_domain_create,
492 .post_domain_destroy = chwall_post_domain_destroy,
493 /* event channel control hooks */
494 .pre_eventchannel_unbound = NULL,
495 .fail_eventchannel_unbound = NULL,
496 .pre_eventchannel_interdomain = NULL,
497 .fail_eventchannel_interdomain = NULL,
498 /* grant table control hooks */
499 .pre_grant_map_ref = NULL,
500 .fail_grant_map_ref = NULL,
501 .pre_grant_setup = NULL,
502 .fail_grant_setup = NULL,
503 };