direct-io.hg

view xen/acm/acm_core.c @ 7689:dd0e2e9fa4e6

Fixed domain refcounting bug (found by inspection)
author unknown@aosda.research.intel-research.net
date Tue Nov 08 11:36:37 2005 +0100 (2005-11-08)
parents 1e40bed176d4
children cc1d77bba4b0
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 ops structs called by the hooks */
53 struct acm_operations *acm_primary_ops = NULL;
54 /* called in hook if-and-only-if primary succeeds */
55 struct acm_operations *acm_secondary_ops = NULL;
57 /* acm global binary policy (points to 'local' primary and secondary policies */
58 struct acm_binary_policy acm_bin_pol;
59 /* acm binary policy lock */
60 rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
62 /* until we have endian support in Xen, we discover it at runtime */
63 u8 little_endian = 1;
64 void acm_set_endian(void)
65 {
66 u32 test = 1;
67 if (*((u8 *)&test) == 1)
68 {
69 printk("ACM module running in LITTLE ENDIAN.\n");
70 little_endian = 1;
71 }
72 else
73 {
74 printk("ACM module running in BIG ENDIAN.\n");
75 little_endian = 0;
76 }
77 }
79 /* initialize global security policy for Xen; policy write-locked already */
80 static void
81 acm_init_binary_policy(void *primary, void *secondary)
82 {
83 acm_bin_pol.primary_policy_code = 0;
84 acm_bin_pol.secondary_policy_code = 0;
85 acm_bin_pol.primary_binary_policy = primary;
86 acm_bin_pol.secondary_binary_policy = secondary;
87 }
89 static int
90 acm_setup(unsigned int *initrdidx,
91 const multiboot_info_t *mbi,
92 unsigned long initial_images_start)
93 {
94 int i;
95 module_t *mod = (module_t *)__va(mbi->mods_addr);
96 int rc = ACM_OK;
98 if (mbi->mods_count > 1)
99 *initrdidx = 1;
101 /*
102 * Try all modules and see whichever could be the binary policy.
103 * Adjust the initrdidx if module[1] is the binary policy.
104 */
105 for (i = mbi->mods_count-1; i >= 1; i--)
106 {
107 struct acm_policy_buffer *pol;
108 char *_policy_start;
109 unsigned long _policy_len;
110 #if defined(__i386__)
111 _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
112 #elif defined(__x86_64__)
113 _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
114 #else
115 #error Architecture unsupported by sHype
116 #endif
117 _policy_len = mod[i].mod_end - mod[i].mod_start;
118 if (_policy_len < sizeof(struct acm_policy_buffer))
119 continue; /* not a policy */
121 pol = (struct acm_policy_buffer *)_policy_start;
122 if (ntohl(pol->magic) == ACM_MAGIC)
123 {
124 rc = acm_set_policy((void *)_policy_start,
125 (u32)_policy_len,
126 0);
127 if (rc == ACM_OK)
128 {
129 printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
130 if (i == 1)
131 {
132 if (mbi->mods_count > 2)
133 {
134 *initrdidx = 2;
135 }
136 else {
137 *initrdidx = 0;
138 }
139 }
140 else
141 {
142 *initrdidx = 1;
143 }
144 break;
145 }
146 else
147 {
148 printk("Invalid policy. %d.th module line.\n", i+1);
149 }
150 } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
151 }
152 return rc;
153 }
156 int
157 acm_init(unsigned int *initrdidx,
158 const multiboot_info_t *mbi,
159 unsigned long initial_images_start)
160 {
161 int ret = ACM_OK;
163 acm_set_endian();
164 write_lock(&acm_bin_pol_rwlock);
165 acm_init_binary_policy(NULL, NULL);
167 /* set primary policy component */
168 switch ((ACM_USE_SECURITY_POLICY) & 0x0f)
169 {
171 case ACM_CHINESE_WALL_POLICY:
172 acm_init_chwall_policy();
173 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
174 acm_primary_ops = &acm_chinesewall_ops;
175 break;
177 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
178 acm_init_ste_policy();
179 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
180 acm_primary_ops = &acm_simple_type_enforcement_ops;
181 break;
183 default:
184 /* NULL or Unknown policy not allowed primary;
185 * NULL/NULL will not compile this code */
186 ret = -EINVAL;
187 goto out;
188 }
190 /* secondary policy component part */
191 switch ((ACM_USE_SECURITY_POLICY) >> 4) {
192 case ACM_NULL_POLICY:
193 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
194 acm_secondary_ops = &acm_null_ops;
195 break;
197 case ACM_CHINESE_WALL_POLICY:
198 if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
199 { /* not a valid combination */
200 ret = -EINVAL;
201 goto out;
202 }
203 acm_init_chwall_policy();
204 acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
205 acm_secondary_ops = &acm_chinesewall_ops;
206 break;
208 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
209 if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
210 { /* not a valid combination */
211 ret = -EINVAL;
212 goto out;
213 }
214 acm_init_ste_policy();
215 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
216 acm_secondary_ops = &acm_simple_type_enforcement_ops;
217 break;
219 default:
220 ret = -EINVAL;
221 goto out;
222 }
224 out:
225 write_unlock(&acm_bin_pol_rwlock);
227 if (ret != ACM_OK)
228 {
229 printk("%s: Error initializing policies.\n", __func__);
230 /* here one could imagine a clean panic */
231 return -EINVAL;
232 }
233 if (acm_setup(initrdidx, mbi, initial_images_start) != ACM_OK)
234 {
235 printk("%s: Error loading policy at boot time.\n", __func__);
236 /* ignore, just continue with the minimal hardcoded startup policy */
237 }
238 printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__,
239 ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
240 ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
241 return ret;
242 }
244 int
245 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
246 {
247 struct acm_ssid_domain *ssid;
248 struct domain *subj = find_domain_by_id(id);
249 int ret1, ret2;
251 if (subj == NULL)
252 {
253 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
254 return ACM_NULL_POINTER_ERROR;
255 }
256 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
257 {
258 put_domain(subj);
259 return ACM_INIT_SSID_ERROR;
260 }
262 ssid->datatype = DOMAIN;
263 ssid->subject = subj;
264 ssid->domainid = subj->domain_id;
265 ssid->primary_ssid = NULL;
266 ssid->secondary_ssid = NULL;
268 if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
269 ssid->ssidref = ssidref;
270 else
271 ssid->ssidref = ACM_DEFAULT_SSID;
273 subj->ssid = ssid;
274 /* now fill in primary and secondary parts; we only get here through hooks */
275 if (acm_primary_ops->init_domain_ssid != NULL)
276 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
277 else
278 ret1 = ACM_OK;
280 if (acm_secondary_ops->init_domain_ssid != NULL)
281 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
282 else
283 ret2 = ACM_OK;
285 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
286 {
287 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
288 __func__, subj->domain_id);
289 acm_free_domain_ssid(ssid);
290 put_domain(subj);
291 return ACM_INIT_SSID_ERROR;
292 }
293 printk("%s: assigned domain %x the ssidref=%x.\n",
294 __func__, id, ssid->ssidref);
295 put_domain(subj);
296 return ACM_OK;
297 }
300 void
301 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
302 {
303 /* domain is already gone, just ssid is left */
304 if (ssid == NULL)
305 return;
307 ssid->subject = NULL;
308 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
309 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
310 ssid->primary_ssid = NULL;
311 if (acm_secondary_ops->free_domain_ssid != NULL)
312 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
313 ssid->secondary_ssid = NULL;
314 xfree(ssid);
315 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
316 __func__, id);
317 }
319 /*
320 * Local variables:
321 * mode: C
322 * c-set-style: "BSD"
323 * c-basic-offset: 4
324 * tab-width: 4
325 * indent-tabs-mode: nil
326 * End:
327 */