|
@@ -1391,21 +1391,19 @@ bool within_kprobe_blacklist(unsigned long addr)
|
|
|
* This returns encoded errors if it fails to look up symbol or invalid
|
|
|
* combination of parameters.
|
|
|
*/
|
|
|
-static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
|
|
|
+static kprobe_opcode_t *_kprobe_addr(kprobe_opcode_t *addr,
|
|
|
+ const char *symbol_name, unsigned int offset)
|
|
|
{
|
|
|
- kprobe_opcode_t *addr = p->addr;
|
|
|
-
|
|
|
- if ((p->symbol_name && p->addr) ||
|
|
|
- (!p->symbol_name && !p->addr))
|
|
|
+ if ((symbol_name && addr) || (!symbol_name && !addr))
|
|
|
goto invalid;
|
|
|
|
|
|
- if (p->symbol_name) {
|
|
|
- kprobe_lookup_name(p->symbol_name, addr);
|
|
|
+ if (symbol_name) {
|
|
|
+ kprobe_lookup_name(symbol_name, addr);
|
|
|
if (!addr)
|
|
|
return ERR_PTR(-ENOENT);
|
|
|
}
|
|
|
|
|
|
- addr = (kprobe_opcode_t *)(((char *)addr) + p->offset);
|
|
|
+ addr = (kprobe_opcode_t *)(((char *)addr) + offset);
|
|
|
if (addr)
|
|
|
return addr;
|
|
|
|
|
@@ -1413,6 +1411,11 @@ invalid:
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
}
|
|
|
|
|
|
+static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
|
|
|
+{
|
|
|
+ return _kprobe_addr(p->addr, p->symbol_name, p->offset);
|
|
|
+}
|
|
|
+
|
|
|
/* Check passed kprobe is valid and return kprobe in kprobe_table. */
|
|
|
static struct kprobe *__get_valid_kprobe(struct kprobe *p)
|
|
|
{
|
|
@@ -1881,19 +1884,28 @@ bool __weak arch_function_offset_within_entry(unsigned long offset)
|
|
|
return !offset;
|
|
|
}
|
|
|
|
|
|
+bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset)
|
|
|
+{
|
|
|
+ kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset);
|
|
|
+
|
|
|
+ if (IS_ERR(kp_addr))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) ||
|
|
|
+ !arch_function_offset_within_entry(offset))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
int register_kretprobe(struct kretprobe *rp)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
struct kretprobe_instance *inst;
|
|
|
int i;
|
|
|
void *addr;
|
|
|
- unsigned long offset;
|
|
|
-
|
|
|
- addr = kprobe_addr(&rp->kp);
|
|
|
- if (!kallsyms_lookup_size_offset((unsigned long)addr, NULL, &offset))
|
|
|
- return -EINVAL;
|
|
|
|
|
|
- if (!arch_function_offset_within_entry(offset))
|
|
|
+ if (!function_offset_within_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
|
|
|
return -EINVAL;
|
|
|
|
|
|
if (kretprobe_blacklist_size) {
|