ia64/xen-unstable

view xen/acm/acm_core.c @ 10718:3cdb93867f81

Domain ID/index mapping in xenmon.

This patch addresses the problem of xenbaked/xenmon not dealing with
large domain ID's. Xen Domain ID's increase monotonically as domains
are created; The ID's are not (often) recycled. Xenbaked was using the
domain
ID's as indices to arrays of data, and this scheme blows up as soon as
a domain ID exceeds the array size. Code has been changed in xenbaked
and xenmon to isolate domain id's from array indices, so everything is
indirect. Users should not notice any difference in behavior.

From: Rob Gardner <rob.gardner@hp.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Jul 10 16:09:20 2006 +0100 (2006-07-10)
parents 21e6625a6c01
children 88e6bd5e2b54
line source
1 /****************************************************************
2 * acm_core.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * Contributors:
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 access control module (ACM)
18 * This file handles initialization of the ACM
19 * as well as initializing/freeing security
20 * identifiers for domains (it calls on active
21 * policy hook functions).
22 *
23 */
25 #include <xen/config.h>
26 #include <xen/errno.h>
27 #include <xen/types.h>
28 #include <xen/lib.h>
29 #include <xen/delay.h>
30 #include <xen/sched.h>
31 #include <xen/multiboot.h>
32 #include <acm/acm_hooks.h>
33 #include <acm/acm_endian.h>
35 /* debug:
36 * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE;
37 * define/undefine this constant to receive / suppress any
38 * security hook debug output of sHype
39 *
40 * include/public/acm.h defines a constant ACM_DEBUG
41 * define/undefine this constant to receive non-hook-related
42 * debug output.
43 */
45 /* function prototypes */
46 void acm_init_chwall_policy(void);
47 void acm_init_ste_policy(void);
49 extern struct acm_operations acm_chinesewall_ops,
50 acm_simple_type_enforcement_ops, acm_null_ops;
52 /* global ACM policy (now dynamically determined at boot time) */
53 u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
55 /* global ops structs called by the hooks */
56 struct acm_operations *acm_primary_ops = NULL;
57 /* called in hook if-and-only-if primary succeeds */
58 struct acm_operations *acm_secondary_ops = NULL;
60 /* acm global binary policy (points to 'local' primary and secondary policies */
61 struct acm_binary_policy acm_bin_pol;
62 /* acm binary policy lock */
63 rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
65 /* until we have endian support in Xen, we discover it at runtime */
66 u8 little_endian = 1;
67 void
68 acm_set_endian(void)
69 {
70 u32 test = 1;
71 if (*((u8 *)&test) == 1)
72 {
73 printkd("ACM module running in LITTLE ENDIAN.\n");
74 little_endian = 1;
75 }
76 else
77 {
78 printkd("ACM module running in BIG ENDIAN.\n");
79 little_endian = 0;
80 }
81 }
83 int
84 acm_set_policy_reference(u8 * buf, u32 buf_size)
85 {
86 struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
87 acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, ntohl(pr->len));
89 if (!acm_bin_pol.policy_reference_name)
90 return -ENOMEM;
92 strcpy(acm_bin_pol.policy_reference_name, (char *)(buf + sizeof(struct acm_policy_reference_buffer)));
93 printk("%s: Activating policy %s\n", __func__, acm_bin_pol.policy_reference_name);
94 return 0;
95 }
97 int
98 acm_dump_policy_reference(u8 *buf, u32 buf_size)
99 {
100 struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
101 int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
103 if (buf_size < ret)
104 return -EINVAL;
106 pr_buf->len = htonl(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
107 strcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
108 acm_bin_pol.policy_reference_name);
109 return ret;
110 }
112 int
113 acm_init_binary_policy(u32 policy_code)
114 {
115 int ret = ACM_OK;
117 acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
118 acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
120 write_lock(&acm_bin_pol_rwlock);
122 /* set primary policy component */
123 switch ((policy_code) & 0x0f)
124 {
126 case ACM_CHINESE_WALL_POLICY:
127 acm_init_chwall_policy();
128 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
129 acm_primary_ops = &acm_chinesewall_ops;
130 break;
132 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
133 acm_init_ste_policy();
134 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
135 acm_primary_ops = &acm_simple_type_enforcement_ops;
136 break;
138 case ACM_NULL_POLICY:
139 acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
140 acm_primary_ops = &acm_null_ops;
141 break;
143 default:
144 /* Unknown policy not allowed primary */
145 ret = -EINVAL;
146 goto out;
147 }
149 /* secondary policy component part */
150 switch ((policy_code) >> 4)
151 {
153 case ACM_NULL_POLICY:
154 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
155 acm_secondary_ops = &acm_null_ops;
156 break;
158 case ACM_CHINESE_WALL_POLICY:
159 if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
160 { /* not a valid combination */
161 ret = -EINVAL;
162 goto out;
163 }
164 acm_init_chwall_policy();
165 acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
166 acm_secondary_ops = &acm_chinesewall_ops;
167 break;
169 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
170 if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
171 { /* not a valid combination */
172 ret = -EINVAL;
173 goto out;
174 }
175 acm_init_ste_policy();
176 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
177 acm_secondary_ops = &acm_simple_type_enforcement_ops;
178 break;
180 default:
181 ret = -EINVAL;
182 goto out;
183 }
185 out:
186 write_unlock(&acm_bin_pol_rwlock);
187 return ret;
188 }
190 static int
191 acm_setup(unsigned int *initrdidx,
192 const multiboot_info_t *mbi,
193 unsigned long initial_images_start)
194 {
195 int i;
196 module_t *mod = (module_t *)__va(mbi->mods_addr);
197 int rc = ACM_OK;
199 if (mbi->mods_count > 1)
200 *initrdidx = 1;
202 /*
203 * Try all modules and see whichever could be the binary policy.
204 * Adjust the initrdidx if module[1] is the binary policy.
205 */
206 for (i = mbi->mods_count-1; i >= 1; i--)
207 {
208 struct acm_policy_buffer *pol;
209 char *_policy_start;
210 unsigned long _policy_len;
211 #if defined(__i386__)
212 _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
213 #elif defined(__x86_64__)
214 _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
215 #else
216 #error Architecture unsupported by sHype
217 #endif
218 _policy_len = mod[i].mod_end - mod[i].mod_start;
219 if (_policy_len < sizeof(struct acm_policy_buffer))
220 continue; /* not a policy */
222 pol = (struct acm_policy_buffer *)_policy_start;
223 if (ntohl(pol->magic) == ACM_MAGIC)
224 {
225 rc = do_acm_set_policy((void *)_policy_start,
226 (u32)_policy_len);
227 if (rc == ACM_OK)
228 {
229 printkd("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
230 if (i == 1)
231 {
232 if (mbi->mods_count > 2)
233 {
234 *initrdidx = 2;
235 }
236 else {
237 *initrdidx = 0;
238 }
239 }
240 else
241 {
242 *initrdidx = 1;
243 }
244 break;
245 }
246 else
247 {
248 printk("Invalid policy. %d.th module line.\n", i+1);
249 /* load default policy later */
250 acm_active_security_policy = ACM_POLICY_UNDEFINED;
251 }
252 } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
253 }
254 return rc;
255 }
258 int
259 acm_init(unsigned int *initrdidx,
260 const multiboot_info_t *mbi,
261 unsigned long initial_images_start)
262 {
263 int ret = ACM_OK;
265 acm_set_endian();
267 /* first try to load the boot policy (uses its own locks) */
268 acm_setup(initrdidx, mbi, initial_images_start);
270 if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
271 {
272 printk("%s: Enforcing %s boot policy.\n", __func__,
273 ACM_POLICY_NAME(acm_active_security_policy));
274 goto out;
275 }
276 /* else continue with the minimal hardcoded default startup policy */
277 printk("%s: Loading default policy (%s).\n",
278 __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
280 if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
281 ret = -EINVAL;
282 goto out;
283 }
284 acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
285 if (acm_active_security_policy != ACM_NULL_POLICY)
286 acm_bin_pol.policy_reference_name = "DEFAULT";
287 else
288 acm_bin_pol.policy_reference_name = "NULL";
290 out:
291 if (ret != ACM_OK)
292 {
293 printk("%s: Error initializing policies.\n", __func__);
294 /* here one could imagine a clean panic */
295 return -EINVAL;
296 }
297 return ret;
298 }
300 int
301 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
302 {
303 struct acm_ssid_domain *ssid;
304 struct domain *subj = find_domain_by_id(id);
305 int ret1, ret2;
307 if (subj == NULL)
308 {
309 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
310 return ACM_NULL_POINTER_ERROR;
311 }
312 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
313 {
314 put_domain(subj);
315 return ACM_INIT_SSID_ERROR;
316 }
318 ssid->datatype = ACM_DATATYPE_domain;
319 ssid->subject = subj;
320 ssid->domainid = subj->domain_id;
321 ssid->primary_ssid = NULL;
322 ssid->secondary_ssid = NULL;
324 if (acm_active_security_policy != ACM_NULL_POLICY)
325 ssid->ssidref = ssidref;
326 else
327 ssid->ssidref = ACM_DEFAULT_SSID;
329 subj->ssid = ssid;
330 /* now fill in primary and secondary parts; we only get here through hooks */
331 if (acm_primary_ops->init_domain_ssid != NULL)
332 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
333 else
334 ret1 = ACM_OK;
336 if (acm_secondary_ops->init_domain_ssid != NULL)
337 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
338 else
339 ret2 = ACM_OK;
341 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
342 {
343 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
344 __func__, subj->domain_id);
345 acm_free_domain_ssid(ssid);
346 put_domain(subj);
347 return ACM_INIT_SSID_ERROR;
348 }
349 printkd("%s: assigned domain %x the ssidref=%x.\n",
350 __func__, id, ssid->ssidref);
351 put_domain(subj);
352 return ACM_OK;
353 }
356 void
357 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
358 {
359 /* domain is already gone, just ssid is left */
360 if (ssid == NULL)
361 return;
363 ssid->subject = NULL;
364 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
365 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
366 ssid->primary_ssid = NULL;
367 if (acm_secondary_ops->free_domain_ssid != NULL)
368 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
369 ssid->secondary_ssid = NULL;
370 xfree(ssid);
371 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
372 __func__, id);
373 }
375 /*
376 * Local variables:
377 * mode: C
378 * c-set-style: "BSD"
379 * c-basic-offset: 4
380 * tab-width: 4
381 * indent-tabs-mode: nil
382 * End:
383 */