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 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 63 static ModuleTypeList *find_type(module_init_type type) 64 { 65 init_lists(); 66 67 return &init_type_list[type]; 68 } 69 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 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 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 123 void module_init_info(const QemuModinfo *info) 124 { 125 module_info = info; 126 } 127 128 void module_allow_arch(const char *arch) 129 { 130 module_arch = arch; 131 } 132 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 */ 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 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 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 354 void module_load_qom_all(void) 355 { 356 const QemuModinfo *modinfo; 357 Error *local_err = NULL; 358 359 if (module_loaded_qom_all) { 360 return; 361 } 362 363 for (modinfo = module_info; modinfo->name != NULL; modinfo++) { 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 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 399 void module_allow_arch(const char *arch) {} 400 void qemu_load_module_for_opts(const char *group) {} 401 int module_load(const char *prefix, const char *name, Error **errp) { return 2; } 402 int module_load_qom(const char *type, Error **errp) { return 2; } 403 void module_load_qom_all(void) {} 404 405 #endif 406