~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/include/xsm/acm/acm_hooks.h

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************
 
2
 * acm_hooks.h 
 
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
 * acm header file implementing the global (policy-independent)
 
15
 *      sHype hooks that are called throughout Xen.
 
16
 * 
 
17
 */
 
18
 
 
19
#ifndef _ACM_HOOKS_H
 
20
#define _ACM_HOOKS_H
 
21
 
 
22
#include <xen/config.h>
 
23
#include <xen/errno.h>
 
24
#include <xen/types.h>
 
25
#include <xen/lib.h>
 
26
#include <xen/delay.h>
 
27
#include <xen/sched.h>
 
28
#include <xen/multiboot.h>
 
29
#include <public/xsm/acm.h>
 
30
#include <xsm/acm/acm_core.h>
 
31
#include <public/domctl.h>
 
32
#include <public/event_channel.h>
 
33
#include <asm/current.h>
 
34
 
 
35
/*
 
36
 * HOOK structure and meaning (justifies a few words about our model):
 
37
 * 
 
38
 * General idea: every policy-controlled system operation is reflected in a 
 
39
 *               transaction in the system's security state
 
40
 *
 
41
 *      Keeping the security state consistent requires "atomic" transactions.
 
42
 *      The name of the hooks to place around policy-controlled transactions
 
43
 *      reflects this. If authorizations do not involve security state changes,
 
44
 *      then and only then POST and FAIL hooks remain empty since we don't care
 
45
 *      about the eventual outcome of the operation from a security viewpoint.
 
46
 *
 
47
 *      PURPOSE of hook types:
 
48
 *      ======================
 
49
 *      PRE-Hooks
 
50
 *       a) general authorization to guard a controlled system operation
 
51
 *       b) prepare security state change
 
52
 *          (means: fail hook must be able to "undo" this)
 
53
 *
 
54
 *      POST-Hooks
 
55
 *       a) commit prepared state change
 
56
 *
 
57
 *      FAIL-Hooks
 
58
 *       a) roll-back prepared security state change from PRE-Hook
 
59
 *
 
60
 *
 
61
 *      PLACEMENT of hook types:
 
62
 *      ========================
 
63
 *      PRE-Hooks must be called before a guarded/controlled system operation
 
64
 *      is started. They return ACM_ACCESS_PERMITTED, ACM_ACCESS_DENIED or
 
65
 *      error. Operation must be aborted if return is not ACM_ACCESS_PERMITTED.
 
66
 *
 
67
 *      POST-Hooks must be called after a successful system operation.
 
68
 *      There is no return value: commit never fails.
 
69
 *
 
70
 *      FAIL-Hooks must be called:
 
71
 *       a) if system transaction (operation) fails after calling the PRE-hook
 
72
 *       b) if another (secondary) policy denies access in its PRE-Hook
 
73
 *          (policy layering is useful but requires additional handling)
 
74
 *
 
75
 * Hook model from a security transaction viewpoint:
 
76
 *   start-sys-ops--> prepare ----succeed-----> commit --> sys-ops success
 
77
 *                   (pre-hook)  \           (post-hook)
 
78
 *                                \
 
79
 *                               fail
 
80
 *                                   \
 
81
 *                                    \
 
82
 *                                  roll-back
 
83
 *                                 (fail-hook)
 
84
 *                                        \
 
85
 *                                       sys-ops error
 
86
 *
 
87
 */
 
88
 
 
89
struct acm_operations {
 
90
    /* policy management functions (must always be defined!) */
 
91
    int  (*init_domain_ssid)           (void **ssid, ssidref_t ssidref);
 
92
    void (*free_domain_ssid)           (void *ssid);
 
93
    int  (*dump_binary_policy)         (u8 *buffer, u32 buf_size);
 
94
    int  (*test_binary_policy)         (u8 *buffer, u32 buf_size,
 
95
                                        int is_bootpolicy,
 
96
                                        struct acm_sized_buffer *);
 
97
    int  (*set_binary_policy)          (u8 *buffer, u32 buf_size);
 
98
    int  (*dump_statistics)            (u8 *buffer, u16 buf_size);
 
99
    int  (*dump_ssid_types)            (ssidref_t ssidref, u8 *buffer, u16 buf_size);
 
100
    /* domain management control hooks (can be NULL) */
 
101
    int  (*domain_create)              (void *subject_ssid, ssidref_t ssidref,
 
102
                                        domid_t domid);
 
103
    void (*domain_destroy)             (void *object_ssid, struct domain *d);
 
104
    /* event channel control hooks  (can be NULL) */
 
105
    int  (*pre_eventchannel_unbound)      (domid_t id1, domid_t id2);
 
106
    void (*fail_eventchannel_unbound)     (domid_t id1, domid_t id2);
 
107
    int  (*pre_eventchannel_interdomain)  (domid_t id);
 
108
    void (*fail_eventchannel_interdomain) (domid_t id);
 
109
    /* grant table control hooks (can be NULL)  */
 
110
    int  (*pre_grant_map_ref)          (domid_t id);
 
111
    void (*fail_grant_map_ref)         (domid_t id);
 
112
    int  (*pre_grant_setup)            (domid_t id);
 
113
    void (*fail_grant_setup)           (domid_t id);
 
114
    /* generic domain-requested decision hooks (can be NULL) */
 
115
    int (*sharing)                     (ssidref_t ssidref1,
 
116
                                        ssidref_t ssidref2);
 
117
    int (*authorization)               (ssidref_t ssidref1,
 
118
                                        ssidref_t ssidref2);
 
119
    int (*conflictset)                 (ssidref_t ssidref1);
 
120
    /* determine whether the default policy is installed */
 
121
    int (*is_default_policy)           (void);
 
122
};
 
123
 
 
124
/* global variables */
 
125
extern struct acm_operations *acm_primary_ops;
 
126
extern struct acm_operations *acm_secondary_ops;
 
127
 
 
128
/* if ACM_TRACE_MODE defined, all hooks should
 
129
 * print a short trace message */
 
130
/* #define ACM_TRACE_MODE */
 
131
 
 
132
#ifdef ACM_TRACE_MODE
 
133
# define traceprintk(fmt, args...) printk(fmt, ## args)
 
134
#else
 
135
# define traceprintk(fmt, args...)
 
136
#endif
 
137
 
 
138
/* if ACM_DEBUG defined, all hooks should
 
139
 * print a short trace message (comment it out
 
140
 * when not in testing mode )
 
141
 */
 
142
/* #define ACM_DEBUG */
 
143
 
 
144
#ifdef ACM_DEBUG
 
145
#  define printkd(fmt, args...) printk(fmt, ## args)
 
146
#else
 
147
#  define printkd(fmt, args...)
 
148
#endif
 
149
 
 
150
#ifndef ACM_SECURITY
 
151
 
 
152
static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
 
153
{ return 0; }
 
154
static inline int acm_pre_eventchannel_interdomain(domid_t id)
 
155
{ return 0; }
 
156
static inline int acm_pre_grant_map_ref(domid_t id) 
 
157
{ return 0; }
 
158
static inline int acm_pre_grant_setup(domid_t id) 
 
159
{ return 0; }
 
160
static inline int acm_is_policy(char *buf, unsigned long len)
 
161
{ return 0; }
 
162
static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
 
163
{ return 0; }
 
164
static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
 
165
{ return 0; }
 
166
static inline int acm_conflictset(ssidref_t ssidref1)
 
167
{ return 0; }
 
168
static inline int acm_domain_create(struct domain *d, ssidref_t ssidref)
 
169
{ return 0; }
 
170
static inline void acm_domain_destroy(struct domain *d)
 
171
{ return; }
 
172
 
 
173
#define DOM0_SSIDREF 0x0
 
174
 
 
175
#else
 
176
 
 
177
static inline void acm_domain_ssid_onto_list(struct acm_ssid_domain *ssid)
 
178
{
 
179
    write_lock(&ssid_list_rwlock);
 
180
    list_add(&ssid->node, &ssid_list);
 
181
    write_unlock(&ssid_list_rwlock);
 
182
}
 
183
 
 
184
static inline void acm_domain_ssid_off_list(struct acm_ssid_domain *ssid)
 
185
{
 
186
    write_lock(&ssid_list_rwlock);
 
187
    list_del(&ssid->node);
 
188
    write_unlock(&ssid_list_rwlock);
 
189
}
 
190
 
 
191
static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
 
192
{
 
193
    if ((acm_primary_ops->pre_eventchannel_unbound != NULL) && 
 
194
        acm_primary_ops->pre_eventchannel_unbound(id1, id2))
 
195
        return ACM_ACCESS_DENIED;
 
196
    else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) && 
 
197
             acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) {
 
198
        /* roll-back primary */
 
199
        if (acm_primary_ops->fail_eventchannel_unbound != NULL)
 
200
            acm_primary_ops->fail_eventchannel_unbound(id1, id2);
 
201
        return ACM_ACCESS_DENIED;
 
202
    } else
 
203
        return ACM_ACCESS_PERMITTED;
 
204
}
 
205
 
 
206
static inline int acm_pre_eventchannel_interdomain(domid_t id)
 
207
{
 
208
    if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
 
209
        acm_primary_ops->pre_eventchannel_interdomain(id))
 
210
        return ACM_ACCESS_DENIED;
 
211
    else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
 
212
             acm_secondary_ops->pre_eventchannel_interdomain(id)) {
 
213
        /* roll-back primary */
 
214
        if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
 
215
            acm_primary_ops->fail_eventchannel_interdomain(id);
 
216
        return ACM_ACCESS_DENIED;
 
217
    } else
 
218
        return ACM_ACCESS_PERMITTED;
 
219
}
 
220
 
 
221
 
 
222
static inline int acm_pre_grant_map_ref(domid_t id)
 
223
{
 
224
    if ( (acm_primary_ops->pre_grant_map_ref != NULL) &&
 
225
         acm_primary_ops->pre_grant_map_ref(id) )
 
226
    {
 
227
        return ACM_ACCESS_DENIED;
 
228
    }
 
229
    else if ( (acm_secondary_ops->pre_grant_map_ref != NULL) &&
 
230
              acm_secondary_ops->pre_grant_map_ref(id) )
 
231
    {
 
232
        /* roll-back primary */
 
233
        if ( acm_primary_ops->fail_grant_map_ref != NULL )
 
234
            acm_primary_ops->fail_grant_map_ref(id);
 
235
        return ACM_ACCESS_DENIED;
 
236
    }
 
237
    else
 
238
    {
 
239
        return ACM_ACCESS_PERMITTED;
 
240
    }
 
241
}
 
242
 
 
243
static inline int acm_pre_grant_setup(domid_t id)
 
244
{
 
245
    if ( (acm_primary_ops->pre_grant_setup != NULL) &&
 
246
         acm_primary_ops->pre_grant_setup(id) )
 
247
    {
 
248
        return ACM_ACCESS_DENIED;
 
249
    }
 
250
    else if ( (acm_secondary_ops->pre_grant_setup != NULL) &&
 
251
              acm_secondary_ops->pre_grant_setup(id) )
 
252
    {
 
253
        /* roll-back primary */
 
254
        if (acm_primary_ops->fail_grant_setup != NULL)
 
255
            acm_primary_ops->fail_grant_setup(id);
 
256
        return ACM_ACCESS_DENIED;
 
257
    }
 
258
    else
 
259
    {
 
260
        return ACM_ACCESS_PERMITTED;
 
261
    }
 
262
}
 
263
 
 
264
 
 
265
static inline void acm_domain_destroy(struct domain *d)
 
266
{
 
267
    void *ssid = d->ssid;
 
268
    if (ssid != NULL) {
 
269
        if (acm_primary_ops->domain_destroy != NULL)
 
270
            acm_primary_ops->domain_destroy(ssid, d);
 
271
        if (acm_secondary_ops->domain_destroy != NULL)
 
272
            acm_secondary_ops->domain_destroy(ssid, d);
 
273
        /* free security ssid for the destroyed domain (also if null policy */
 
274
        acm_domain_ssid_off_list(ssid);
 
275
        acm_free_domain_ssid(d);
 
276
    }
 
277
}
 
278
 
 
279
 
 
280
static inline int acm_domain_create(struct domain *d, ssidref_t ssidref)
 
281
{
 
282
    void *subject_ssid = current->domain->ssid;
 
283
    domid_t domid = d->domain_id;
 
284
    int rc;
 
285
 
 
286
    read_lock(&acm_bin_pol_rwlock);
 
287
    /*
 
288
       To be called when a domain is created; returns '0' if the
 
289
       domain is allowed to be created, != '0' if not.
 
290
     */
 
291
    rc = acm_init_domain_ssid(d, ssidref);
 
292
    if (rc != ACM_OK)
 
293
        goto error_out;
 
294
 
 
295
    if ((acm_primary_ops->domain_create != NULL) &&
 
296
        acm_primary_ops->domain_create(subject_ssid, ssidref, domid)) {
 
297
        rc = ACM_ACCESS_DENIED;
 
298
    } else if ((acm_secondary_ops->domain_create != NULL) &&
 
299
                acm_secondary_ops->domain_create(subject_ssid, ssidref,
 
300
                                                 domid)) {
 
301
        /* roll-back primary */
 
302
        if (acm_primary_ops->domain_destroy != NULL)
 
303
            acm_primary_ops->domain_destroy(d->ssid, d);
 
304
        rc = ACM_ACCESS_DENIED;
 
305
    }
 
306
 
 
307
    if ( rc == ACM_OK )
 
308
    {
 
309
        acm_domain_ssid_onto_list(d->ssid);
 
310
    } else {
 
311
        acm_free_domain_ssid(d);
 
312
    }
 
313
 
 
314
error_out:
 
315
    read_unlock(&acm_bin_pol_rwlock);
 
316
    return rc;
 
317
}
 
318
 
 
319
 
 
320
static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
 
321
{
 
322
    if ((acm_primary_ops->sharing != NULL) &&
 
323
        acm_primary_ops->sharing(ssidref1, ssidref2))
 
324
        return ACM_ACCESS_DENIED;
 
325
    else if ((acm_secondary_ops->sharing != NULL) &&
 
326
             acm_secondary_ops->sharing(ssidref1, ssidref2)) {
 
327
        return ACM_ACCESS_DENIED;
 
328
    } else
 
329
        return ACM_ACCESS_PERMITTED;
 
330
}
 
331
 
 
332
 
 
333
static inline int acm_authorization(ssidref_t ssidref1, ssidref_t ssidref2)
 
334
{
 
335
    if ((acm_primary_ops->authorization != NULL) &&
 
336
        acm_primary_ops->authorization(ssidref1, ssidref2))
 
337
        return ACM_ACCESS_DENIED;
 
338
    else if ((acm_secondary_ops->authorization != NULL) &&
 
339
             acm_secondary_ops->authorization(ssidref1, ssidref2)) {
 
340
        return ACM_ACCESS_DENIED;
 
341
    } else
 
342
        return acm_sharing(ssidref1, ssidref2);
 
343
}
 
344
 
 
345
 
 
346
static inline int acm_conflictset(ssidref_t ssidref1)
 
347
{
 
348
    if ((acm_primary_ops->conflictset != NULL) &&
 
349
        acm_primary_ops->conflictset(ssidref1))
 
350
        return ACM_ACCESS_DENIED;
 
351
    else if ((acm_secondary_ops->conflictset != NULL) &&
 
352
             acm_secondary_ops->conflictset(ssidref1))
 
353
        return ACM_ACCESS_DENIED;
 
354
    return ACM_ACCESS_PERMITTED;
 
355
}
 
356
 
 
357
/* Return true iff buffer has an acm policy magic number.  */
 
358
extern int acm_is_policy(char *buf, unsigned long len);
 
359
 
 
360
#define DOM0_SSIDREF (dom0_ste_ssidref << 16 | dom0_chwall_ssidref)
 
361
 
 
362
#endif
 
363
 
 
364
#endif
 
365
 
 
366
/*
 
367
 * Local variables:
 
368
 * mode: C
 
369
 * c-set-style: "BSD"
 
370
 * c-basic-offset: 4
 
371
 * tab-width: 4
 
372
 * indent-tabs-mode: nil
 
373
 * End:
 
374
 */