source: trunk/packages/xen-3.1/xen-3.1/xen/common/acm_ops.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 6.6 KB
Line 
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
17#include <xen/config.h>
18#include <xen/types.h>
19#include <xen/lib.h>
20#include <xen/mm.h>
21#include <public/acm.h>
22#include <public/acm_ops.h>
23#include <xen/sched.h>
24#include <xen/event.h>
25#include <xen/trace.h>
26#include <xen/console.h>
27#include <xen/guest_access.h>
28#include <acm/acm_hooks.h>
29
30#ifndef ACM_SECURITY
31
32long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
33{
34    return -ENOSYS;
35}
36
37#else
38
39int acm_authorize_acm_ops(struct domain *d)
40{
41    return (IS_PRIV(d) ? 0 : -EPERM);
42}
43
44long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
45{
46    long rc = -EFAULT;
47
48    if ( acm_authorize_acm_ops(current->domain) )
49        return -EPERM;
50
51    switch ( cmd )
52    {
53
54    case ACMOP_setpolicy: {
55        struct acm_setpolicy setpolicy;
56        if (copy_from_guest(&setpolicy, arg, 1) != 0)
57            return -EFAULT;
58        if (setpolicy.interface_version != ACM_INTERFACE_VERSION)
59            return -EACCES;
60
61        rc = acm_set_policy(setpolicy.pushcache,
62                            setpolicy.pushcache_size);
63        break;
64    }
65
66    case ACMOP_getpolicy: {
67        struct acm_getpolicy getpolicy;
68        if (copy_from_guest(&getpolicy, arg, 1) != 0)
69            return -EFAULT;
70        if (getpolicy.interface_version != ACM_INTERFACE_VERSION)
71            return -EACCES;
72
73        rc = acm_get_policy(getpolicy.pullcache,
74                            getpolicy.pullcache_size);
75        break;
76    }
77
78    case ACMOP_dumpstats: {
79        struct acm_dumpstats dumpstats;
80        if (copy_from_guest(&dumpstats, arg, 1) != 0)
81            return -EFAULT;
82        if (dumpstats.interface_version != ACM_INTERFACE_VERSION)
83            return -EACCES;
84
85        rc = acm_dump_statistics(dumpstats.pullcache,
86                                 dumpstats.pullcache_size);
87        break;
88    }
89
90    case ACMOP_getssid: {
91        struct acm_getssid getssid;
92        ssidref_t ssidref;
93
94        if (copy_from_guest(&getssid, arg, 1) != 0)
95            return -EFAULT;
96        if (getssid.interface_version != ACM_INTERFACE_VERSION)
97            return -EACCES;
98
99        if (getssid.get_ssid_by == ACM_GETBY_ssidref)
100            ssidref = getssid.id.ssidref;
101        else if (getssid.get_ssid_by == ACM_GETBY_domainid)
102        {
103            struct domain *subj = rcu_lock_domain_by_id(getssid.id.domainid);
104            if (!subj)
105            {
106                rc = -ESRCH; /* domain not found */
107                break;
108            }
109            if (subj->ssid == NULL)
110            {
111                rcu_unlock_domain(subj);
112                rc = -ESRCH;
113                break;
114            }
115            ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
116            rcu_unlock_domain(subj);
117        }
118        else
119        {
120            rc = -ESRCH;
121            break;
122        }
123        rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size);
124        break;
125    }
126
127    case ACMOP_getdecision: {
128        struct acm_getdecision getdecision;
129        ssidref_t ssidref1, ssidref2;
130
131        if (copy_from_guest(&getdecision, arg, 1) != 0)
132            return -EFAULT;
133        if (getdecision.interface_version != ACM_INTERFACE_VERSION)
134            return -EACCES;
135
136        if (getdecision.get_decision_by1 == ACM_GETBY_ssidref)
137            ssidref1 = getdecision.id1.ssidref;
138        else if (getdecision.get_decision_by1 == ACM_GETBY_domainid)
139        {
140            struct domain *subj = rcu_lock_domain_by_id(getdecision.id1.domainid);
141            if (!subj)
142            {
143                rc = -ESRCH; /* domain not found */
144                break;
145            }
146            if (subj->ssid == NULL)
147            {
148                rcu_unlock_domain(subj);
149                rc = -ESRCH;
150                break;
151            }
152            ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
153            rcu_unlock_domain(subj);
154        }
155        else
156        {
157            rc = -ESRCH;
158            break;
159        }
160        if (getdecision.get_decision_by2 == ACM_GETBY_ssidref)
161            ssidref2 = getdecision.id2.ssidref;
162        else if (getdecision.get_decision_by2 == ACM_GETBY_domainid)
163        {
164            struct domain *subj = rcu_lock_domain_by_id(getdecision.id2.domainid);
165            if (!subj)
166            {
167                rc = -ESRCH; /* domain not found */
168                break;;
169            }
170            if (subj->ssid == NULL)
171            {
172                rcu_unlock_domain(subj);
173                rc = -ESRCH;
174                break;
175            }
176            ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
177            rcu_unlock_domain(subj);
178        }
179        else
180        {
181            rc = -ESRCH;
182            break;
183        }
184        rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook);
185
186        if (rc == ACM_ACCESS_PERMITTED)
187        {
188            getdecision.acm_decision = ACM_ACCESS_PERMITTED;
189            rc = 0;
190        }
191        else if  (rc == ACM_ACCESS_DENIED)
192        {
193            getdecision.acm_decision = ACM_ACCESS_DENIED;
194            rc = 0;
195        }
196        else
197            rc = -ESRCH;
198
199        if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) )
200            rc = -EFAULT;
201        break;
202    }
203
204    case ACMOP_chgpolicy: {
205        struct acm_change_policy chgpolicy;
206
207        if (copy_from_guest(&chgpolicy, arg, 1) != 0)
208            return -EFAULT;
209        if (chgpolicy.interface_version != ACM_INTERFACE_VERSION)
210            return -EACCES;
211
212        rc = acm_change_policy(&chgpolicy);
213
214        if (rc == 0)
215            if (copy_to_guest(arg, &chgpolicy, 1) != 0)
216                rc = -EFAULT;
217        break;
218    }
219
220    case ACMOP_relabeldoms: {
221        struct acm_relabel_doms relabeldoms;
222
223        if (copy_from_guest(&relabeldoms, arg, 1) != 0)
224            return -EFAULT;
225        if (relabeldoms.interface_version != ACM_INTERFACE_VERSION)
226            return -EACCES;
227
228        rc = acm_relabel_domains(&relabeldoms);
229
230        if (rc == 0)
231            if (copy_to_guest(arg, &relabeldoms, 1) != 0)
232                rc = -EFAULT;
233        break;
234    }
235
236    default:
237        rc = -ENOSYS;
238        break;
239    }
240
241    return rc;
242}
243
244#endif /* defined(ACM_SECURITY) */
245
246/*
247 * Local variables:
248 * mode: C
249 * c-set-style: "BSD"
250 * c-basic-offset: 4
251 * tab-width: 4
252 * indent-tabs-mode: nil
253 * End:
254 */
Note: See TracBrowser for help on using the repository browser.