ia64/xen-unstable

view xen/acm/acm_chinesewall_hooks.c @ 8723:61e7afb7344b

The memset in init_switch_stack is overwriting the processor stack.
We need to avoid manipulating the switch stack area of the currently
running cpu. Original patch by Kevin Tian.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Feb 01 00:56:19 2006 +0100 (2006-02-01)
parents fcb7e5616102
children d088aec406c0
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 = htonl(chwall_bin_pol.max_types);
136 chwall_buf->chwall_max_ssidrefs = htonl(chwall_bin_pol.max_ssidrefs);
137 chwall_buf->policy_code = htonl(ACM_CHINESE_WALL_POLICY);
138 chwall_buf->chwall_ssid_offset =
139 htonl(sizeof(struct acm_chwall_policy_buffer));
140 chwall_buf->chwall_max_conflictsets =
141 htonl(chwall_bin_pol.max_conflictsets);
142 chwall_buf->chwall_conflict_sets_offset =
143 htonl(ntohl(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 htonl(ntohl(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 htonl(ntohl(chwall_buf->chwall_running_types_offset) +
152 sizeof(domaintype_t) * chwall_bin_pol.max_types);
154 ret = ntohl(chwall_buf->chwall_conflict_aggregate_offset) +
155 sizeof(domaintype_t) * chwall_bin_pol.max_types;
157 if (buf_size < ret)
158 return -EINVAL;
160 /* now copy buffers over */
161 arrcpy16((u16 *) (buf + ntohl(chwall_buf->chwall_ssid_offset)),
162 chwall_bin_pol.ssidrefs,
163 chwall_bin_pol.max_ssidrefs * chwall_bin_pol.max_types);
165 arrcpy16((u16 *) (buf +
166 ntohl(chwall_buf->chwall_conflict_sets_offset)),
167 chwall_bin_pol.conflict_sets,
168 chwall_bin_pol.max_conflictsets * chwall_bin_pol.max_types);
170 arrcpy16((u16 *) (buf +
171 ntohl(chwall_buf->chwall_running_types_offset)),
172 chwall_bin_pol.running_types, chwall_bin_pol.max_types);
174 arrcpy16((u16 *) (buf +
175 ntohl(chwall_buf->chwall_conflict_aggregate_offset)),
176 chwall_bin_pol.conflict_aggregate_set,
177 chwall_bin_pol.max_types);
178 return ret;
179 }
181 /* adapt security state (running_types and conflict_aggregate_set) to all running
182 * domains; chwall_init_state is called when a policy is changed to bring the security
183 * information into a consistent state and to detect violations (return != 0).
184 * from a security point of view, we simulate that all running domains are re-started
185 */
186 static int
187 chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
188 domaintype_t * ssidrefs, domaintype_t * conflict_sets,
189 domaintype_t * running_types,
190 domaintype_t * conflict_aggregate_set)
191 {
192 int violation = 0, i, j;
193 struct chwall_ssid *chwall_ssid;
194 ssidref_t chwall_ssidref;
195 struct domain **pd;
197 write_lock(&domlist_lock);
198 /* go through all domains and adjust policy as if this domain was started now */
199 pd = &domain_list;
200 for (pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list)
201 {
202 chwall_ssid =
203 GET_SSIDP(ACM_CHINESE_WALL_POLICY,
204 (struct acm_ssid_domain *) (*pd)->ssid);
205 chwall_ssidref = chwall_ssid->chwall_ssidref;
206 traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
207 __func__, (*pd)->domain_id, chwall_ssidref);
208 /* a) adjust types ref-count for running domains */
209 for (i = 0; i < chwall_buf->chwall_max_types; i++)
210 running_types[i] +=
211 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
213 /* b) check for conflict */
214 for (i = 0; i < chwall_buf->chwall_max_types; i++)
215 if (conflict_aggregate_set[i] &&
216 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i])
217 {
218 printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
219 __func__, i);
220 violation = 1;
221 goto out;
222 }
223 /* set violation and break out of the loop */
224 /* c) adapt conflict aggregate set for this domain (notice conflicts) */
225 for (i = 0; i < chwall_buf->chwall_max_conflictsets; i++)
226 {
227 int common = 0;
228 /* check if conflict_set_i and ssidref have common types */
229 for (j = 0; j < chwall_buf->chwall_max_types; j++)
230 if (conflict_sets[i * chwall_buf->chwall_max_types + j] &&
231 ssidrefs[chwall_ssidref *
232 chwall_buf->chwall_max_types + j])
233 {
234 common = 1;
235 break;
236 }
237 if (common == 0)
238 continue; /* try next conflict set */
239 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
240 for (j = 0; j < chwall_buf->chwall_max_types; j++)
241 if (conflict_sets[i * chwall_buf->chwall_max_types + j] &&
242 !ssidrefs[chwall_ssidref *
243 chwall_buf->chwall_max_types + j])
244 conflict_aggregate_set[j]++;
245 }
246 }
247 out:
248 write_unlock(&domlist_lock);
249 return violation;
250 /* returning "violation != 0" means that the currently running set of domains would
251 * not be possible if the new policy had been enforced before starting them; for chinese
252 * wall, this means that the new policy includes at least one conflict set of which
253 * more than one type is currently running */
254 }
256 static int chwall_set_policy(u8 * buf, u32 buf_size)
257 {
258 /* policy write-locked already */
259 struct acm_chwall_policy_buffer *chwall_buf =
260 (struct acm_chwall_policy_buffer *) buf;
261 void *ssids = NULL, *conflict_sets = NULL, *running_types =
262 NULL, *conflict_aggregate_set = NULL;
264 if (buf_size < sizeof(struct acm_chwall_policy_buffer))
265 return -EINVAL;
267 /* rewrite the policy due to endianess */
268 chwall_buf->policy_code = ntohl(chwall_buf->policy_code);
269 chwall_buf->policy_version = ntohl(chwall_buf->policy_version);
270 chwall_buf->chwall_max_types = ntohl(chwall_buf->chwall_max_types);
271 chwall_buf->chwall_max_ssidrefs =
272 ntohl(chwall_buf->chwall_max_ssidrefs);
273 chwall_buf->chwall_max_conflictsets =
274 ntohl(chwall_buf->chwall_max_conflictsets);
275 chwall_buf->chwall_ssid_offset = ntohl(chwall_buf->chwall_ssid_offset);
276 chwall_buf->chwall_conflict_sets_offset =
277 ntohl(chwall_buf->chwall_conflict_sets_offset);
278 chwall_buf->chwall_running_types_offset =
279 ntohl(chwall_buf->chwall_running_types_offset);
280 chwall_buf->chwall_conflict_aggregate_offset =
281 ntohl(chwall_buf->chwall_conflict_aggregate_offset);
283 /* policy type and version checks */
284 if ((chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
285 (chwall_buf->policy_version != ACM_CHWALL_VERSION))
286 return -EINVAL;
288 /* 1. allocate new buffers */
289 ssids =
290 xmalloc_array(domaintype_t,
291 chwall_buf->chwall_max_types *
292 chwall_buf->chwall_max_ssidrefs);
293 conflict_sets =
294 xmalloc_array(domaintype_t,
295 chwall_buf->chwall_max_conflictsets *
296 chwall_buf->chwall_max_types);
297 running_types =
298 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
299 conflict_aggregate_set =
300 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
302 if ((ssids == NULL) || (conflict_sets == NULL)
303 || (running_types == NULL) || (conflict_aggregate_set == NULL))
304 goto error_free;
306 /* 2. set new policy */
307 if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
308 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
309 buf_size)
310 goto error_free;
312 arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
313 sizeof(domaintype_t),
314 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
316 if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
317 chwall_buf->chwall_max_types *
318 chwall_buf->chwall_max_conflictsets > buf_size)
319 goto error_free;
321 arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
322 sizeof(domaintype_t),
323 chwall_buf->chwall_max_types *
324 chwall_buf->chwall_max_conflictsets);
326 /* we also use new state buffers since max_types can change */
327 memset(running_types, 0,
328 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
329 memset(conflict_aggregate_set, 0,
330 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
332 /* 3. now re-calculate the state for the new policy based on running domains;
333 * this can fail if new policy is conflicting with running domains */
334 if (chwall_init_state(chwall_buf, ssids,
335 conflict_sets, running_types,
336 conflict_aggregate_set))
337 {
338 printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
339 __func__);
340 goto error_free; /* new policy conflicts with running domains */
341 }
342 /* 4. free old policy buffers, replace with new ones */
343 chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
344 chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
345 chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
346 xfree(chwall_bin_pol.ssidrefs);
347 xfree(chwall_bin_pol.conflict_aggregate_set);
348 xfree(chwall_bin_pol.running_types);
349 xfree(chwall_bin_pol.conflict_sets);
350 chwall_bin_pol.ssidrefs = ssids;
351 chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
352 chwall_bin_pol.running_types = running_types;
353 chwall_bin_pol.conflict_sets = conflict_sets;
354 return ACM_OK;
356 error_free:
357 printk("%s: ERROR setting policy.\n", __func__);
358 xfree(ssids);
359 xfree(conflict_sets);
360 xfree(running_types);
361 xfree(conflict_aggregate_set);
362 return -EFAULT;
363 }
365 static int chwall_dump_stats(u8 * buf, u16 len)
366 {
367 /* no stats for Chinese Wall Policy */
368 return 0;
369 }
371 static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
372 {
373 int i;
375 /* fill in buffer */
376 if (chwall_bin_pol.max_types > len)
377 return -EFAULT;
379 if (ssidref >= chwall_bin_pol.max_ssidrefs)
380 return -EFAULT;
382 /* read types for chwall ssidref */
383 for (i = 0; i < chwall_bin_pol.max_types; i++)
384 {
385 if (chwall_bin_pol.
386 ssidrefs[ssidref * chwall_bin_pol.max_types + i])
387 buf[i] = 1;
388 else
389 buf[i] = 0;
390 }
391 return chwall_bin_pol.max_types;
392 }
394 /***************************
395 * Authorization functions
396 ***************************/
398 /* -------- DOMAIN OPERATION HOOKS -----------*/
400 static int chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
401 {
402 ssidref_t chwall_ssidref;
403 int i, j;
404 traceprintk("%s.\n", __func__);
406 read_lock(&acm_bin_pol_rwlock);
407 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
408 if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID)
409 {
410 printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n",
411 __func__);
412 read_unlock(&acm_bin_pol_rwlock);
413 return ACM_ACCESS_DENIED; /* catching and indicating config error */
414 }
415 if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs)
416 {
417 printk("%s: ERROR chwall_ssidref > max(%x).\n",
418 __func__, chwall_bin_pol.max_ssidrefs - 1);
419 read_unlock(&acm_bin_pol_rwlock);
420 return ACM_ACCESS_DENIED;
421 }
422 /* A: chinese wall check for conflicts */
423 for (i = 0; i < chwall_bin_pol.max_types; i++)
424 if (chwall_bin_pol.conflict_aggregate_set[i] &&
425 chwall_bin_pol.ssidrefs[chwall_ssidref *
426 chwall_bin_pol.max_types + i])
427 {
428 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
429 read_unlock(&acm_bin_pol_rwlock);
430 return ACM_ACCESS_DENIED;
431 }
433 /* B: chinese wall conflict set adjustment (so that other
434 * other domains simultaneously created are evaluated against this new set)*/
435 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
436 {
437 int common = 0;
438 /* check if conflict_set_i and ssidref have common types */
439 for (j = 0; j < chwall_bin_pol.max_types; j++)
440 if (chwall_bin_pol.
441 conflict_sets[i * chwall_bin_pol.max_types + j]
442 && chwall_bin_pol.ssidrefs[chwall_ssidref *
443 chwall_bin_pol.max_types + j])
444 {
445 common = 1;
446 break;
447 }
448 if (common == 0)
449 continue; /* try next conflict set */
450 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
451 for (j = 0; j < chwall_bin_pol.max_types; j++)
452 if (chwall_bin_pol.
453 conflict_sets[i * chwall_bin_pol.max_types + j]
454 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
455 chwall_bin_pol.max_types + j])
456 chwall_bin_pol.conflict_aggregate_set[j]++;
457 }
458 read_unlock(&acm_bin_pol_rwlock);
459 return ACM_ACCESS_PERMITTED;
460 }
462 static void chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
463 {
464 int i, j;
465 ssidref_t chwall_ssidref;
466 traceprintk("%s.\n", __func__);
468 read_lock(&acm_bin_pol_rwlock);
469 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
470 /* adjust types ref-count for running domains */
471 for (i = 0; i < chwall_bin_pol.max_types; i++)
472 chwall_bin_pol.running_types[i] +=
473 chwall_bin_pol.ssidrefs[chwall_ssidref *
474 chwall_bin_pol.max_types + i];
475 if (domid)
476 {
477 read_unlock(&acm_bin_pol_rwlock);
478 return;
479 }
480 /* Xen does not call pre-create hook for DOM0;
481 * to consider type conflicts of any domain with DOM0, we need
482 * to adjust the conflict_aggregate for DOM0 here the same way it
483 * is done for non-DOM0 domains in the pre-hook */
484 printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
485 __func__, ssidref, chwall_ssidref);
487 /* chinese wall conflict set adjustment (so that other
488 * other domains simultaneously created are evaluated against this new set)*/
489 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
490 {
491 int common = 0;
492 /* check if conflict_set_i and ssidref have common types */
493 for (j = 0; j < chwall_bin_pol.max_types; j++)
494 if (chwall_bin_pol.
495 conflict_sets[i * chwall_bin_pol.max_types + j]
496 && chwall_bin_pol.ssidrefs[chwall_ssidref *
497 chwall_bin_pol.max_types + j])
498 {
499 common = 1;
500 break;
501 }
502 if (common == 0)
503 continue; /* try next conflict set */
504 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
505 for (j = 0; j < chwall_bin_pol.max_types; j++)
506 if (chwall_bin_pol.
507 conflict_sets[i * chwall_bin_pol.max_types + j]
508 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
509 chwall_bin_pol.max_types + j])
510 chwall_bin_pol.conflict_aggregate_set[j]++;
511 }
512 read_unlock(&acm_bin_pol_rwlock);
513 return;
514 }
516 static void
517 chwall_fail_domain_create(void *subject_ssid, ssidref_t ssidref)
518 {
519 int i, j;
520 ssidref_t chwall_ssidref;
521 traceprintk("%s.\n", __func__);
523 read_lock(&acm_bin_pol_rwlock);
524 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
525 /* roll-back: re-adjust conflicting types aggregate */
526 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
527 {
528 int common = 0;
529 /* check if conflict_set_i and ssidref have common types */
530 for (j = 0; j < chwall_bin_pol.max_types; j++)
531 if (chwall_bin_pol.
532 conflict_sets[i * chwall_bin_pol.max_types + j]
533 && chwall_bin_pol.ssidrefs[chwall_ssidref *
534 chwall_bin_pol.max_types + j])
535 {
536 common = 1;
537 break;
538 }
539 if (common == 0)
540 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
541 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
542 for (j = 0; j < chwall_bin_pol.max_types; j++)
543 if (chwall_bin_pol.
544 conflict_sets[i * chwall_bin_pol.max_types + j]
545 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
546 chwall_bin_pol.max_types + j])
547 chwall_bin_pol.conflict_aggregate_set[j]--;
548 }
549 read_unlock(&acm_bin_pol_rwlock);
550 }
553 static void chwall_post_domain_destroy(void *object_ssid, domid_t id)
554 {
555 int i, j;
556 struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
557 (struct acm_ssid_domain *)
558 object_ssid);
559 ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
561 traceprintk("%s.\n", __func__);
563 read_lock(&acm_bin_pol_rwlock);
564 /* adjust running types set */
565 for (i = 0; i < chwall_bin_pol.max_types; i++)
566 chwall_bin_pol.running_types[i] -=
567 chwall_bin_pol.ssidrefs[chwall_ssidref *
568 chwall_bin_pol.max_types + i];
570 /* roll-back: re-adjust conflicting types aggregate */
571 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
572 {
573 int common = 0;
574 /* check if conflict_set_i and ssidref have common types */
575 for (j = 0; j < chwall_bin_pol.max_types; j++)
576 if (chwall_bin_pol.
577 conflict_sets[i * chwall_bin_pol.max_types + j]
578 && chwall_bin_pol.ssidrefs[chwall_ssidref *
579 chwall_bin_pol.max_types + j])
580 {
581 common = 1;
582 break;
583 }
584 if (common == 0)
585 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
586 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
587 for (j = 0; j < chwall_bin_pol.max_types; j++)
588 if (chwall_bin_pol.
589 conflict_sets[i * chwall_bin_pol.max_types + j]
590 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
591 chwall_bin_pol.max_types + j])
592 chwall_bin_pol.conflict_aggregate_set[j]--;
593 }
594 read_unlock(&acm_bin_pol_rwlock);
595 return;
596 }
598 struct acm_operations acm_chinesewall_ops = {
599 /* policy management services */
600 .init_domain_ssid = chwall_init_domain_ssid,
601 .free_domain_ssid = chwall_free_domain_ssid,
602 .dump_binary_policy = chwall_dump_policy,
603 .set_binary_policy = chwall_set_policy,
604 .dump_statistics = chwall_dump_stats,
605 .dump_ssid_types = chwall_dump_ssid_types,
606 /* domain management control hooks */
607 .pre_domain_create = chwall_pre_domain_create,
608 .post_domain_create = chwall_post_domain_create,
609 .fail_domain_create = chwall_fail_domain_create,
610 .post_domain_destroy = chwall_post_domain_destroy,
611 /* event channel control hooks */
612 .pre_eventchannel_unbound = NULL,
613 .fail_eventchannel_unbound = NULL,
614 .pre_eventchannel_interdomain = NULL,
615 .fail_eventchannel_interdomain = NULL,
616 /* grant table control hooks */
617 .pre_grant_map_ref = NULL,
618 .fail_grant_map_ref = NULL,
619 .pre_grant_setup = NULL,
620 .fail_grant_setup = NULL,
621 /* generic domain-requested decision hooks */
622 .sharing = NULL,
623 };
625 /*
626 * Local variables:
627 * mode: C
628 * c-set-style: "BSD"
629 * c-basic-offset: 4
630 * tab-width: 4
631 * indent-tabs-mode: nil
632 * End:
633 */