0001
0002
0003
0004
0005 #ifndef _LINUX_RETHOOK_H
0006 #define _LINUX_RETHOOK_H
0007
0008 #include <linux/compiler.h>
0009 #include <linux/freelist.h>
0010 #include <linux/kallsyms.h>
0011 #include <linux/llist.h>
0012 #include <linux/rcupdate.h>
0013 #include <linux/refcount.h>
0014
0015 struct rethook_node;
0016
0017 typedef void (*rethook_handler_t) (struct rethook_node *, void *, struct pt_regs *);
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 struct rethook {
0031 void *data;
0032 rethook_handler_t handler;
0033 struct freelist_head pool;
0034 refcount_t ref;
0035 struct rcu_head rcu;
0036 };
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 struct rethook_node {
0051 union {
0052 struct freelist_node freelist;
0053 struct rcu_head rcu;
0054 };
0055 struct llist_node llist;
0056 struct rethook *rethook;
0057 unsigned long ret_addr;
0058 unsigned long frame;
0059 };
0060
0061 struct rethook *rethook_alloc(void *data, rethook_handler_t handler);
0062 void rethook_free(struct rethook *rh);
0063 void rethook_add_node(struct rethook *rh, struct rethook_node *node);
0064 struct rethook_node *rethook_try_get(struct rethook *rh);
0065 void rethook_recycle(struct rethook_node *node);
0066 void rethook_hook(struct rethook_node *node, struct pt_regs *regs, bool mcount);
0067 unsigned long rethook_find_ret_addr(struct task_struct *tsk, unsigned long frame,
0068 struct llist_node **cur);
0069
0070
0071 void arch_rethook_prepare(struct rethook_node *node, struct pt_regs *regs, bool mcount);
0072 void arch_rethook_trampoline(void);
0073
0074
0075
0076
0077
0078
0079
0080 static inline bool is_rethook_trampoline(unsigned long addr)
0081 {
0082 return addr == (unsigned long)dereference_symbol_descriptor(arch_rethook_trampoline);
0083 }
0084
0085
0086 void arch_rethook_fixup_return(struct pt_regs *regs,
0087 unsigned long correct_ret_addr);
0088
0089
0090 unsigned long rethook_trampoline_handler(struct pt_regs *regs,
0091 unsigned long frame);
0092
0093 #ifdef CONFIG_RETHOOK
0094 void rethook_flush_task(struct task_struct *tk);
0095 #else
0096 #define rethook_flush_task(tsk) do { } while (0)
0097 #endif
0098
0099 #endif
0100