ia64/xen-unstable

annotate xen/acm/acm_chinesewall_hooks.c @ 9738:c4eead8a925b

Only BSP can really do clear_all_shadow_status.
This fixes SMP IA32 VMX guest booting on IA32 xen.

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