direct-io.hg

view xen/acm/acm_core.c @ 14149:8e3899a4f62d

Added SXP pretty-printer.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Tue Feb 27 13:58:40 2007 +0000 (2007-02-27)
parents 699656fb1d0b
children 09a9b6d6c356
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 DEFINE_RWLOCK(acm_bin_pol_rwlock);
65 int
66 acm_set_policy_reference(u8 *buf, u32 buf_size)
67 {
68 struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf;
69 acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, be32_to_cpu(pr->len));
71 if (!acm_bin_pol.policy_reference_name)
72 return -ENOMEM;
74 strlcpy(acm_bin_pol.policy_reference_name,
75 (char *)(buf + sizeof(struct acm_policy_reference_buffer)),
76 be32_to_cpu(pr->len));
77 printk("%s: Activating policy %s\n", __func__,
78 acm_bin_pol.policy_reference_name);
79 return 0;
80 }
82 int
83 acm_dump_policy_reference(u8 *buf, u32 buf_size)
84 {
85 struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
86 int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
88 ret = (ret + 7) & ~7;
89 if (buf_size < ret)
90 return -EINVAL;
92 memset(buf, 0, ret);
93 pr_buf->len = cpu_to_be32(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
94 strlcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
95 acm_bin_pol.policy_reference_name,
96 be32_to_cpu(pr_buf->len));
97 return ret;
98 }
100 int
101 acm_init_binary_policy(u32 policy_code)
102 {
103 int ret = ACM_OK;
105 acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
106 acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
108 write_lock(&acm_bin_pol_rwlock);
110 /* set primary policy component */
111 switch ((policy_code) & 0x0f)
112 {
114 case ACM_CHINESE_WALL_POLICY:
115 acm_init_chwall_policy();
116 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
117 acm_primary_ops = &acm_chinesewall_ops;
118 break;
120 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
121 acm_init_ste_policy();
122 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
123 acm_primary_ops = &acm_simple_type_enforcement_ops;
124 break;
126 case ACM_NULL_POLICY:
127 acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
128 acm_primary_ops = &acm_null_ops;
129 break;
131 default:
132 /* Unknown policy not allowed primary */
133 ret = -EINVAL;
134 goto out;
135 }
137 /* secondary policy component part */
138 switch ((policy_code) >> 4)
139 {
141 case ACM_NULL_POLICY:
142 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
143 acm_secondary_ops = &acm_null_ops;
144 break;
146 case ACM_CHINESE_WALL_POLICY:
147 if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
148 { /* not a valid combination */
149 ret = -EINVAL;
150 goto out;
151 }
152 acm_init_chwall_policy();
153 acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
154 acm_secondary_ops = &acm_chinesewall_ops;
155 break;
157 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
158 if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
159 { /* not a valid combination */
160 ret = -EINVAL;
161 goto out;
162 }
163 acm_init_ste_policy();
164 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
165 acm_secondary_ops = &acm_simple_type_enforcement_ops;
166 break;
168 default:
169 ret = -EINVAL;
170 goto out;
171 }
173 out:
174 write_unlock(&acm_bin_pol_rwlock);
175 return ret;
176 }
178 int
179 acm_is_policy(char *buf, unsigned long len)
180 {
181 struct acm_policy_buffer *pol;
183 if (buf == NULL || len < sizeof(struct acm_policy_buffer))
184 return 0;
186 pol = (struct acm_policy_buffer *)buf;
187 return be32_to_cpu(pol->magic) == ACM_MAGIC;
188 }
191 static int
192 acm_setup(char *policy_start,
193 unsigned long policy_len)
194 {
195 int rc = ACM_OK;
196 struct acm_policy_buffer *pol;
198 if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
199 return rc;
201 pol = (struct acm_policy_buffer *)policy_start;
202 if (be32_to_cpu(pol->magic) != ACM_MAGIC)
203 return rc;
205 rc = do_acm_set_policy((void *)policy_start, (u32)policy_len);
206 if (rc == ACM_OK)
207 {
208 printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
209 }
210 else
211 {
212 printk("Invalid policy.\n");
213 /* load default policy later */
214 acm_active_security_policy = ACM_POLICY_UNDEFINED;
215 }
216 return rc;
217 }
220 int
221 acm_init(char *policy_start,
222 unsigned long policy_len)
223 {
224 int ret = ACM_OK;
226 /* first try to load the boot policy (uses its own locks) */
227 acm_setup(policy_start, policy_len);
229 if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
230 {
231 printk("%s: Enforcing %s boot policy.\n", __func__,
232 ACM_POLICY_NAME(acm_active_security_policy));
233 goto out;
234 }
235 /* else continue with the minimal hardcoded default startup policy */
236 printk("%s: Loading default policy (%s).\n",
237 __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
239 if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
240 ret = -EINVAL;
241 goto out;
242 }
243 acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
244 if (acm_active_security_policy != ACM_NULL_POLICY)
245 acm_bin_pol.policy_reference_name = "DEFAULT";
246 else
247 acm_bin_pol.policy_reference_name = "NULL";
249 out:
250 if (ret != ACM_OK)
251 {
252 printk("%s: Error initializing policies.\n", __func__);
253 /* here one could imagine a clean panic */
254 return -EINVAL;
255 }
256 return ret;
257 }
259 int
260 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
261 {
262 struct acm_ssid_domain *ssid;
263 struct domain *subj = get_domain_by_id(id);
264 int ret1, ret2;
266 if (subj == NULL)
267 {
268 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
269 return ACM_NULL_POINTER_ERROR;
270 }
271 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
272 {
273 put_domain(subj);
274 return ACM_INIT_SSID_ERROR;
275 }
277 ssid->datatype = ACM_DATATYPE_domain;
278 ssid->subject = subj;
279 ssid->domainid = subj->domain_id;
280 ssid->primary_ssid = NULL;
281 ssid->secondary_ssid = NULL;
283 if (acm_active_security_policy != ACM_NULL_POLICY)
284 ssid->ssidref = ssidref;
285 else
286 ssid->ssidref = ACM_DEFAULT_SSID;
288 subj->ssid = ssid;
289 /* now fill in primary and secondary parts; we only get here through hooks */
290 if (acm_primary_ops->init_domain_ssid != NULL)
291 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
292 else
293 ret1 = ACM_OK;
295 if (acm_secondary_ops->init_domain_ssid != NULL)
296 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
297 else
298 ret2 = ACM_OK;
300 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
301 {
302 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
303 __func__, subj->domain_id);
304 acm_free_domain_ssid(ssid);
305 put_domain(subj);
306 return ACM_INIT_SSID_ERROR;
307 }
308 printkd("%s: assigned domain %x the ssidref=%x.\n",
309 __func__, id, ssid->ssidref);
310 put_domain(subj);
311 return ACM_OK;
312 }
315 void
316 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
317 {
318 /* domain is already gone, just ssid is left */
319 if (ssid == NULL)
320 return;
322 ssid->subject = NULL;
323 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
324 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
325 ssid->primary_ssid = NULL;
326 if (acm_secondary_ops->free_domain_ssid != NULL)
327 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
328 ssid->secondary_ssid = NULL;
329 xfree(ssid);
330 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
331 __func__, id);
332 }
334 /*
335 * Local variables:
336 * mode: C
337 * c-set-style: "BSD"
338 * c-basic-offset: 4
339 * tab-width: 4
340 * indent-tabs-mode: nil
341 * End:
342 */