direct-io.hg

view xen/common/acm_ops.c @ 10057:0f16f0871dc9

[ACM] Replace the union structure parameter of the ACM hypercalls
with command-specific request structures. It aligns the ACM
hypercalls with the way parameters are passed in the event channel
hypercalls.

Advantages include backward-compatibility regarding old guests when
new calls are added and clarity of the code.

Signed-off by: Reiner Sailer <sailer@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sun May 21 19:05:31 2006 +0100 (2006-05-21)
parents 4e1b8be54311
children 96b1479305ce
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 <xen/guest_access.h>
29 #include <asm/shadow.h>
30 #include <public/sched_ctl.h>
31 #include <acm/acm_hooks.h>
33 #ifndef ACM_SECURITY
36 long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
37 {
38 return -ENOSYS;
39 }
42 #else
45 int acm_authorize_acm_ops(struct domain *d)
46 {
47 /* currently, policy management functions are restricted to privileged domains */
48 if (!IS_PRIV(d))
49 return -EPERM;
50 return 0;
51 }
54 long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
55 {
56 long rc = -EFAULT;
58 if (acm_authorize_acm_ops(current->domain))
59 return -EPERM;
61 switch ( cmd )
62 {
64 case ACMOP_setpolicy: {
65 struct acm_setpolicy setpolicy;
66 if (copy_from_guest(&setpolicy, arg, 1) != 0)
67 return -EFAULT;
68 if (setpolicy.interface_version != ACM_INTERFACE_VERSION)
69 return -EACCES;
71 rc = acm_set_policy(setpolicy.pushcache,
72 setpolicy.pushcache_size, 1);
73 break;
74 }
76 case ACMOP_getpolicy: {
77 struct acm_getpolicy getpolicy;
78 if (copy_from_guest(&getpolicy, arg, 1) != 0)
79 return -EFAULT;
80 if (getpolicy.interface_version != ACM_INTERFACE_VERSION)
81 return -EACCES;
83 rc = acm_get_policy(getpolicy.pullcache,
84 getpolicy.pullcache_size);
85 break;
86 }
88 case ACMOP_dumpstats: {
89 struct acm_dumpstats dumpstats;
90 if (copy_from_guest(&dumpstats, arg, 1) != 0)
91 return -EFAULT;
92 if (dumpstats.interface_version != ACM_INTERFACE_VERSION)
93 return -EACCES;
95 rc = acm_dump_statistics(dumpstats.pullcache,
96 dumpstats.pullcache_size);
97 break;
98 }
100 case ACMOP_getssid: {
101 struct acm_getssid getssid;
102 ssidref_t ssidref;
104 if (copy_from_guest(&getssid, arg, 1) != 0)
105 return -EFAULT;
106 if (getssid.interface_version != ACM_INTERFACE_VERSION)
107 return -EACCES;
109 if (getssid.get_ssid_by == SSIDREF)
110 ssidref = getssid.id.ssidref;
111 else if (getssid.get_ssid_by == DOMAINID)
112 {
113 struct domain *subj = find_domain_by_id(getssid.id.domainid);
114 if (!subj)
115 {
116 rc = -ESRCH; /* domain not found */
117 break;
118 }
119 if (subj->ssid == NULL)
120 {
121 put_domain(subj);
122 rc = -ESRCH;
123 break;
124 }
125 ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
126 put_domain(subj);
127 }
128 else
129 {
130 rc = -ESRCH;
131 break;
132 }
133 rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size);
134 break;
135 }
137 case ACMOP_getdecision: {
138 struct acm_getdecision getdecision;
139 ssidref_t ssidref1, ssidref2;
141 if (copy_from_guest(&getdecision, arg, 1) != 0)
142 return -EFAULT;
143 if (getdecision.interface_version != ACM_INTERFACE_VERSION)
144 return -EACCES;
146 if (getdecision.get_decision_by1 == SSIDREF)
147 ssidref1 = getdecision.id1.ssidref;
148 else if (getdecision.get_decision_by1 == DOMAINID)
149 {
150 struct domain *subj = find_domain_by_id(getdecision.id1.domainid);
151 if (!subj)
152 {
153 rc = -ESRCH; /* domain not found */
154 break;
155 }
156 if (subj->ssid == NULL)
157 {
158 put_domain(subj);
159 rc = -ESRCH;
160 break;
161 }
162 ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
163 put_domain(subj);
164 }
165 else
166 {
167 rc = -ESRCH;
168 break;
169 }
170 if (getdecision.get_decision_by2 == SSIDREF)
171 ssidref2 = getdecision.id2.ssidref;
172 else if (getdecision.get_decision_by2 == DOMAINID)
173 {
174 struct domain *subj = find_domain_by_id(getdecision.id2.domainid);
175 if (!subj)
176 {
177 rc = -ESRCH; /* domain not found */
178 break;;
179 }
180 if (subj->ssid == NULL)
181 {
182 put_domain(subj);
183 rc = -ESRCH;
184 break;
185 }
186 ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
187 put_domain(subj);
188 }
189 else
190 {
191 rc = -ESRCH;
192 break;
193 }
194 rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook);
196 if (rc == ACM_ACCESS_PERMITTED)
197 {
198 getdecision.acm_decision = ACM_ACCESS_PERMITTED;
199 rc = 0;
200 }
201 else if (rc == ACM_ACCESS_DENIED)
202 {
203 getdecision.acm_decision = ACM_ACCESS_DENIED;
204 rc = 0;
205 }
206 else
207 rc = -ESRCH;
209 if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) )
210 rc = -EFAULT;
211 break;
212 }
214 default:
215 rc = -ENOSYS;
216 break;
217 }
219 return rc;
220 }
222 #endif
224 /*
225 * Local variables:
226 * mode: C
227 * c-set-style: "BSD"
228 * c-basic-offset: 4
229 * tab-width: 4
230 * indent-tabs-mode: nil
231 * End:
232 */