ia64/xen-unstable

view xen/acm/acm_core.c @ 12272:8f552314e45a

[LINUX] Use pfn_to_page instead of relying in memory assumptions

This makes usage agnostic wrt the memory model being used.

Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com>
author kfraser@localhost.localdomain
date Tue Nov 07 09:28:18 2006 +0000 (2006-11-07)
parents 8190a4a7ea4d
children 271ffb1c12eb
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 /* 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 ret = (ret + 7) & ~7;
104 if (buf_size < ret)
105 return -EINVAL;
107 memset(buf, 0, ret);
108 pr_buf->len = htonl(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
109 strcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
110 acm_bin_pol.policy_reference_name);
111 return ret;
112 }
114 int
115 acm_init_binary_policy(u32 policy_code)
116 {
117 int ret = ACM_OK;
119 acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
120 acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
122 write_lock(&acm_bin_pol_rwlock);
124 /* set primary policy component */
125 switch ((policy_code) & 0x0f)
126 {
128 case ACM_CHINESE_WALL_POLICY:
129 acm_init_chwall_policy();
130 acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
131 acm_primary_ops = &acm_chinesewall_ops;
132 break;
134 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
135 acm_init_ste_policy();
136 acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
137 acm_primary_ops = &acm_simple_type_enforcement_ops;
138 break;
140 case ACM_NULL_POLICY:
141 acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
142 acm_primary_ops = &acm_null_ops;
143 break;
145 default:
146 /* Unknown policy not allowed primary */
147 ret = -EINVAL;
148 goto out;
149 }
151 /* secondary policy component part */
152 switch ((policy_code) >> 4)
153 {
155 case ACM_NULL_POLICY:
156 acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
157 acm_secondary_ops = &acm_null_ops;
158 break;
160 case ACM_CHINESE_WALL_POLICY:
161 if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
162 { /* not a valid combination */
163 ret = -EINVAL;
164 goto out;
165 }
166 acm_init_chwall_policy();
167 acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
168 acm_secondary_ops = &acm_chinesewall_ops;
169 break;
171 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
172 if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
173 { /* not a valid combination */
174 ret = -EINVAL;
175 goto out;
176 }
177 acm_init_ste_policy();
178 acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
179 acm_secondary_ops = &acm_simple_type_enforcement_ops;
180 break;
182 default:
183 ret = -EINVAL;
184 goto out;
185 }
187 out:
188 write_unlock(&acm_bin_pol_rwlock);
189 return ret;
190 }
192 int
193 acm_is_policy(char *buf, unsigned long len)
194 {
195 struct acm_policy_buffer *pol;
197 if (buf == NULL || len < sizeof(struct acm_policy_buffer))
198 return 0;
200 pol = (struct acm_policy_buffer *)buf;
201 return ntohl(pol->magic) == ACM_MAGIC;
202 }
205 static int
206 acm_setup(char *policy_start,
207 unsigned long policy_len)
208 {
209 int rc = ACM_OK;
210 struct acm_policy_buffer *pol;
212 if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
213 return rc;
215 pol = (struct acm_policy_buffer *)policy_start;
216 if (ntohl(pol->magic) != ACM_MAGIC)
217 return rc;
219 rc = do_acm_set_policy((void *)policy_start, (u32)policy_len);
220 if (rc == ACM_OK)
221 {
222 printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
223 }
224 else
225 {
226 printk("Invalid policy.\n");
227 /* load default policy later */
228 acm_active_security_policy = ACM_POLICY_UNDEFINED;
229 }
230 return rc;
231 }
234 int
235 acm_init(char *policy_start,
236 unsigned long policy_len)
237 {
238 int ret = ACM_OK;
240 acm_set_endian();
242 /* first try to load the boot policy (uses its own locks) */
243 acm_setup(policy_start, policy_len);
245 if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
246 {
247 printk("%s: Enforcing %s boot policy.\n", __func__,
248 ACM_POLICY_NAME(acm_active_security_policy));
249 goto out;
250 }
251 /* else continue with the minimal hardcoded default startup policy */
252 printk("%s: Loading default policy (%s).\n",
253 __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
255 if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
256 ret = -EINVAL;
257 goto out;
258 }
259 acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
260 if (acm_active_security_policy != ACM_NULL_POLICY)
261 acm_bin_pol.policy_reference_name = "DEFAULT";
262 else
263 acm_bin_pol.policy_reference_name = "NULL";
265 out:
266 if (ret != ACM_OK)
267 {
268 printk("%s: Error initializing policies.\n", __func__);
269 /* here one could imagine a clean panic */
270 return -EINVAL;
271 }
272 return ret;
273 }
275 int
276 acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
277 {
278 struct acm_ssid_domain *ssid;
279 struct domain *subj = find_domain_by_id(id);
280 int ret1, ret2;
282 if (subj == NULL)
283 {
284 printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id);
285 return ACM_NULL_POINTER_ERROR;
286 }
287 if ((ssid = xmalloc(struct acm_ssid_domain)) == NULL)
288 {
289 put_domain(subj);
290 return ACM_INIT_SSID_ERROR;
291 }
293 ssid->datatype = ACM_DATATYPE_domain;
294 ssid->subject = subj;
295 ssid->domainid = subj->domain_id;
296 ssid->primary_ssid = NULL;
297 ssid->secondary_ssid = NULL;
299 if (acm_active_security_policy != ACM_NULL_POLICY)
300 ssid->ssidref = ssidref;
301 else
302 ssid->ssidref = ACM_DEFAULT_SSID;
304 subj->ssid = ssid;
305 /* now fill in primary and secondary parts; we only get here through hooks */
306 if (acm_primary_ops->init_domain_ssid != NULL)
307 ret1 = acm_primary_ops->init_domain_ssid(&(ssid->primary_ssid), ssidref);
308 else
309 ret1 = ACM_OK;
311 if (acm_secondary_ops->init_domain_ssid != NULL)
312 ret2 = acm_secondary_ops->init_domain_ssid(&(ssid->secondary_ssid), ssidref);
313 else
314 ret2 = ACM_OK;
316 if ((ret1 != ACM_OK) || (ret2 != ACM_OK))
317 {
318 printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n",
319 __func__, subj->domain_id);
320 acm_free_domain_ssid(ssid);
321 put_domain(subj);
322 return ACM_INIT_SSID_ERROR;
323 }
324 printkd("%s: assigned domain %x the ssidref=%x.\n",
325 __func__, id, ssid->ssidref);
326 put_domain(subj);
327 return ACM_OK;
328 }
331 void
332 acm_free_domain_ssid(struct acm_ssid_domain *ssid)
333 {
334 /* domain is already gone, just ssid is left */
335 if (ssid == NULL)
336 return;
338 ssid->subject = NULL;
339 if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */
340 acm_primary_ops->free_domain_ssid(ssid->primary_ssid);
341 ssid->primary_ssid = NULL;
342 if (acm_secondary_ops->free_domain_ssid != NULL)
343 acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid);
344 ssid->secondary_ssid = NULL;
345 xfree(ssid);
346 printkd("%s: Freed individual domain ssid (domain=%02x).\n",
347 __func__, id);
348 }
350 /*
351 * Local variables:
352 * mode: C
353 * c-set-style: "BSD"
354 * c-basic-offset: 4
355 * tab-width: 4
356 * indent-tabs-mode: nil
357 * End:
358 */