diff options
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2161f519d481..993b84cc1db5 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -1921,28 +1921,48 @@ bool __weak arch_kprobe_on_func_entry(unsigned long offset) | |||
1921 | return !offset; | 1921 | return !offset; |
1922 | } | 1922 | } |
1923 | 1923 | ||
1924 | bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) | 1924 | /** |
1925 | * kprobe_on_func_entry() -- check whether given address is function entry | ||
1926 | * @addr: Target address | ||
1927 | * @sym: Target symbol name | ||
1928 | * @offset: The offset from the symbol or the address | ||
1929 | * | ||
1930 | * This checks whether the given @addr+@offset or @sym+@offset is on the | ||
1931 | * function entry address or not. | ||
1932 | * This returns 0 if it is the function entry, or -EINVAL if it is not. | ||
1933 | * And also it returns -ENOENT if it fails the symbol or address lookup. | ||
1934 | * Caller must pass @addr or @sym (either one must be NULL), or this | ||
1935 | * returns -EINVAL. | ||
1936 | */ | ||
1937 | int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) | ||
1925 | { | 1938 | { |
1926 | kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); | 1939 | kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); |
1927 | 1940 | ||
1928 | if (IS_ERR(kp_addr)) | 1941 | if (IS_ERR(kp_addr)) |
1929 | return false; | 1942 | return PTR_ERR(kp_addr); |
1930 | 1943 | ||
1931 | if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) || | 1944 | if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset)) |
1932 | !arch_kprobe_on_func_entry(offset)) | 1945 | return -ENOENT; |
1933 | return false; | ||
1934 | 1946 | ||
1935 | return true; | 1947 | if (!arch_kprobe_on_func_entry(offset)) |
1948 | return -EINVAL; | ||
1949 | |||
1950 | return 0; | ||
1936 | } | 1951 | } |
1937 | 1952 | ||
1938 | int register_kretprobe(struct kretprobe *rp) | 1953 | int register_kretprobe(struct kretprobe *rp) |
1939 | { | 1954 | { |
1940 | int ret = 0; | 1955 | int ret; |
1941 | struct kretprobe_instance *inst; | 1956 | struct kretprobe_instance *inst; |
1942 | int i; | 1957 | int i; |
1943 | void *addr; | 1958 | void *addr; |
1944 | 1959 | ||
1945 | if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset)) | 1960 | ret = kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset); |
1961 | if (ret) | ||
1962 | return ret; | ||
1963 | |||
1964 | /* If only rp->kp.addr is specified, check reregistering kprobes */ | ||
1965 | if (rp->kp.addr && check_kprobe_rereg(&rp->kp)) | ||
1946 | return -EINVAL; | 1966 | return -EINVAL; |
1947 | 1967 | ||
1948 | if (kretprobe_blacklist_size) { | 1968 | if (kretprobe_blacklist_size) { |
@@ -1956,6 +1976,9 @@ int register_kretprobe(struct kretprobe *rp) | |||
1956 | } | 1976 | } |
1957 | } | 1977 | } |
1958 | 1978 | ||
1979 | if (rp->data_size > KRETPROBE_MAX_DATA_SIZE) | ||
1980 | return -E2BIG; | ||
1981 | |||
1959 | rp->kp.pre_handler = pre_handler_kretprobe; | 1982 | rp->kp.pre_handler = pre_handler_kretprobe; |
1960 | rp->kp.post_handler = NULL; | 1983 | rp->kp.post_handler = NULL; |
1961 | rp->kp.fault_handler = NULL; | 1984 | rp->kp.fault_handler = NULL; |