1 /*
2  *  This work is based on the LSM implementation in Linux 2.6.13.4.
3  *
4  *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
5  *
6  *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2,
10  *  as published by the Free Software Foundation.
11  */
12 
13 #include <xen/init.h>
14 #include <xen/errno.h>
15 #include <xen/lib.h>
16 #include <xen/param.h>
17 
18 #include <xen/hypercall.h>
19 #include <xsm/xsm.h>
20 
21 #ifdef CONFIG_XSM
22 
23 #ifdef CONFIG_MULTIBOOT
24 #include <asm/setup.h>
25 #endif
26 
27 #ifdef CONFIG_HAS_DEVICE_TREE
28 #include <asm/setup.h>
29 #endif
30 
31 #define XSM_FRAMEWORK_VERSION    "1.0.0"
32 
33 struct xsm_operations *xsm_ops;
34 
35 enum xsm_bootparam {
36     XSM_BOOTPARAM_DUMMY,
37     XSM_BOOTPARAM_FLASK,
38     XSM_BOOTPARAM_SILO,
39 };
40 
41 static enum xsm_bootparam __initdata xsm_bootparam =
42 #ifdef CONFIG_XSM_FLASK_DEFAULT
43     XSM_BOOTPARAM_FLASK;
44 #elif CONFIG_XSM_SILO_DEFAULT
45     XSM_BOOTPARAM_SILO;
46 #else
47     XSM_BOOTPARAM_DUMMY;
48 #endif
49 
parse_xsm_param(const char * s)50 static int __init parse_xsm_param(const char *s)
51 {
52     int rc = 0;
53 
54     if ( !strcmp(s, "dummy") )
55         xsm_bootparam = XSM_BOOTPARAM_DUMMY;
56 #ifdef CONFIG_XSM_FLASK
57     else if ( !strcmp(s, "flask") )
58         xsm_bootparam = XSM_BOOTPARAM_FLASK;
59 #endif
60 #ifdef CONFIG_XSM_SILO
61     else if ( !strcmp(s, "silo") )
62         xsm_bootparam = XSM_BOOTPARAM_SILO;
63 #endif
64     else
65         rc = -EINVAL;
66 
67     return rc;
68 }
69 custom_param("xsm", parse_xsm_param);
70 
verify(struct xsm_operations * ops)71 static inline int verify(struct xsm_operations *ops)
72 {
73     /* verify the security_operations structure exists */
74     if ( !ops )
75         return -EINVAL;
76     xsm_fixup_ops(ops);
77     return 0;
78 }
79 
xsm_core_init(const void * policy_buffer,size_t policy_size)80 static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
81 {
82 #ifdef CONFIG_XSM_FLASK_POLICY
83     if ( policy_size == 0 )
84     {
85         policy_buffer = xsm_flask_init_policy;
86         policy_size = xsm_flask_init_policy_size;
87     }
88 #endif
89 
90     if ( verify(&dummy_xsm_ops) )
91     {
92         printk(XENLOG_ERR "Could not verify dummy_xsm_ops structure\n");
93         return -EIO;
94     }
95 
96     xsm_ops = &dummy_xsm_ops;
97 
98     switch ( xsm_bootparam )
99     {
100     case XSM_BOOTPARAM_DUMMY:
101         break;
102 
103     case XSM_BOOTPARAM_FLASK:
104         flask_init(policy_buffer, policy_size);
105         break;
106 
107     case XSM_BOOTPARAM_SILO:
108         silo_init();
109         break;
110 
111     default:
112         ASSERT_UNREACHABLE();
113         break;
114     }
115 
116     return 0;
117 }
118 
119 #ifdef CONFIG_MULTIBOOT
xsm_multiboot_init(unsigned long * module_map,const multiboot_info_t * mbi)120 int __init xsm_multiboot_init(unsigned long *module_map,
121                               const multiboot_info_t *mbi)
122 {
123     int ret = 0;
124     void *policy_buffer = NULL;
125     size_t policy_size = 0;
126 
127     printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
128 
129     if ( XSM_MAGIC )
130     {
131         ret = xsm_multiboot_policy_init(module_map, mbi,
132                                         &policy_buffer, &policy_size);
133         if ( ret )
134         {
135             bootstrap_map(NULL);
136             printk(XENLOG_ERR "Error %d initializing XSM policy\n", ret);
137             return -EINVAL;
138         }
139     }
140 
141     ret = xsm_core_init(policy_buffer, policy_size);
142     bootstrap_map(NULL);
143 
144     return 0;
145 }
146 #endif
147 
148 #ifdef CONFIG_HAS_DEVICE_TREE
xsm_dt_init(void)149 int __init xsm_dt_init(void)
150 {
151     int ret = 0;
152     void *policy_buffer = NULL;
153     size_t policy_size = 0;
154 
155     printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
156 
157     if ( XSM_MAGIC )
158     {
159         ret = xsm_dt_policy_init(&policy_buffer, &policy_size);
160         if ( ret )
161         {
162             printk(XENLOG_ERR "Error %d initializing XSM policy\n", ret);
163             return -EINVAL;
164         }
165     }
166 
167     ret = xsm_core_init(policy_buffer, policy_size);
168 
169     xfree(policy_buffer);
170 
171     return ret ?: (xsm_bootparam == XSM_BOOTPARAM_SILO);
172 }
173 
174 /**
175  * has_xsm_magic - Check XSM Magic of the module header by phy address
176  * A XSM module has a special header
177  * ------------------------------------------------
178  * uint magic | uint target_len | uchar target[8] |
179  * 0xf97cff8c |        8        |    "XenFlask"   |
180  * ------------------------------------------------
181  * 0xf97cff8c is policy magic number (XSM_MAGIC).
182  * Here we only check the "magic" of the module.
183  */
has_xsm_magic(paddr_t start)184 bool __init has_xsm_magic(paddr_t start)
185 {
186     xsm_magic_t magic;
187 
188     if ( XSM_MAGIC )
189     {
190         copy_from_paddr(&magic, start, sizeof(magic) );
191         return ( magic == XSM_MAGIC );
192     }
193 
194     return false;
195 }
196 #endif
197 
register_xsm(struct xsm_operations * ops)198 int __init register_xsm(struct xsm_operations *ops)
199 {
200     if ( verify(ops) )
201     {
202         printk(XENLOG_ERR "Could not verify xsm_operations structure\n");
203         return -EINVAL;
204     }
205 
206     if ( xsm_ops != &dummy_xsm_ops )
207         return -EAGAIN;
208 
209     xsm_ops = ops;
210 
211     return 0;
212 }
213 
214 #endif
215 
do_xsm_op(XEN_GUEST_HANDLE_PARAM (xsm_op_t)op)216 long do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
217 {
218     return xsm_do_xsm_op(op);
219 }
220 
221 #ifdef CONFIG_COMPAT
compat_xsm_op(XEN_GUEST_HANDLE_PARAM (xsm_op_t)op)222 int compat_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
223 {
224     return xsm_do_compat_op(op);
225 }
226 #endif
227