/* ====================================================================== */ int kedr_init_module_ms_alloc(void) { int ret = kallsyms_on_each_symbol(symbol_walk_callback, NULL); if (ret) return ret; if (module_alloc_func == NULL) { pr_warning(KEDR_MSG_PREFIX "Unable to find \"module_alloc\" function\n"); return -EFAULT; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) if (module_memfree_func == NULL) { pr_warning(KEDR_MSG_PREFIX "Unable to find \"module_memfree\" function.\n"); return -EFAULT; } #else if (module_free_func == NULL) { pr_warning(KEDR_MSG_PREFIX "Unable to find \"module_free\" function.\n"); return -EFAULT; } #endif return 0; /* success */ }
static int find_syscalls(void) { int rc; ugidctl_sys_setuid = NULL; ugidctl_sys_setgid = NULL; ugidctl_sys_setgroups = NULL; rc = kallsyms_on_each_symbol(symbol_walk_callback, NULL); if (rc) return rc; if (ugidctl_sys_setuid == NULL) { printk(KERN_ERR "%s: unable to find sys_setuid()\n", MOD_NAME); return -EFAULT; } if (ugidctl_sys_setgid == NULL) { printk(KERN_ERR "%s: unable to find sys_setgid()\n", MOD_NAME); return -EFAULT; } if (ugidctl_sys_setgroups == NULL) { printk(KERN_ERR "%s: unable to find sys_setgroups()\n", MOD_NAME); return -EFAULT; } return 0; }
static int stapkp_init(struct stap_kprobe_probe *probes, size_t nprobes) { size_t i; #ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL // If we have any symbol_name+offset probes, we need to try to // convert those into address-based probes. size_t probe_max = 0; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; if (! skp->symbol_name) continue; ++probe_max; } if (probe_max > 0) { // Here we're going to try to convert any symbol_name+offset // probes into address probes. struct stapkp_symbol_data sd; dbug_stapkp("looking up %lu probes\n", probe_max); sd.probes = probes; sd.nprobes = nprobes; sd.probe_max = probe_max; sd.modname = NULL; preempt_disable(); kallsyms_on_each_symbol(stapkp_symbol_callback, &sd); preempt_enable(); dbug_stapkp("found %lu probes\n", sd.probe_max); } #endif for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; int rc = 0; rc = stapkp_register_probe(skp); if (rc == 1) // failed to relocate addr? continue; // don't fuss about it, module probably not loaded // NB: We keep going even if a probe failed to register (PR6749). We only // warn about it if it wasn't optional and isn't in a module. if (rc && !skp->optional_p && ((skp->module == NULL) || skp->module[0] == '\0' || strcmp(skp->module, "kernel") == 0)) { if (skp->symbol_name) _stp_warn("probe %s (%s+%u) registration error (rc %d)", skp->probe->pp, skp->symbol_name, skp->offset, rc); else _stp_warn("probe %s (address 0x%lx) registration error (rc %d)", skp->probe->pp, stapkp_relocate_addr(skp), rc); } } return 0; }
static int cmd_profile_dump(struct vmm_chardev * cdev, char *filter_mode) { int index = 0; int (*cmp_function) (void *, size_t, size_t) = cmd_profile_count_cmp; if (filter_mode != NULL) { cmp_function = NULL; while (filters[index].name) { if (strcmp(filter_mode, filters[index].name) == 0) { cmp_function = filters[index].function; break; } index++; } } if (cmp_function == NULL) { cmd_profile_usage(cdev); return VMM_EFAIL; } kallsyms_on_each_symbol(cmd_profile_count_iterator, count_array); libsort_smoothsort(count_array, 0, kallsyms_num_syms, cmp_function, cmd_profile_swap); for (index = 0; index < kallsyms_num_syms; index++) { if (count_array[index].count) { vmm_printf("%-30s %-10u %-10u %u\n", count_array[index].function_name, count_array[index].count, ns_to_micros(count_array[index].total_time), ns_to_micros(count_array[index].time_per_call)); } } return VMM_OK; }
/* stapkp_refresh is called for two reasons: either a kprobe needs to be * enabled/disabled (modname is NULL), or a module has been loaded/unloaded and * kprobes need to be registered/unregistered (modname is !NULL). */ static void stapkp_refresh(const char *modname, struct stap_kprobe_probe *probes, size_t nprobes) { size_t i; dbug_stapkp("refresh %lu probes with module %s\n", nprobes, modname ?: "?"); #ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL if (modname) { size_t probe_max = 0; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; // If this probe is in the same module that is being // loaded/unloaded and the probe is symbol_name+offset based // and it isn't registered (so the module must be loaded), // try to convert all probes in the same module to // address-based probes. if (skp->module && strcmp(modname, skp->module) == 0 && skp->symbol_name && skp->registered_p == 0) ++probe_max; } if (probe_max > 0) { struct stapkp_symbol_data sd; sd.probes = probes; sd.nprobes = nprobes; sd.probe_max = probe_max; sd.modname = modname; preempt_disable(); kallsyms_on_each_symbol(stapkp_symbol_callback, &sd); preempt_enable(); } } #endif for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; // was this probe's target module loaded/unloaded if (modname && skp->module && strcmp(modname, skp->module) == 0) { int rc; unsigned long addr = (! skp->symbol_name ? stapkp_relocate_addr(skp) : 0); // module being loaded? if (skp->registered_p == 0 && (addr != 0 || skp->symbol_name)) stapkp_register_probe(skp); // module/section being unloaded? else if (skp->registered_p == 1 && addr == 0) stapkp_unregister_probe(skp); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) else if (stapkp_should_enable_probe(skp) || stapkp_should_disable_probe(skp)) { stapkp_refresh_probe(skp); } #endif } }
static int klp_find_object_symbol(const char *objname, const char *name, unsigned long sympos, unsigned long *addr) { struct klp_find_arg args = { .objname = objname, .name = name, .addr = 0, .count = 0, .pos = sympos, }; mutex_lock(&module_mutex); if (objname) module_kallsyms_on_each_symbol(klp_find_callback, &args); else kallsyms_on_each_symbol(klp_find_callback, &args); mutex_unlock(&module_mutex); /* * Ensure an address was found. If sympos is 0, ensure symbol is unique; * otherwise ensure the symbol position count matches sympos. */ if (args.addr == 0) pr_err("symbol '%s' not found in symbol table\n", name); else if (args.count > 1 && sympos == 0) { pr_err("unresolvable ambiguity for symbol '%s' in object '%s'\n", name, objname); } else if (sympos != args.count && sympos > 0) { pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n", sympos, name, objname ? objname : "vmlinux"); } else { *addr = args.addr; return 0; } *addr = 0; return -EINVAL; } static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod) { int i, cnt, vmlinux, ret; char objname[MODULE_NAME_LEN]; char symname[KSYM_NAME_LEN]; char *strtab = pmod->core_kallsyms.strtab; Elf_Rela *relas; Elf_Sym *sym; unsigned long sympos, addr; /* * Since the field widths for objname and symname in the sscanf() * call are hard-coded and correspond to MODULE_NAME_LEN and * KSYM_NAME_LEN respectively, we must make sure that MODULE_NAME_LEN * and KSYM_NAME_LEN have the values we expect them to have. * * Because the value of MODULE_NAME_LEN can differ among architectures, * we use the smallest/strictest upper bound possible (56, based on * the current definition of MODULE_NAME_LEN) to prevent overflows. */ BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128); relas = (Elf_Rela *) relasec->sh_addr; /* For each rela in this klp relocation section */ for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) { sym = pmod->core_kallsyms.symtab + ELF_R_SYM(relas[i].r_info); if (sym->st_shndx != SHN_LIVEPATCH) { pr_err("symbol %s is not marked as a livepatch symbol\n", strtab + sym->st_name); return -EINVAL; } /* Format: .klp.sym.objname.symname,sympos */ cnt = sscanf(strtab + sym->st_name, ".klp.sym.%55[^.].%127[^,],%lu", objname, symname, &sympos); if (cnt != 3) { pr_err("symbol %s has an incorrectly formatted name\n", strtab + sym->st_name); return -EINVAL; } /* klp_find_object_symbol() treats a NULL objname as vmlinux */ vmlinux = !strcmp(objname, "vmlinux"); ret = klp_find_object_symbol(vmlinux ? NULL : objname, symname, sympos, &addr); if (ret) return ret; sym->st_value = addr; } return 0; }