未验证 提交 a5a6aebf 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!250 add UPROBE_ALTER_PC flag for uprobe mechanism

Merge Pull Request from: @anatas 
 
[Description]
We try to implement a live-patch mechanism in the userspace based on the UPROBE.
In the handler, we may change the PC register.
In this case, UPROBE must skip the handle of the next instruction.

[Testing]
kernel options:
UPROBES_SUPPORT_PC_ALTER=y

 
 
Link:https://gitee.com/openeuler/kernel/pulls/250 
Reviewed-by: Xu Kuohai <xukuohai@huawei.com> 
Reviewed-by: Liu Chao <liuchao173@huawei.com> 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
...@@ -156,6 +156,15 @@ config UPROBES ...@@ -156,6 +156,15 @@ config UPROBES
managed by the kernel and kept transparent to the probed managed by the kernel and kept transparent to the probed
application. ) application. )
config UPROBES_SUPPORT_PC_ALTER
def_bool n
depends on UPROBES
help
Add UPROBE_ALTER_PC flag for uprobe handlers. When handlers
change the pc register, set this flag to let the uprobe
mechanism skip the execuation of the next insturction.
config HAVE_64BIT_ALIGNED_ACCESS config HAVE_64BIT_ALIGNED_ACCESS
def_bool 64BIT && !HAVE_EFFICIENT_UNALIGNED_ACCESS def_bool 64BIT && !HAVE_EFFICIENT_UNALIGNED_ACCESS
help help
......
...@@ -758,6 +758,7 @@ CONFIG_JUMP_LABEL=y ...@@ -758,6 +758,7 @@ CONFIG_JUMP_LABEL=y
CONFIG_OPTPROBES=y CONFIG_OPTPROBES=y
CONFIG_KPROBES_ON_FTRACE=y CONFIG_KPROBES_ON_FTRACE=y
CONFIG_UPROBES=y CONFIG_UPROBES=y
CONFIG_UPROBES_SUPPORT_PC_ALTER=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_KRETPROBES=y CONFIG_KRETPROBES=y
......
...@@ -22,8 +22,14 @@ struct inode; ...@@ -22,8 +22,14 @@ struct inode;
struct notifier_block; struct notifier_block;
struct page; struct page;
#define UPROBE_HANDLER_REMOVE 1 #define UPROBE_HANDLER_REMOVE 1
#define UPROBE_HANDLER_MASK 1
#ifndef CONFIG_UPROBES_SUPPORT_PC_ALTER
#define UPROBE_HANDLER_MASK 1
#else
#define UPROBE_ALTER_PC 0x2
#define UPROBE_HANDLER_MASK 0x3
#endif
#define MAX_URETPROBE_DEPTH 64 #define MAX_URETPROBE_DEPTH 64
......
...@@ -2070,10 +2070,17 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) ...@@ -2070,10 +2070,17 @@ static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
return uprobe; return uprobe;
} }
#ifdef CONFIG_UPROBES_SUPPORT_PC_ALTER
static bool handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
#else
static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
#endif
{ {
struct uprobe_consumer *uc; struct uprobe_consumer *uc;
int remove = UPROBE_HANDLER_REMOVE; int remove = UPROBE_HANDLER_REMOVE;
#ifdef CONFIG_UPROBES_SUPPORT_PC_ALTER
bool need_skip = false;
#endif
bool need_prep = false; /* prepare return uprobe, when needed */ bool need_prep = false; /* prepare return uprobe, when needed */
down_read(&uprobe->register_rwsem); down_read(&uprobe->register_rwsem);
...@@ -2090,6 +2097,10 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) ...@@ -2090,6 +2097,10 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
need_prep = true; need_prep = true;
remove &= rc; remove &= rc;
#ifdef CONFIG_UPROBES_SUPPORT_PC_ALTER
if (rc & UPROBE_ALTER_PC)
need_skip = true;
#endif
} }
if (need_prep && !remove) if (need_prep && !remove)
...@@ -2100,6 +2111,9 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) ...@@ -2100,6 +2111,9 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
unapply_uprobe(uprobe, current->mm); unapply_uprobe(uprobe, current->mm);
} }
up_read(&uprobe->register_rwsem); up_read(&uprobe->register_rwsem);
#ifdef CONFIG_UPROBES_SUPPORT_PC_ALTER
return need_skip;
#endif
} }
static void static void
...@@ -2241,7 +2255,12 @@ static void handle_swbp(struct pt_regs *regs) ...@@ -2241,7 +2255,12 @@ static void handle_swbp(struct pt_regs *regs)
if (arch_uprobe_ignore(&uprobe->arch, regs)) if (arch_uprobe_ignore(&uprobe->arch, regs))
goto out; goto out;
#ifdef CONFIG_UPROBES_SUPPORT_PC_ALTER
if (handler_chain(uprobe, regs))
goto out;
#else
handler_chain(uprobe, regs); handler_chain(uprobe, regs);
#endif
if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
goto out; goto out;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册