ia64/xen-unstable

view xen/common/acm_ops.c @ 8609:85d693e6f61a

Arch-specific per-vcpu info should be initialised to zero
when allocating a new vcpu structure, not copied from
CPU0's idle VCPU. Especially now that the idle VCPU itself
is dynamically allocated.

This should fix assertions people have been seeing in
getdomain_info_ctxt() relation to IOPL in eflags.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Jan 14 21:26:40 2006 +0100 (2006-01-14)
parents a8ac8be1a889
children 4293d6760cef
line source
1 /******************************************************************************
2 * acm_ops.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * Process acm command requests from guest OS.
15 *
16 */
18 #include <xen/config.h>
19 #include <xen/types.h>
20 #include <xen/lib.h>
21 #include <xen/mm.h>
22 #include <public/acm.h>
23 #include <public/acm_ops.h>
24 #include <xen/sched.h>
25 #include <xen/event.h>
26 #include <xen/trace.h>
27 #include <xen/console.h>
28 #include <asm/shadow.h>
29 #include <public/sched_ctl.h>
30 #include <acm/acm_hooks.h>
32 #ifndef ACM_SECURITY
34 long do_acm_op(struct acm_op * u_acm_op)
35 {
36 return -ENOSYS;
37 }
39 #else
41 enum acm_operation {
42 POLICY, /* access to policy interface (early drop) */
43 GETPOLICY, /* dump policy cache */
44 SETPOLICY, /* set policy cache (controls security) */
45 DUMPSTATS, /* dump policy statistics */
46 GETSSID, /* retrieve ssidref for domain id (decide inside authorized domains) */
47 GETDECISION /* retrieve ACM decision from authorized domains */
48 };
50 int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops)
51 {
52 /* currently, policy management functions are restricted to privileged domains */
53 if (!IS_PRIV(d))
54 return -EPERM;
56 return 0;
57 }
59 long do_acm_op(struct acm_op * u_acm_op)
60 {
61 long ret = 0;
62 struct acm_op curop, *op = &curop;
64 if (acm_authorize_acm_ops(current->domain, POLICY))
65 return -EPERM;
67 if (copy_from_user(op, u_acm_op, sizeof(*op)))
68 return -EFAULT;
70 if (op->interface_version != ACM_INTERFACE_VERSION)
71 return -EACCES;
73 switch (op->cmd)
74 {
75 case ACM_SETPOLICY:
76 {
77 ret = acm_authorize_acm_ops(current->domain, SETPOLICY);
78 if (!ret)
79 ret = acm_set_policy(op->u.setpolicy.pushcache,
80 op->u.setpolicy.pushcache_size, 1);
81 }
82 break;
84 case ACM_GETPOLICY:
85 {
86 ret = acm_authorize_acm_ops(current->domain, GETPOLICY);
87 if (!ret)
88 ret = acm_get_policy(op->u.getpolicy.pullcache,
89 op->u.getpolicy.pullcache_size);
90 if (!ret)
91 copy_to_user(u_acm_op, op, sizeof(*op));
92 }
93 break;
95 case ACM_DUMPSTATS:
96 {
97 ret = acm_authorize_acm_ops(current->domain, DUMPSTATS);
98 if (!ret)
99 ret = acm_dump_statistics(op->u.dumpstats.pullcache,
100 op->u.dumpstats.pullcache_size);
101 if (!ret)
102 copy_to_user(u_acm_op, op, sizeof(*op));
103 }
104 break;
106 case ACM_GETSSID:
107 {
108 ssidref_t ssidref;
110 ret = acm_authorize_acm_ops(current->domain, GETSSID);
111 if (ret)
112 break;
114 if (op->u.getssid.get_ssid_by == SSIDREF)
115 ssidref = op->u.getssid.id.ssidref;
116 else if (op->u.getssid.get_ssid_by == DOMAINID)
117 {
118 struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid);
119 if (!subj)
120 {
121 ret = -ESRCH; /* domain not found */
122 break;
123 }
124 if (subj->ssid == NULL)
125 {
126 put_domain(subj);
127 ret = -ESRCH;
128 break;
129 }
130 ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
131 put_domain(subj);
132 }
133 else
134 {
135 ret = -ESRCH;
136 break;
137 }
138 ret = acm_get_ssid(ssidref,
139 op->u.getssid.ssidbuf,
140 op->u.getssid.ssidbuf_size);
141 if (!ret)
142 copy_to_user(u_acm_op, op, sizeof(*op));
143 }
144 break;
146 case ACM_GETDECISION:
147 {
148 ssidref_t ssidref1, ssidref2;
150 ret = acm_authorize_acm_ops(current->domain, GETDECISION);
151 if (ret)
152 break;
154 if (op->u.getdecision.get_decision_by1 == SSIDREF)
155 ssidref1 = op->u.getdecision.id1.ssidref;
156 else if (op->u.getdecision.get_decision_by1 == DOMAINID)
157 {
158 struct domain *subj = find_domain_by_id(op->u.getdecision.id1.domainid);
159 if (!subj)
160 {
161 ret = -ESRCH; /* domain not found */
162 break;
163 }
164 if (subj->ssid == NULL)
165 {
166 put_domain(subj);
167 ret = -ESRCH;
168 break;
169 }
170 ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
171 put_domain(subj);
172 }
173 else
174 {
175 ret = -ESRCH;
176 break;
177 }
178 if (op->u.getdecision.get_decision_by2 == SSIDREF)
179 ssidref2 = op->u.getdecision.id2.ssidref;
180 else if (op->u.getdecision.get_decision_by2 == DOMAINID)
181 {
182 struct domain *subj = find_domain_by_id(op->u.getdecision.id2.domainid);
183 if (!subj)
184 {
185 ret = -ESRCH; /* domain not found */
186 break;;
187 }
188 if (subj->ssid == NULL)
189 {
190 put_domain(subj);
191 ret = -ESRCH;
192 break;
193 }
194 ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
195 put_domain(subj);
196 }
197 else
198 {
199 ret = -ESRCH;
200 break;
201 }
202 ret = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
204 if (ret == ACM_ACCESS_PERMITTED)
205 {
206 op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
207 ret = 0;
208 }
209 else if (ret == ACM_ACCESS_DENIED)
210 {
211 op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
212 ret = 0;
213 }
214 else
215 ret = -ESRCH;
217 if (!ret)
218 copy_to_user(u_acm_op, op, sizeof(*op));
219 }
220 break;
222 default:
223 ret = -ESRCH;
224 }
226 return ret;
227 }
229 #endif
231 /*
232 * Local variables:
233 * mode: C
234 * c-set-style: "BSD"
235 * c-basic-offset: 4
236 * tab-width: 4
237 * indent-tabs-mode: nil
238 * End:
239 */