Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
Steven Rostedt wrote: On Sat, 25 Apr 2020 10:11:56 + Christophe Leroy wrote: Sure it's be more explicit, but then more lines also. 3 lines for only one really usefull. With goto, I would look like: diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 046485bb0a52..938208f824da 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -139,14 +139,14 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) } } -#define PATCH_INSN(addr, instr) \ +#define PATCH_INSN(addr, instr, label) \ With the explicit label as a parameter, makes it more evident that it will do something (like jump) with that label. I think I will also rename the macro to PATCH_INSN_OR_GOTO() to make it super evident :) I like this solution the best! Thanks for the feedback. - Naveen
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
Christophe Leroy wrote: On 04/24/2020 06:26 PM, Naveen N. Rao wrote: Steven Rostedt wrote: On Thu, 23 Apr 2020 17:41:52 +0200 Christophe Leroy wrote: > diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c > index 024f7aad1952..046485bb0a52 100644 > --- a/arch/powerpc/kernel/optprobes.c > +++ b/arch/powerpc/kernel/optprobes.c > @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) > } > } > > +#define PATCH_INSN(addr, instr) \ > +do { \ > + int rc = patch_instruction((unsigned int *)(addr), instr); \ > + if (rc) { \ > + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ > + __func__, __LINE__, \ > + (void *)(addr), (void *)(addr), rc); \ > + return rc; \ > + } \ > +} while (0) > + I hate this kind of macro which hides the "return". What about keeping the return action in the caller ? Otherwise, what about implementing something based on the use of goto, on the same model as unsafe_put_user() for instance ? Thanks for the review. I noticed this as a warning from checkpatch.pl, but this looked compact and correct for use in the two following functions. You'll notice that I added it just before the two functions this is used in. I suppose 'goto err' is usable too, but the ftrace code (patch 2) will end up with more changes. I'm also struggling to see how a 'goto' is less offensive. I think Steve's suggestion below would be the better way to go, to make things explicit. Sure it's be more explicit, but then more lines also. 3 lines for only one really usefull. With goto, I would look like: diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 046485bb0a52..938208f824da 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -139,14 +139,14 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) } } -#define PATCH_INSN(addr, instr) \ +#define PATCH_INSN(addr, instr, label) \ do { \ int rc = patch_instruction((unsigned int *)(addr), instr); \ if (rc) {\ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ __func__, __LINE__, \ (void *)(addr), (void *)(addr), rc); \ - return rc; \ + goto label; \ }\ } while (0) My earlier complaint was that this would still add a flow control statement, so didn't look to immediately address your original concern. However, I suppose introduction of an explicit label makes things a bit better. In addition: @@ -291,23 +297,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) goto error; } - rc = patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback); - if (rc) { - pr_err("%s:%d: Error patching instruction at 0x%pK: %d\n", - __func__, __LINE__, - (void *)(buff + TMPL_CALL_HDLR_IDX), rc); - rc = -EFAULT; - goto error; - } - - rc = patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step); - if (rc) { - pr_err("%s:%d: Error patching instruction at 0x%pK: %d\n", - __func__, __LINE__, - (void *)(buff + TMPL_EMULATE_IDX), rc); - rc = -EFAULT; - goto error; - } + PATCH_INSN(buff + TMPL_CALL_HDLR_IDX, branch_op_callback, efault); + PATCH_INSN(buff + TMPL_EMULATE_IDX, branch_emulate_step, efault); I like how this variant can cover additional uses of patch_instruction() here. I will use this variant. Thanks for the suggestion! - Naveen
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
On Sat, 25 Apr 2020 10:11:56 + Christophe Leroy wrote: > > Sure it's be more explicit, but then more lines also. 3 lines for only > one really usefull. > > With goto, I would look like: > > diff --git a/arch/powerpc/kernel/optprobes.c > b/arch/powerpc/kernel/optprobes.c > index 046485bb0a52..938208f824da 100644 > --- a/arch/powerpc/kernel/optprobes.c > +++ b/arch/powerpc/kernel/optprobes.c > @@ -139,14 +139,14 @@ void arch_remove_optimized_kprobe(struct > optimized_kprobe *op) > } > } > > -#define PATCH_INSN(addr, instr) > \ > +#define PATCH_INSN(addr, instr, label) > \ With the explicit label as a parameter, makes it more evident that it will do something (like jump) with that label. I like this solution the best! -- Steve > do { > \ > int rc = patch_instruction((unsigned int *)(addr), instr); \ > if (rc) {\ > pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", > \ > __func__, __LINE__, \ > (void *)(addr), (void *)(addr), rc); \ > - return rc; \ > + goto label; \ > }\ > } while (0) >
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
On 04/24/2020 06:26 PM, Naveen N. Rao wrote: Steven Rostedt wrote: On Thu, 23 Apr 2020 17:41:52 +0200 Christophe Leroy wrote: > diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c > index 024f7aad1952..046485bb0a52 100644 > --- a/arch/powerpc/kernel/optprobes.c > +++ b/arch/powerpc/kernel/optprobes.c > @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) > } > } > > +#define PATCH_INSN(addr, instr) \ > +do { \ > + int rc = patch_instruction((unsigned int *)(addr), instr); \ > + if (rc) { \ > + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ > + __func__, __LINE__, \ > + (void *)(addr), (void *)(addr), rc); \ > + return rc; \ > + } \ > +} while (0) > + I hate this kind of macro which hides the "return". What about keeping the return action in the caller ? Otherwise, what about implementing something based on the use of goto, on the same model as unsafe_put_user() for instance ? Thanks for the review. I noticed this as a warning from checkpatch.pl, but this looked compact and correct for use in the two following functions. You'll notice that I added it just before the two functions this is used in. I suppose 'goto err' is usable too, but the ftrace code (patch 2) will end up with more changes. I'm also struggling to see how a 'goto' is less offensive. I think Steve's suggestion below would be the better way to go, to make things explicit. Sure it's be more explicit, but then more lines also. 3 lines for only one really usefull. With goto, I would look like: diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 046485bb0a52..938208f824da 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -139,14 +139,14 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) } } -#define PATCH_INSN(addr, instr) \ +#define PATCH_INSN(addr, instr, label) \ do {\ int rc = patch_instruction((unsigned int *)(addr), instr); \ if (rc) {\ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ __func__, __LINE__, \ (void *)(addr), (void *)(addr), rc); \ - return rc; \ + goto label; \ }\ } while (0) @@ -159,14 +159,17 @@ static int patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr) { /* addis r4,0,(insn)@h */ PATCH_INSN(addr, PPC_INST_ADDIS | ___PPC_RT(4) | - ((val >> 16) & 0x)); + ((val >> 16) & 0x), failed); addr++; /* ori r4,r4,(insn)@l */ PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(4) | - ___PPC_RS(4) | (val & 0x)); + ___PPC_RS(4) | (val & 0x), failed); return 0; + +failed: + return -EFAULT; } /* @@ -177,29 +180,32 @@ static int patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr) { /* lis r3,(op)@highest */ PATCH_INSN(addr, PPC_INST_ADDIS | ___PPC_RT(3) | - ((val >> 48) & 0x)); + ((val >> 48) & 0x), failed); addr++; /* ori r3,r3,(op)@higher */ PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 32) & 0x)); + ___PPC_RS(3) | ((val >> 32) & 0x), failed); addr++; /* rldicr r3,r3,32,31 */ PATCH_INSN(addr, PPC_INST_RLDICR | ___PPC_RA(3) | - ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)); + ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31), failed); addr++; /* oris r3,r3,(op)@h */ PATCH_INSN(addr, PPC_INST_ORIS | ___PPC_RA(3) | - ___PPC_RS(3) | ((val >> 16) & 0x)); + ___PPC_RS(3) | ((val >> 16) & 0x), failed); addr++; /* ori r3,r3,(op)@l */ PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(3) | - ___PPC_RS(3) | (val & 0x)); + ___PPC_RS(3) | (val & 0x), failed); return 0; + +failed: + return -EFAULT; }
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
Steven Rostedt wrote: On Fri, 24 Apr 2020 23:56:25 +0530 "Naveen N. Rao" wrote: > #define PATCH_INSN(addr, instr) \ > ({ >int rc = patch_instruction((unsigned int *)(addr), instr); \ >if (rc) \ >pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ >__func__, __LINE__, \ >(void *)(addr), (void *)(addr), rc); \ >rc; \ > }) > > > Then you can just do: > > ret = PATCH_INSN(...); >if (ret) >return ret; > > in the code. That's really nice. However, in this case, I guess I can simply use an inline function? The primary reason I used the macro was for including a 'return' statement in it. I thought the primary reason was the __func__, __LINE__ which wont work as expected as an inline. Ugh, you're right indeed. I clearly didn't think it through. :facepalm: I'll use this variant. Regards, Naveen
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
On Fri, 24 Apr 2020 23:56:25 +0530 "Naveen N. Rao" wrote: > > #define PATCH_INSN(addr, instr) \ > > ({ > > int rc = patch_instruction((unsigned int *)(addr), instr); \ > > if (rc) \ > > pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", > > \ > > __func__, __LINE__, \ > > (void *)(addr), (void *)(addr), rc); \ > > rc; \ > > }) > > > > > > Then you can just do: > > > > ret = PATCH_INSN(...); > > if (ret) > > return ret; > > > > in the code. > > That's really nice. However, in this case, I guess I can simply use an > inline function? The primary reason I used the macro was for including a > 'return' statement in it. I thought the primary reason was the __func__, __LINE__ which wont work as expected as an inline. -- Steve
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
Steven Rostedt wrote: On Thu, 23 Apr 2020 17:41:52 +0200 Christophe Leroy wrote: > diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c > index 024f7aad1952..046485bb0a52 100644 > --- a/arch/powerpc/kernel/optprobes.c > +++ b/arch/powerpc/kernel/optprobes.c > @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) >} > } > > +#define PATCH_INSN(addr, instr) \ > +do { \ > + int rc = patch_instruction((unsigned int *)(addr), instr); \ > + if (rc) {\ > + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ > + __func__, __LINE__, \ > + (void *)(addr), (void *)(addr), rc); \ > + return rc; \ > + }\ > +} while (0) > + I hate this kind of macro which hides the "return". What about keeping the return action in the caller ? Otherwise, what about implementing something based on the use of goto, on the same model as unsafe_put_user() for instance ? Thanks for the review. I noticed this as a warning from checkpatch.pl, but this looked compact and correct for use in the two following functions. You'll notice that I added it just before the two functions this is used in. I suppose 'goto err' is usable too, but the ftrace code (patch 2) will end up with more changes. I'm also struggling to see how a 'goto' is less offensive. I think Steve's suggestion below would be the better way to go, to make things explicit. #define PATCH_INSN(addr, instr) \ ({ int rc = patch_instruction((unsigned int *)(addr), instr); \ if (rc) \ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ __func__, __LINE__, \ (void *)(addr), (void *)(addr), rc); \ rc; \ }) Then you can just do: ret = PATCH_INSN(...); if (ret) return ret; in the code. That's really nice. However, in this case, I guess I can simply use an inline function? The primary reason I used the macro was for including a 'return' statement in it. Thanks for the review! - Naveen
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
On Thu, 23 Apr 2020 17:41:52 +0200 Christophe Leroy wrote: > > diff --git a/arch/powerpc/kernel/optprobes.c > > b/arch/powerpc/kernel/optprobes.c > > index 024f7aad1952..046485bb0a52 100644 > > --- a/arch/powerpc/kernel/optprobes.c > > +++ b/arch/powerpc/kernel/optprobes.c > > @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct > > optimized_kprobe *op) > > } > > } > > > > +#define PATCH_INSN(addr, instr) > > \ > > +do { > > \ > > + int rc = patch_instruction((unsigned int *)(addr), instr); \ > > + if (rc) {\ > > + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", > > \ > > + __func__, __LINE__, \ > > + (void *)(addr), (void *)(addr), rc); \ > > + return rc; \ > > + }\ > > +} while (0) > > + > > I hate this kind of macro which hides the "return". > > What about keeping the return action in the caller ? > > Otherwise, what about implementing something based on the use of goto, > on the same model as unsafe_put_user() for instance ? #define PATCH_INSN(addr, instr) \ ({ int rc = patch_instruction((unsigned int *)(addr), instr); \ if (rc) \ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ __func__, __LINE__, \ (void *)(addr), (void *)(addr), rc); \ rc; \ }) Then you can just do: ret = PATCH_INSN(...); if (ret) return ret; in the code. -- Steve
Re: [PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
Le 23/04/2020 à 17:09, Naveen N. Rao a écrit : patch_instruction() can fail in some scenarios. Add appropriate error checking so that such failures are caught and logged, and suitable error code is returned. Fixes: d07df82c43be8 ("powerpc/kprobes: Move kprobes over to patch_instruction()") Fixes: f3eca95638931 ("powerpc/kprobes/optprobes: Use patch_instruction()") Signed-off-by: Naveen N. Rao --- arch/powerpc/kernel/kprobes.c | 10 +++- arch/powerpc/kernel/optprobes.c | 99 ++--- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 81efb605113e..4a297ae2bd87 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -138,13 +138,19 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe); void arch_arm_kprobe(struct kprobe *p) { - patch_instruction(p->addr, BREAKPOINT_INSTRUCTION); + int rc = patch_instruction(p->addr, BREAKPOINT_INSTRUCTION); + + if (rc) + WARN("Failed to patch trap at 0x%pK: %d\n", (void *)p->addr, rc); } NOKPROBE_SYMBOL(arch_arm_kprobe); void arch_disarm_kprobe(struct kprobe *p) { - patch_instruction(p->addr, p->opcode); + int rc = patch_instruction(p->addr, p->opcode); + + if (rc) + WARN("Failed to remove trap at 0x%pK: %d\n", (void *)p->addr, rc); } NOKPROBE_SYMBOL(arch_disarm_kprobe); diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 024f7aad1952..046485bb0a52 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) } } +#define PATCH_INSN(addr, instr) \ +do {\ + int rc = patch_instruction((unsigned int *)(addr), instr); \ + if (rc) {\ + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ + __func__, __LINE__, \ + (void *)(addr), (void *)(addr), rc); \ + return rc; \ + }\ +} while (0) + I hate this kind of macro which hides the "return". What about keeping the return action in the caller ? Otherwise, what about implementing something based on the use of goto, on the same model as unsafe_put_user() for instance ? Christophe
[PATCH 3/3] powerpc/kprobes: Check return value of patch_instruction()
patch_instruction() can fail in some scenarios. Add appropriate error checking so that such failures are caught and logged, and suitable error code is returned. Fixes: d07df82c43be8 ("powerpc/kprobes: Move kprobes over to patch_instruction()") Fixes: f3eca95638931 ("powerpc/kprobes/optprobes: Use patch_instruction()") Signed-off-by: Naveen N. Rao --- arch/powerpc/kernel/kprobes.c | 10 +++- arch/powerpc/kernel/optprobes.c | 99 ++--- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 81efb605113e..4a297ae2bd87 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -138,13 +138,19 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe); void arch_arm_kprobe(struct kprobe *p) { - patch_instruction(p->addr, BREAKPOINT_INSTRUCTION); + int rc = patch_instruction(p->addr, BREAKPOINT_INSTRUCTION); + + if (rc) + WARN("Failed to patch trap at 0x%pK: %d\n", (void *)p->addr, rc); } NOKPROBE_SYMBOL(arch_arm_kprobe); void arch_disarm_kprobe(struct kprobe *p) { - patch_instruction(p->addr, p->opcode); + int rc = patch_instruction(p->addr, p->opcode); + + if (rc) + WARN("Failed to remove trap at 0x%pK: %d\n", (void *)p->addr, rc); } NOKPROBE_SYMBOL(arch_disarm_kprobe); diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 024f7aad1952..046485bb0a52 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -139,52 +139,67 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) } } +#define PATCH_INSN(addr, instr) \ +do {\ + int rc = patch_instruction((unsigned int *)(addr), instr); \ + if (rc) {\ + pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \ + __func__, __LINE__, \ + (void *)(addr), (void *)(addr), rc); \ + return rc; \ + }\ +} while (0) + /* * emulate_step() requires insn to be emulated as * second parameter. Load register 'r4' with the * instruction. */ -void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr) +static int patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr) { /* addis r4,0,(insn)@h */ - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) | + PATCH_INSN(addr, PPC_INST_ADDIS | ___PPC_RT(4) | ((val >> 16) & 0x)); addr++; /* ori r4,r4,(insn)@l */ - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) | + PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(4) | ___PPC_RS(4) | (val & 0x)); + + return 0; } /* * Generate instructions to load provided immediate 64-bit value * to register 'r3' and patch these instructions at 'addr'. */ -void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr) +static int patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr) { /* lis r3,(op)@highest */ - patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) | + PATCH_INSN(addr, PPC_INST_ADDIS | ___PPC_RT(3) | ((val >> 48) & 0x)); addr++; /* ori r3,r3,(op)@higher */ - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) | + PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(3) | ___PPC_RS(3) | ((val >> 32) & 0x)); addr++; /* rldicr r3,r3,32,31 */ - patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) | + PATCH_INSN(addr, PPC_INST_RLDICR | ___PPC_RA(3) | ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31)); addr++; /* oris r3,r3,(op)@h */ - patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) | + PATCH_INSN(addr, PPC_INST_ORIS | ___PPC_RA(3) | ___PPC_RS(3) | ((val >> 16) & 0x)); addr++; /* ori r3,r3,(op)@l */ - patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) | + PATCH_INSN(addr, PPC_INST_ORI | ___PPC_RA(3) | ___PPC_RS(3) | (val & 0x)); + + return 0; } int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) @@ -216,14 +231,18 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) * be within 32MB on either side of the current instruction. */ b_offset = (unsigned long)buff - (unsigned long)p->addr; - if (!is_offset_in_branch_range(b_offset)) +