ia64/xen-unstable

view xen/acm/acm_core.c @ 10123:d9f63f9361c4

[LOADER] Another change to the elf_paddr_offset/virt_base logic.
This avoids using zero to indicate 'undefined'. Instead we use
an explicit boolean to indicate whether suitable defaults should
be used. As well as making the logic clearer (I believe) it also
avoids problems if anyone ever explicitly specifies virt_base
(and also elf_paddr_offset) as zero.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun May 21 18:55:14 2006 +0100 (2006-05-21)
parents 0a5183b3e7bb
children 96b1479305ce
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 = acm_set_policy((void *)_policy_start,
226 (u32)_policy_len,
227 0);
228 if (rc == ACM_OK)
229 {
230 printkd("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
231 if (i == 1)
232 {
233 if (mbi->mods_count > 2)
234 {
235 *initrdidx = 2;
236 }
237 else {
238 *initrdidx = 0;
239 }
240 }
241 else
242 {
243 *initrdidx = 1;
244 }
245 break;
246 }
247 else
248 {
249 printk("Invalid policy. %d.th module line.\n", i+1);
250 /* load default policy later */
251 acm_active_security_policy = ACM_POLICY_UNDEFINED;
252 }
253 } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
254 }
255 return rc;
256 }
259 int
260 acm_init(unsigned int *initrdidx,
261 const multiboot_info_t *mbi,
262 unsigned long initial_images_start)
263 {
264 int ret = ACM_OK;
266 acm_set_endian();
268 /* first try to load the boot policy (uses its own locks) */
269 acm_setup(initrdidx, mbi, initial_images_start);
271 if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
272 {
273 printk("%s: Enforcing %s boot policy.\n", __func__,
274 ACM_POLICY_NAME(acm_active_security_policy));
275 goto out;
276 }
277 /* else continue with the minimal hardcoded default startup policy */
278 printk("%s: Loading default policy (%s).\n",
279 __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
281 if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
282 ret = -EINVAL;
283 goto out;
284 }
285 acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
286 if (acm_active_security_policy != ACM_NULL_POLICY)
287 acm_bin_pol.policy_reference_name = "DEFAULT";
288 else
289 acm_bin_pol.policy_reference_name = "NULL";
291 out:
292 if (ret != ACM_OK)
293 {
294 printk("%s: Error initializing policies.\n", __func__);
295 /* here one could imagine a clean panic */
296 return -EINVAL;
297 }
298 return ret;
299 }
301 int
302 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
303 {
304 struct acm_ssid_domain *ssid;
305 struct domain *subj = find_domain_by_id(id);
306 int ret1, ret2;
308 if (subj == NULL)
309 {
310 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
311 return ACM_NULL_POINTER_ERROR;
312 }
313 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
314 {
315 put_domain(subj);
316 return ACM_INIT_SSID_ERROR;
317 }
319 ssid->datatype = DOMAIN;
320 ssid->subject = subj;
321 ssid->domainid = subj->domain_id;
322 ssid->primary_ssid = NULL;
323 ssid->secondary_ssid = NULL;
325 if (acm_active_security_policy != ACM_NULL_POLICY)
326 ssid->ssidref = ssidref;
327 else
328 ssid->ssidref = ACM_DEFAULT_SSID;
330 subj->ssid = ssid;
331 /* now fill in primary and secondary parts; we only get here through hooks */
332 if (acm_primary_ops->init_domain_ssid != NULL)
333 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
334 else
335 ret1 = ACM_OK;
337 if (acm_secondary_ops->init_domain_ssid != NULL)
338 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
339 else
340 ret2 = ACM_OK;
342 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
343 {
344 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
345 __func__, subj->domain_id);
346 acm_free_domain_ssid(ssid);
347 put_domain(subj);
348 return ACM_INIT_SSID_ERROR;
349 }
350 printkd("%s: assigned domain %x the ssidref=%x.\n",
351 __func__, id, ssid->ssidref);
352 put_domain(subj);
353 return ACM_OK;
354 }
357 void
358 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
359 {
360 /* domain is already gone, just ssid is left */
361 if (ssid == NULL)
362 return;
364 ssid->subject = NULL;
365 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
366 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
367 ssid->primary_ssid = NULL;
368 if (acm_secondary_ops->free_domain_ssid != NULL)
369 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
370 ssid->secondary_ssid = NULL;
371 xfree(ssid);
372 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
373 __func__, id);
374 }
376 /*
377 * Local variables:
378 * mode: C
379 * c-set-style: "BSD"
380 * c-basic-offset: 4
381 * tab-width: 4
382 * indent-tabs-mode: nil
383 * End:
384 */