ia64/xen-unstable

view xen/acm/acm_core.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 cc1d77bba4b0
children 0a5183b3e7bb
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 printk("ACM module running in LITTLE ENDIAN.\n");
74 little_endian = 1;
75 }
76 else
77 {
78 printk("ACM module running in BIG ENDIAN.\n");
79 little_endian = 0;
80 }
81 }
83 int
84 acm_init_binary_policy(u32 policy_code)
85 {
86 int ret = ACM_OK;
88 acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
89 acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
91 write_lock(&acm_bin_pol_rwlock);
93 /* set primary policy component */
94 switch ((policy_code) & 0x0f)
95 {
97 case ACM_CHINESE_WALL_POLICY:
98 acm_init_chwall_policy();
99 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
100 acm_primary_ops = &acm_chinesewall_ops;
101 break;
103 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
104 acm_init_ste_policy();
105 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
106 acm_primary_ops = &acm_simple_type_enforcement_ops;
107 break;
109 case ACM_NULL_POLICY:
110 acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
111 acm_primary_ops = &acm_null_ops;
112 break;
114 default:
115 /* Unknown policy not allowed primary */
116 ret = -EINVAL;
117 goto out;
118 }
120 /* secondary policy component part */
121 switch ((policy_code) >> 4)
122 {
124 case ACM_NULL_POLICY:
125 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
126 acm_secondary_ops = &acm_null_ops;
127 break;
129 case ACM_CHINESE_WALL_POLICY:
130 if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
131 { /* not a valid combination */
132 ret = -EINVAL;
133 goto out;
134 }
135 acm_init_chwall_policy();
136 acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
137 acm_secondary_ops = &acm_chinesewall_ops;
138 break;
140 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
141 if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
142 { /* not a valid combination */
143 ret = -EINVAL;
144 goto out;
145 }
146 acm_init_ste_policy();
147 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
148 acm_secondary_ops = &acm_simple_type_enforcement_ops;
149 break;
151 default:
152 ret = -EINVAL;
153 goto out;
154 }
156 out:
157 write_unlock(&acm_bin_pol_rwlock);
158 return ret;
159 }
161 static int
162 acm_setup(unsigned int *initrdidx,
163 const multiboot_info_t *mbi,
164 unsigned long initial_images_start)
165 {
166 int i;
167 module_t *mod = (module_t *)__va(mbi->mods_addr);
168 int rc = ACM_OK;
170 if (mbi->mods_count > 1)
171 *initrdidx = 1;
173 /*
174 * Try all modules and see whichever could be the binary policy.
175 * Adjust the initrdidx if module[1] is the binary policy.
176 */
177 for (i = mbi->mods_count-1; i >= 1; i--)
178 {
179 struct acm_policy_buffer *pol;
180 char *_policy_start;
181 unsigned long _policy_len;
182 #if defined(__i386__)
183 _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
184 #elif defined(__x86_64__)
185 _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
186 #else
187 #error Architecture unsupported by sHype
188 #endif
189 _policy_len = mod[i].mod_end - mod[i].mod_start;
190 if (_policy_len < sizeof(struct acm_policy_buffer))
191 continue; /* not a policy */
193 pol = (struct acm_policy_buffer *)_policy_start;
194 if (ntohl(pol->magic) == ACM_MAGIC)
195 {
196 rc = acm_set_policy((void *)_policy_start,
197 (u32)_policy_len,
198 0);
199 if (rc == ACM_OK)
200 {
201 printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
202 if (i == 1)
203 {
204 if (mbi->mods_count > 2)
205 {
206 *initrdidx = 2;
207 }
208 else {
209 *initrdidx = 0;
210 }
211 }
212 else
213 {
214 *initrdidx = 1;
215 }
216 break;
217 }
218 else
219 {
220 printk("Invalid policy. %d.th module line.\n", i+1);
221 }
222 } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
223 }
224 return rc;
225 }
228 int
229 acm_init(unsigned int *initrdidx,
230 const multiboot_info_t *mbi,
231 unsigned long initial_images_start)
232 {
233 int ret = ACM_OK;
235 acm_set_endian();
237 /* first try to load the boot policy (uses its own locks) */
238 acm_setup(initrdidx, mbi, initial_images_start);
240 if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
241 {
242 printk("%s: Boot-Policy. Enforcing %s: Primary %s, Secondary %s.\n", __func__,
243 ACM_POLICY_NAME(acm_active_security_policy),
244 ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
245 ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
246 goto out;
247 }
248 /* else continue with the minimal hardcoded default startup policy */
249 printk("%s: Loading default policy (%s).\n",
250 __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
252 if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
253 ret = -EINVAL;
254 goto out;
255 }
256 acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
258 out:
259 if (ret != ACM_OK)
260 {
261 printk("%s: Error initializing policies.\n", __func__);
262 /* here one could imagine a clean panic */
263 return -EINVAL;
264 }
265 return ret;
266 }
268 int
269 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
270 {
271 struct acm_ssid_domain *ssid;
272 struct domain *subj = find_domain_by_id(id);
273 int ret1, ret2;
275 if (subj == NULL)
276 {
277 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
278 return ACM_NULL_POINTER_ERROR;
279 }
280 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
281 {
282 put_domain(subj);
283 return ACM_INIT_SSID_ERROR;
284 }
286 ssid->datatype = DOMAIN;
287 ssid->subject = subj;
288 ssid->domainid = subj->domain_id;
289 ssid->primary_ssid = NULL;
290 ssid->secondary_ssid = NULL;
292 if (acm_active_security_policy != ACM_NULL_POLICY)
293 ssid->ssidref = ssidref;
294 else
295 ssid->ssidref = ACM_DEFAULT_SSID;
297 subj->ssid = ssid;
298 /* now fill in primary and secondary parts; we only get here through hooks */
299 if (acm_primary_ops->init_domain_ssid != NULL)
300 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
301 else
302 ret1 = ACM_OK;
304 if (acm_secondary_ops->init_domain_ssid != NULL)
305 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
306 else
307 ret2 = ACM_OK;
309 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
310 {
311 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
312 __func__, subj->domain_id);
313 acm_free_domain_ssid(ssid);
314 put_domain(subj);
315 return ACM_INIT_SSID_ERROR;
316 }
317 printk("%s: assigned domain %x the ssidref=%x.\n",
318 __func__, id, ssid->ssidref);
319 put_domain(subj);
320 return ACM_OK;
321 }
324 void
325 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
326 {
327 /* domain is already gone, just ssid is left */
328 if (ssid == NULL)
329 return;
331 ssid->subject = NULL;
332 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
333 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
334 ssid->primary_ssid = NULL;
335 if (acm_secondary_ops->free_domain_ssid != NULL)
336 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
337 ssid->secondary_ssid = NULL;
338 xfree(ssid);
339 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
340 __func__, id);
341 }
343 /*
344 * Local variables:
345 * mode: C
346 * c-set-style: "BSD"
347 * c-basic-offset: 4
348 * tab-width: 4
349 * indent-tabs-mode: nil
350 * End:
351 */