ia64/xen-unstable

view xen/acm/acm_chinesewall_hooks.c @ 15452:f152e44325a7

xenconsoled: improve robustness of logfile handling

Check the 'log_reload' on every iteration of the select() loop, not just when
select() returns EINTR. This is because the log reload signal may have
iterrupted a syscall other than select & thus without this change we
might miss the reload signal. The second change makes us process the
hypervisor logs on every iteration of the loop, not just upon timeouts.
This is because if a guest VM were consistently sending some log message
and < 1 second period, the select() would never hit the 1 second timeout
and thus never process the HV logs.

Thanks to Markus Armbruster for pointing out both these edge cases

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author Keir Fraser <keir@xensource.com>
date Wed Jun 27 21:05:54 2007 +0100 (2007-06-27)
parents 4677ee247aa9
children 4a8dbbc16d48
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 /*
187 * Adapt security state (running_types and conflict_aggregate_set) to all
188 * running domains; chwall_init_state is called when a policy is changed
189 * to bring the security information into a consistent state and to detect
190 * violations (return != 0) from a security point of view, we simulate
191 * that all running domains are re-started
192 */
193 static int
194 chwall_init_state(struct acm_chwall_policy_buffer *chwall_buf,
195 domaintype_t * ssidrefs,
196 domaintype_t * conflict_sets,
197 domaintype_t * running_types,
198 domaintype_t * conflict_aggregate_set,
199 struct acm_sized_buffer *errors /* may be NULL */)
200 {
201 int violation = 0, i, j;
202 struct chwall_ssid *chwall_ssid;
203 ssidref_t chwall_ssidref;
204 struct acm_ssid_domain *rawssid;
206 read_lock(&ssid_list_rwlock);
208 /* go through all domains and adjust policy as if this domain was started now */
209 for_each_acmssid( rawssid )
210 {
211 chwall_ssid =
212 GET_SSIDP(ACM_CHINESE_WALL_POLICY, rawssid);
213 chwall_ssidref = chwall_ssid->chwall_ssidref;
214 traceprintk("%s: validating policy for domain %x (chwall-REF=%x).\n",
215 __func__, d->domain_id, chwall_ssidref);
216 /* a) adjust types ref-count for running domains */
217 for (i = 0; i < chwall_buf->chwall_max_types; i++)
218 running_types[i] +=
219 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i];
221 /* b) check for conflict */
222 for (i = 0; i < chwall_buf->chwall_max_types; i++)
223 if (conflict_aggregate_set[i] &&
224 ssidrefs[chwall_ssidref * chwall_buf->chwall_max_types + i])
225 {
226 printk("%s: CHINESE WALL CONFLICT in type %02x.\n",
227 __func__, i);
228 violation = 1;
230 acm_array_append_tuple(errors, ACM_CHWALL_CONFLICT, i);
232 goto out;
233 }
234 /* set violation and break out of the loop */
235 /* c) adapt conflict aggregate set for this domain (notice conflicts) */
236 for (i = 0; i < chwall_buf->chwall_max_conflictsets; i++)
237 {
238 int common = 0;
239 /* check if conflict_set_i and ssidref have common types */
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 {
245 common = 1;
246 break;
247 }
248 if (common == 0)
249 continue; /* try next conflict set */
250 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
251 for (j = 0; j < chwall_buf->chwall_max_types; j++)
252 if (conflict_sets[i * chwall_buf->chwall_max_types + j] &&
253 !ssidrefs[chwall_ssidref *
254 chwall_buf->chwall_max_types + j])
255 conflict_aggregate_set[j]++;
256 }
257 }
258 out:
259 read_unlock(&ssid_list_rwlock);
260 return violation;
261 /* returning "violation != 0" means that the currently running set of domains would
262 * not be possible if the new policy had been enforced before starting them; for chinese
263 * wall, this means that the new policy includes at least one conflict set of which
264 * more than one type is currently running */
265 }
268 int
269 do_chwall_init_state_curr(struct acm_sized_buffer *errors)
270 {
271 struct acm_chwall_policy_buffer chwall_buf = {
272 /* only these two are important */
273 .chwall_max_types = chwall_bin_pol.max_types,
274 .chwall_max_conflictsets = chwall_bin_pol.max_conflictsets,
275 };
276 /* reset running_types and aggregate set for recalculation */
277 memset(chwall_bin_pol.running_types,
278 0x0,
279 sizeof(domaintype_t) * chwall_bin_pol.max_types);
280 memset(chwall_bin_pol.conflict_aggregate_set,
281 0x0,
282 sizeof(domaintype_t) * chwall_bin_pol.max_types);
283 return chwall_init_state(&chwall_buf,
284 chwall_bin_pol.ssidrefs,
285 chwall_bin_pol.conflict_sets,
286 chwall_bin_pol.running_types,
287 chwall_bin_pol.conflict_aggregate_set,
288 errors);
289 }
291 /*
292 * Attempt to set the policy. This function must be called in test_only
293 * mode first to only perform checks. A second call then does the
294 * actual changes.
295 */
296 static int _chwall_update_policy(u8 *buf, u32 buf_size, int test_only,
297 struct acm_sized_buffer *errors)
298 {
299 int rc = -EFAULT;
300 /* policy write-locked already */
301 struct acm_chwall_policy_buffer *chwall_buf =
302 (struct acm_chwall_policy_buffer *) buf;
303 void *ssids = NULL, *conflict_sets = NULL, *running_types =
304 NULL, *conflict_aggregate_set = NULL;
306 /* 1. allocate new buffers */
307 ssids =
308 xmalloc_array(domaintype_t,
309 chwall_buf->chwall_max_types *
310 chwall_buf->chwall_max_ssidrefs);
311 conflict_sets =
312 xmalloc_array(domaintype_t,
313 chwall_buf->chwall_max_conflictsets *
314 chwall_buf->chwall_max_types);
315 running_types =
316 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
317 conflict_aggregate_set =
318 xmalloc_array(domaintype_t, chwall_buf->chwall_max_types);
320 if ((ssids == NULL) || (conflict_sets == NULL)
321 || (running_types == NULL) || (conflict_aggregate_set == NULL))
322 goto error_free;
324 /* 2. set new policy */
325 if (chwall_buf->chwall_ssid_offset + sizeof(domaintype_t) *
326 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs >
327 buf_size)
328 goto error_free;
330 arrcpy(ssids, buf + chwall_buf->chwall_ssid_offset,
331 sizeof(domaintype_t),
332 chwall_buf->chwall_max_types * chwall_buf->chwall_max_ssidrefs);
334 if (chwall_buf->chwall_conflict_sets_offset + sizeof(domaintype_t) *
335 chwall_buf->chwall_max_types *
336 chwall_buf->chwall_max_conflictsets > buf_size)
337 goto error_free;
339 arrcpy(conflict_sets, buf + chwall_buf->chwall_conflict_sets_offset,
340 sizeof(domaintype_t),
341 chwall_buf->chwall_max_types *
342 chwall_buf->chwall_max_conflictsets);
344 /* we also use new state buffers since max_types can change */
345 memset(running_types, 0,
346 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
347 memset(conflict_aggregate_set, 0,
348 sizeof(domaintype_t) * chwall_buf->chwall_max_types);
350 /* 3. now re-calculate the state for the new policy based on running domains;
351 * this can fail if new policy is conflicting with running domains */
352 if (chwall_init_state(chwall_buf, ssids,
353 conflict_sets, running_types,
354 conflict_aggregate_set,
355 errors))
356 {
357 printk("%s: New policy conflicts with running domains. Policy load aborted.\n",
358 __func__);
359 goto error_free; /* new policy conflicts with running domains */
360 }
362 /* if this was only a test run, exit with ACM_OK */
363 if (test_only) {
364 rc = ACM_OK;
365 goto error_free;
366 }
368 /* 4. free old policy buffers, replace with new ones */
369 chwall_bin_pol.max_types = chwall_buf->chwall_max_types;
370 chwall_bin_pol.max_ssidrefs = chwall_buf->chwall_max_ssidrefs;
371 chwall_bin_pol.max_conflictsets = chwall_buf->chwall_max_conflictsets;
372 xfree(chwall_bin_pol.ssidrefs);
373 xfree(chwall_bin_pol.conflict_aggregate_set);
374 xfree(chwall_bin_pol.running_types);
375 xfree(chwall_bin_pol.conflict_sets);
376 chwall_bin_pol.ssidrefs = ssids;
377 chwall_bin_pol.conflict_aggregate_set = conflict_aggregate_set;
378 chwall_bin_pol.running_types = running_types;
379 chwall_bin_pol.conflict_sets = conflict_sets;
380 return ACM_OK;
382 error_free:
383 if (!test_only) printk("%s: ERROR setting policy.\n", __func__);
384 xfree(ssids);
385 xfree(conflict_sets);
386 xfree(running_types);
387 xfree(conflict_aggregate_set);
388 return rc;
389 }
391 /*
392 * This function MUST be called before the chwall_ste_policy function!
393 */
394 static int chwall_test_policy(u8 *buf, u32 buf_size, int is_bootpolicy,
395 struct acm_sized_buffer *errors)
396 {
397 struct acm_chwall_policy_buffer *chwall_buf =
398 (struct acm_chwall_policy_buffer *) buf;
400 if (buf_size < sizeof(struct acm_chwall_policy_buffer))
401 return -EINVAL;
403 /* rewrite the policy due to endianess */
404 chwall_buf->policy_code = be32_to_cpu(chwall_buf->policy_code);
405 chwall_buf->policy_version = be32_to_cpu(chwall_buf->policy_version);
406 chwall_buf->chwall_max_types =
407 be32_to_cpu(chwall_buf->chwall_max_types);
408 chwall_buf->chwall_max_ssidrefs =
409 be32_to_cpu(chwall_buf->chwall_max_ssidrefs);
410 chwall_buf->chwall_max_conflictsets =
411 be32_to_cpu(chwall_buf->chwall_max_conflictsets);
412 chwall_buf->chwall_ssid_offset =
413 be32_to_cpu(chwall_buf->chwall_ssid_offset);
414 chwall_buf->chwall_conflict_sets_offset =
415 be32_to_cpu(chwall_buf->chwall_conflict_sets_offset);
416 chwall_buf->chwall_running_types_offset =
417 be32_to_cpu(chwall_buf->chwall_running_types_offset);
418 chwall_buf->chwall_conflict_aggregate_offset =
419 be32_to_cpu(chwall_buf->chwall_conflict_aggregate_offset);
421 /* policy type and version checks */
422 if ((chwall_buf->policy_code != ACM_CHINESE_WALL_POLICY) ||
423 (chwall_buf->policy_version != ACM_CHWALL_VERSION))
424 return -EINVAL;
426 /* during boot dom0_chwall_ssidref is set */
427 if (is_bootpolicy &&
428 (dom0_chwall_ssidref >= chwall_buf->chwall_max_ssidrefs))
429 return -EINVAL;
432 return _chwall_update_policy(buf, buf_size, 1, errors);
433 }
435 static int chwall_set_policy(u8 *buf, u32 buf_size)
436 {
437 return _chwall_update_policy(buf, buf_size, 0, NULL);
438 }
440 static int chwall_dump_stats(u8 * buf, u16 len)
441 {
442 /* no stats for Chinese Wall Policy */
443 return 0;
444 }
446 static int chwall_dump_ssid_types(ssidref_t ssidref, u8 * buf, u16 len)
447 {
448 int i;
450 /* fill in buffer */
451 if (chwall_bin_pol.max_types > len)
452 return -EFAULT;
454 if (ssidref >= chwall_bin_pol.max_ssidrefs)
455 return -EFAULT;
457 /* read types for chwall ssidref */
458 for (i = 0; i < chwall_bin_pol.max_types; i++)
459 {
460 if (chwall_bin_pol.
461 ssidrefs[ssidref * chwall_bin_pol.max_types + i])
462 buf[i] = 1;
463 else
464 buf[i] = 0;
465 }
466 return chwall_bin_pol.max_types;
467 }
469 /***************************
470 * Authorization functions
471 ***************************/
473 /* -------- DOMAIN OPERATION HOOKS -----------*/
475 static int _chwall_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
476 {
477 ssidref_t chwall_ssidref;
478 int i, j;
479 traceprintk("%s.\n", __func__);
481 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
482 if (chwall_ssidref == ACM_DEFAULT_LOCAL_SSID)
483 {
484 printk("%s: ERROR CHWALL SSID is NOT SET but policy enforced.\n",
485 __func__);
486 return ACM_ACCESS_DENIED; /* catching and indicating config error */
487 }
488 if (chwall_ssidref >= chwall_bin_pol.max_ssidrefs)
489 {
490 printk("%s: ERROR chwall_ssidref > max(%x).\n",
491 __func__, chwall_bin_pol.max_ssidrefs - 1);
492 return ACM_ACCESS_DENIED;
493 }
494 /* A: chinese wall check for conflicts */
495 for (i = 0; i < chwall_bin_pol.max_types; i++)
496 if (chwall_bin_pol.conflict_aggregate_set[i] &&
497 chwall_bin_pol.ssidrefs[chwall_ssidref *
498 chwall_bin_pol.max_types + i])
499 {
500 printk("%s: CHINESE WALL CONFLICT in type %02x.\n", __func__, i);
501 return ACM_ACCESS_DENIED;
502 }
504 /* B: chinese wall conflict set adjustment (so that other
505 * other domains simultaneously created are evaluated against this new set)*/
506 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
507 {
508 int common = 0;
509 /* check if conflict_set_i and ssidref have common types */
510 for (j = 0; j < chwall_bin_pol.max_types; j++)
511 if (chwall_bin_pol.
512 conflict_sets[i * chwall_bin_pol.max_types + j]
513 && chwall_bin_pol.ssidrefs[chwall_ssidref *
514 chwall_bin_pol.max_types + j])
515 {
516 common = 1;
517 break;
518 }
519 if (common == 0)
520 continue; /* try next conflict set */
521 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
522 for (j = 0; j < chwall_bin_pol.max_types; j++)
523 if (chwall_bin_pol.
524 conflict_sets[i * chwall_bin_pol.max_types + j]
525 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
526 chwall_bin_pol.max_types + j])
527 chwall_bin_pol.conflict_aggregate_set[j]++;
528 }
529 return ACM_ACCESS_PERMITTED;
530 }
533 static void _chwall_post_domain_create(domid_t domid, ssidref_t ssidref)
534 {
535 int i, j;
536 ssidref_t chwall_ssidref;
537 traceprintk("%s.\n", __func__);
539 chwall_ssidref = GET_SSIDREF(ACM_CHINESE_WALL_POLICY, ssidref);
540 /* adjust types ref-count for running domains */
541 for (i = 0; i < chwall_bin_pol.max_types; i++)
542 chwall_bin_pol.running_types[i] +=
543 chwall_bin_pol.ssidrefs[chwall_ssidref *
544 chwall_bin_pol.max_types + i];
545 if (domid)
546 {
547 return;
548 }
549 /* Xen does not call pre-create hook for DOM0;
550 * to consider type conflicts of any domain with DOM0, we need
551 * to adjust the conflict_aggregate for DOM0 here the same way it
552 * is done for non-DOM0 domains in the pre-hook */
553 printkd("%s: adjusting security state for DOM0 (ssidref=%x, chwall_ssidref=%x).\n",
554 __func__, ssidref, chwall_ssidref);
556 /* chinese wall conflict set adjustment (so that other
557 * other domains simultaneously created are evaluated against this new set)*/
558 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
559 {
560 int common = 0;
561 /* check if conflict_set_i and ssidref have common types */
562 for (j = 0; j < chwall_bin_pol.max_types; j++)
563 if (chwall_bin_pol.
564 conflict_sets[i * chwall_bin_pol.max_types + j]
565 && chwall_bin_pol.ssidrefs[chwall_ssidref *
566 chwall_bin_pol.max_types + j])
567 {
568 common = 1;
569 break;
570 }
571 if (common == 0)
572 continue; /* try next conflict set */
573 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
574 for (j = 0; j < chwall_bin_pol.max_types; j++)
575 if (chwall_bin_pol.
576 conflict_sets[i * chwall_bin_pol.max_types + j]
577 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
578 chwall_bin_pol.max_types + j])
579 chwall_bin_pol.conflict_aggregate_set[j]++;
580 }
581 return;
582 }
585 /*
586 * To be called when creating a domain. If this call is unsuccessful,
587 * no state changes have occurred (adjustments of counters etc.). If it
588 * was successful, state was changed and can be undone using
589 * chwall_domain_destroy.
590 */
591 static int chwall_domain_create(void *subject_ssid, ssidref_t ssidref,
592 domid_t domid)
593 {
594 int rc;
595 read_lock(&acm_bin_pol_rwlock);
596 rc = _chwall_pre_domain_create(subject_ssid, ssidref);
597 if (rc == ACM_ACCESS_PERMITTED) {
598 _chwall_post_domain_create(domid, ssidref);
599 }
600 read_unlock(&acm_bin_pol_rwlock);
601 return rc;
602 }
604 /*
605 * This function undoes everything a successful call to
606 * chwall_domain_create has done.
607 */
608 static void chwall_domain_destroy(void *object_ssid, struct domain *d)
609 {
610 int i, j;
611 struct chwall_ssid *chwall_ssidp = GET_SSIDP(ACM_CHINESE_WALL_POLICY,
612 (struct acm_ssid_domain *)
613 object_ssid);
614 ssidref_t chwall_ssidref = chwall_ssidp->chwall_ssidref;
616 traceprintk("%s.\n", __func__);
618 read_lock(&acm_bin_pol_rwlock);
619 /* adjust running types set */
620 for (i = 0; i < chwall_bin_pol.max_types; i++)
621 chwall_bin_pol.running_types[i] -=
622 chwall_bin_pol.ssidrefs[chwall_ssidref *
623 chwall_bin_pol.max_types + i];
625 /* roll-back: re-adjust conflicting types aggregate */
626 for (i = 0; i < chwall_bin_pol.max_conflictsets; i++)
627 {
628 int common = 0;
629 /* check if conflict_set_i and ssidref have common types */
630 for (j = 0; j < chwall_bin_pol.max_types; j++)
631 if (chwall_bin_pol.
632 conflict_sets[i * chwall_bin_pol.max_types + j]
633 && chwall_bin_pol.ssidrefs[chwall_ssidref *
634 chwall_bin_pol.max_types + j])
635 {
636 common = 1;
637 break;
638 }
639 if (common == 0)
640 continue; /* try next conflict set, this one does not include any type of chwall_ssidref */
641 /* now add types of the conflict set to conflict_aggregate_set (except types in chwall_ssidref) */
642 for (j = 0; j < chwall_bin_pol.max_types; j++)
643 if (chwall_bin_pol.
644 conflict_sets[i * chwall_bin_pol.max_types + j]
645 && !chwall_bin_pol.ssidrefs[chwall_ssidref *
646 chwall_bin_pol.max_types + j])
647 chwall_bin_pol.conflict_aggregate_set[j]--;
648 }
649 read_unlock(&acm_bin_pol_rwlock);
650 return;
651 }
653 struct acm_operations acm_chinesewall_ops = {
654 /* policy management services */
655 .init_domain_ssid = chwall_init_domain_ssid,
656 .free_domain_ssid = chwall_free_domain_ssid,
657 .dump_binary_policy = chwall_dump_policy,
658 .test_binary_policy = chwall_test_policy,
659 .set_binary_policy = chwall_set_policy,
660 .dump_statistics = chwall_dump_stats,
661 .dump_ssid_types = chwall_dump_ssid_types,
662 /* domain management control hooks */
663 .domain_create = chwall_domain_create,
664 .domain_destroy = chwall_domain_destroy,
665 /* event channel control hooks */
666 .pre_eventchannel_unbound = NULL,
667 .fail_eventchannel_unbound = NULL,
668 .pre_eventchannel_interdomain = NULL,
669 .fail_eventchannel_interdomain = NULL,
670 /* grant table control hooks */
671 .pre_grant_map_ref = NULL,
672 .fail_grant_map_ref = NULL,
673 .pre_grant_setup = NULL,
674 .fail_grant_setup = NULL,
675 /* generic domain-requested decision hooks */
676 .sharing = NULL,
677 };
679 /*
680 * Local variables:
681 * mode: C
682 * c-set-style: "BSD"
683 * c-basic-offset: 4
684 * tab-width: 4
685 * indent-tabs-mode: nil
686 * End:
687 */