1 /*
2 * QEMU Module Infrastructure
3 *
4 * Copyright IBM, Corp. 2009
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
14 */
15
16 #include "qemu/osdep.h"
17 #ifdef CONFIG_MODULES
18 #include <gmodule.h>
19 #endif
20 #include "qemu/queue.h"
21 #include "qemu/module.h"
22 #include "qemu/cutils.h"
23 #include "qemu/config-file.h"
24 #include "qapi/error.h"
25 #ifdef CONFIG_MODULE_UPGRADES
26 #include "qemu-version.h"
27 #endif
28 #include "trace.h"
29
30 typedef struct ModuleEntry
31 {
32 void (*init)(void);
33 QTAILQ_ENTRY(ModuleEntry) node;
34 module_init_type type;
35 } ModuleEntry;
36
37 typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
38
39 static ModuleTypeList init_type_list[MODULE_INIT_MAX];
40 static bool modules_init_done[MODULE_INIT_MAX];
41
42 static ModuleTypeList dso_init_list;
43
init_lists(void)44 static void init_lists(void)
45 {
46 static int inited;
47 int i;
48
49 if (inited) {
50 return;
51 }
52
53 for (i = 0; i < MODULE_INIT_MAX; i++) {
54 QTAILQ_INIT(&init_type_list[i]);
55 }
56
57 QTAILQ_INIT(&dso_init_list);
58
59 inited = 1;
60 }
61
62
find_type(module_init_type type)63 static ModuleTypeList *find_type(module_init_type type)
64 {
65 init_lists();
66
67 return &init_type_list[type];
68 }
69
register_module_init(void (* fn)(void),module_init_type type)70 void register_module_init(void (*fn)(void), module_init_type type)
71 {
72 ModuleEntry *e;
73 ModuleTypeList *l;
74
75 e = g_malloc0(sizeof(*e));
76 e->init = fn;
77 e->type = type;
78
79 l = find_type(type);
80
81 QTAILQ_INSERT_TAIL(l, e, node);
82 }
83
register_dso_module_init(void (* fn)(void),module_init_type type)84 void register_dso_module_init(void (*fn)(void), module_init_type type)
85 {
86 ModuleEntry *e;
87
88 init_lists();
89
90 e = g_malloc0(sizeof(*e));
91 e->init = fn;
92 e->type = type;
93
94 QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
95 }
96
module_call_init(module_init_type type)97 void module_call_init(module_init_type type)
98 {
99 ModuleTypeList *l;
100 ModuleEntry *e;
101
102 if (modules_init_done[type]) {
103 return;
104 }
105
106 l = find_type(type);
107
108 QTAILQ_FOREACH(e, l, node) {
109 e->init();
110 }
111
112 modules_init_done[type] = true;
113 }
114
115 #ifdef CONFIG_MODULES
116
117 static const QemuModinfo module_info_stub[] = { {
118 /* end of list */
119 } };
120 static const QemuModinfo *module_info = module_info_stub;
121 static const char *module_arch;
122
module_init_info(const QemuModinfo * info)123 void module_init_info(const QemuModinfo *info)
124 {
125 module_info = info;
126 }
127
module_allow_arch(const char * arch)128 void module_allow_arch(const char *arch)
129 {
130 module_arch = arch;
131 }
132
module_check_arch(const QemuModinfo * modinfo)133 static bool module_check_arch(const QemuModinfo *modinfo)
134 {
135 if (modinfo->arch) {
136 if (!module_arch) {
137 /* no arch set -> ignore all */
138 return false;
139 }
140 if (strcmp(module_arch, modinfo->arch) != 0) {
141 /* mismatch */
142 return false;
143 }
144 }
145 return true;
146 }
147
148 /*
149 * module_load_dso: attempt to load an existing dso file
150 *
151 * fname: full pathname of the file to load
152 * export_symbols: if true, add the symbols to the global name space
153 * errp: error to set.
154 *
155 * Return value: true on success, false on error, and errp will be set.
156 */
module_load_dso(const char * fname,bool export_symbols,Error ** errp)157 static bool module_load_dso(const char *fname, bool export_symbols,
158 Error **errp)
159 {
160 GModule *g_module;
161 void (*sym)(void);
162 ModuleEntry *e, *next;
163 int flags;
164
165 assert(QTAILQ_EMPTY(&dso_init_list));
166
167 flags = 0;
168 if (!export_symbols) {
169 flags |= G_MODULE_BIND_LOCAL;
170 }
171 g_module = g_module_open(fname, flags);
172 if (!g_module) {
173 error_setg(errp, "failed to open module: %s", g_module_error());
174 return false;
175 }
176 if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) {
177 error_setg(errp, "failed to initialize module: %s", fname);
178 /*
179 * Print some info if this is a QEMU module (but from different build),
180 * this will make debugging user problems easier.
181 */
182 if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) {
183 error_append_hint(errp,
184 "Only modules from the same build can be loaded.\n");
185 }
186 g_module_close(g_module);
187 return false;
188 }
189
190 QTAILQ_FOREACH(e, &dso_init_list, node) {
191 e->init();
192 register_module_init(e->init, e->type);
193 }
194 trace_module_load_module(fname);
195 QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) {
196 QTAILQ_REMOVE(&dso_init_list, e, node);
197 g_free(e);
198 }
199 return true;
200 }
201
module_load(const char * prefix,const char * name,Error ** errp)202 int module_load(const char *prefix, const char *name, Error **errp)
203 {
204 int rv = -1;
205 #ifdef CONFIG_MODULE_UPGRADES
206 char *version_dir;
207 #endif
208 const char *search_dir;
209 char *dirs[5];
210 char *module_name;
211 int i = 0, n_dirs = 0;
212 bool export_symbols = false;
213 static GHashTable *loaded_modules;
214 const QemuModinfo *modinfo;
215 const char **sl;
216
217 if (!g_module_supported()) {
218 error_setg(errp, "%s", "this platform does not support GLib modules");
219 return -1;
220 }
221
222 if (!loaded_modules) {
223 loaded_modules = g_hash_table_new(g_str_hash, g_str_equal);
224 }
225
226 /* allocate all resources managed by the out: label here */
227 module_name = g_strdup_printf("%s%s", prefix, name);
228
229 if (g_hash_table_contains(loaded_modules, module_name)) {
230 g_free(module_name);
231 return 2; /* module already loaded */
232 }
233 g_hash_table_add(loaded_modules, module_name);
234
235 search_dir = getenv("QEMU_MODULE_DIR");
236 if (search_dir != NULL) {
237 dirs[n_dirs++] = g_strdup_printf("%s", search_dir);
238 }
239 dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR);
240
241 #ifdef CONFIG_MODULE_UPGRADES
242 version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION),
243 G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~",
244 '_');
245 dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir);
246 #endif
247 assert(n_dirs <= ARRAY_SIZE(dirs));
248
249 /* end of resources managed by the out: label */
250
251 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
252 if (modinfo->arch) {
253 if (strcmp(modinfo->name, module_name) == 0) {
254 if (!module_check_arch(modinfo)) {
255 error_setg(errp, "module arch does not match: "
256 "expected '%s', got '%s'", module_arch, modinfo->arch);
257 goto out;
258 }
259 }
260 }
261 if (modinfo->deps) {
262 if (strcmp(modinfo->name, module_name) == 0) {
263 /* we depend on other module(s) */
264 for (sl = modinfo->deps; *sl != NULL; sl++) {
265 int subrv = module_load("", *sl, errp);
266 if (subrv <= 0) {
267 rv = subrv;
268 goto out;
269 }
270 }
271 } else {
272 for (sl = modinfo->deps; *sl != NULL; sl++) {
273 if (strcmp(module_name, *sl) == 0) {
274 /* another module depends on us */
275 export_symbols = true;
276 }
277 }
278 }
279 }
280 }
281
282 for (i = 0; i < n_dirs; i++) {
283 char *fname = g_strdup_printf("%s/%s%s",
284 dirs[i], module_name, CONFIG_HOST_DSOSUF);
285 int ret = access(fname, F_OK);
286 if (ret != 0 && (errno == ENOENT || errno == ENOTDIR)) {
287 /*
288 * if we don't find the module in this dir, try the next one.
289 * If we don't find it in any dir, that can be fine too: user
290 * did not install the module. We will return 0 in this case
291 * with no error set.
292 */
293 g_free(fname);
294 continue;
295 } else if (ret != 0) {
296 /* most common is EACCES here */
297 error_setg_errno(errp, errno, "error trying to access %s", fname);
298 } else if (module_load_dso(fname, export_symbols, errp)) {
299 rv = 1; /* module successfully loaded */
300 }
301 g_free(fname);
302 goto out;
303 }
304 rv = 0; /* module not found */
305
306 out:
307 if (rv <= 0) {
308 g_hash_table_remove(loaded_modules, module_name);
309 g_free(module_name);
310 }
311 for (i = 0; i < n_dirs; i++) {
312 g_free(dirs[i]);
313 }
314 return rv;
315 }
316
317 static bool module_loaded_qom_all;
318
module_load_qom(const char * type,Error ** errp)319 int module_load_qom(const char *type, Error **errp)
320 {
321 const QemuModinfo *modinfo;
322 const char **sl;
323 int rv = 0;
324
325 if (!type) {
326 error_setg(errp, "%s", "type is NULL");
327 return -1;
328 }
329
330 trace_module_lookup_object_type(type);
331 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
332 if (!modinfo->objs) {
333 continue;
334 }
335 if (!module_check_arch(modinfo)) {
336 continue;
337 }
338 for (sl = modinfo->objs; *sl != NULL; sl++) {
339 if (strcmp(type, *sl) == 0) {
340 if (rv > 0) {
341 error_setg(errp, "multiple modules providing '%s'", type);
342 return -1;
343 }
344 rv = module_load("", modinfo->name, errp);
345 if (rv < 0) {
346 return rv;
347 }
348 }
349 }
350 }
351 return rv;
352 }
353
module_load_qom_all(void)354 void module_load_qom_all(void)
355 {
356 const QemuModinfo *modinfo;
357
358 if (module_loaded_qom_all) {
359 return;
360 }
361
362 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
363 Error *local_err = NULL;
364 if (!modinfo->objs) {
365 continue;
366 }
367 if (!module_check_arch(modinfo)) {
368 continue;
369 }
370 if (module_load("", modinfo->name, &local_err) < 0) {
371 error_report_err(local_err);
372 }
373 }
374 module_loaded_qom_all = true;
375 }
376
qemu_load_module_for_opts(const char * group)377 void qemu_load_module_for_opts(const char *group)
378 {
379 const QemuModinfo *modinfo;
380 const char **sl;
381
382 for (modinfo = module_info; modinfo->name != NULL; modinfo++) {
383 if (!modinfo->opts) {
384 continue;
385 }
386 for (sl = modinfo->opts; *sl != NULL; sl++) {
387 if (strcmp(group, *sl) == 0) {
388 Error *local_err = NULL;
389 if (module_load("", modinfo->name, &local_err) < 0) {
390 error_report_err(local_err);
391 }
392 }
393 }
394 }
395 }
396
397 #else
398
module_allow_arch(const char * arch)399 void module_allow_arch(const char *arch) {}
qemu_load_module_for_opts(const char * group)400 void qemu_load_module_for_opts(const char *group) {}
module_load(const char * prefix,const char * name,Error ** errp)401 int module_load(const char *prefix, const char *name, Error **errp) { return 2; }
module_load_qom(const char * type,Error ** errp)402 int module_load_qom(const char *type, Error **errp) { return 2; }
module_load_qom_all(void)403 void module_load_qom_all(void) {}
404
405 #endif
406