Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Return hooking with list-based shadow stack.
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  * struct rethook - The rethook management data structure.
0021  * @data: The user-defined data storage.
0022  * @handler: The user-defined return hook handler.
0023  * @pool: The pool of struct rethook_node.
0024  * @ref: The reference counter.
0025  * @rcu: The rcu_head for deferred freeing.
0026  *
0027  * Don't embed to another data structure, because this is a self-destructive
0028  * data structure when all rethook_node are freed.
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  * struct rethook_node - The rethook shadow-stack entry node.
0040  * @freelist: The freelist, linked to struct rethook::pool.
0041  * @rcu: The rcu_head for deferred freeing.
0042  * @llist: The llist, linked to a struct task_struct::rethooks.
0043  * @rethook: The pointer to the struct rethook.
0044  * @ret_addr: The storage for the real return address.
0045  * @frame: The storage for the frame pointer.
0046  *
0047  * You can embed this to your extended data structure to store any data
0048  * on each entry of the shadow stack.
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 /* Arch dependent code must implement arch_* and trampoline code */
0071 void arch_rethook_prepare(struct rethook_node *node, struct pt_regs *regs, bool mcount);
0072 void arch_rethook_trampoline(void);
0073 
0074 /**
0075  * is_rethook_trampoline() - Check whether the address is rethook trampoline
0076  * @addr: The address to be checked
0077  *
0078  * Return true if the @addr is the rethook trampoline address.
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 /* If the architecture needs to fixup the return address, implement it. */
0086 void arch_rethook_fixup_return(struct pt_regs *regs,
0087                    unsigned long correct_ret_addr);
0088 
0089 /* Generic trampoline handler, arch code must prepare asm stub */
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