ACK/cmnt: [PATCH] x86/kprobes: Fix optprobe to detect INT3 padding correctly

Kleber Souza kleber.souza at canonical.com
Wed Mar 10 11:25:29 UTC 2021


On 08.03.21 21:49, Tim Gardner wrote:
> From: Masami Hiramatsu <mhiramat at kernel.org>
> 
> CVE-2021-3411
> 
> commit 0d07c0ec4381f630c801539c79ad8dcc627f6e4a upstream.
> 
> Commit
> 
>    7705dc855797 ("x86/vmlinux: Use INT3 instead of NOP for linker fill bytes")
> 
> changed the padding bytes between functions from NOP to INT3. However,
> when optprobe decodes a target function it finds INT3 and gives up the
> jump optimization.
> 
> Instead of giving up any INT3 detection, check whether the rest of the
> bytes to the end of the function are INT3. If all of them are INT3,
> those come from the linker. In that case, continue the optprobe jump
> optimization.
> 
>   [ bp: Massage commit message. ]
> 
> Fixes: 7705dc855797 ("x86/vmlinux: Use INT3 instead of NOP for linker fill bytes")
> Reported-by: Adam Zabrocki <pi3 at pi3.com.pl>
> Signed-off-by: Masami Hiramatsu <mhiramat at kernel.org>
> Signed-off-by: Borislav Petkov <bp at suse.de>
> Reviewed-by: Steven Rostedt (VMware) <rostedt at goodmis.org>
> Reviewed-by: Kees Cook <keescook at chromium.org>
> Cc: stable at vger.kernel.org
> Link: https://lkml.kernel.org/r/160767025681.3880685.16021570341428835411.stgit@devnote2
> Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> 
> (backported from commit d4f949439d2748209b004b4003e21285e580909d)

This sha1 seems to come from the linux-5.9.y linux-stable branch, so we should add the
"linux-5.9.y" prefix to the line above.

> Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
> 
> [ commit fe557319aa06c23cffc9346000f119547e0f289a "maccess: rename probe_kernel_{read,write}
> to copy_{from,to}_kernel_nofault" renamed probe_kernel_read() to copy_from_kernel_nofault().
> commit 25f12ae45fc1931a1dce3cc59f9989a9d87834b0 "maccess: rename probe_kernel_address to get_kernel_nofault"
> added get_kernel_nofault() in include/linux/uaccess.h. However, that commit is too invasive to
> backport intact. ]

Apart from the small comment above, which we can fix when applying, the backport
looks good.

Acked-by: Kleber Sacilotto de Souza <kleber.souza at canonical.com>

> ---
>   arch/x86/kernel/kprobes/opt.c | 25 +++++++++++++++++++++++--
>   1 file changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c
> index 3f45b5c43a71..21acfc823a91 100644
> --- a/arch/x86/kernel/kprobes/opt.c
> +++ b/arch/x86/kernel/kprobes/opt.c
> @@ -247,6 +247,22 @@ static int insn_is_indirect_jump(struct insn *insn)
>   	return ret;
>   }
>   
> +#define get_kernel_nofault(val, ptr)           \
> +	probe_kernel_read(&(val), (ptr), sizeof(val))
> +
> +static bool is_padding_int3(unsigned long addr, unsigned long eaddr)
> +{
> +	unsigned char ops;
> +
> +	for (; addr < eaddr; addr++) {
> +		if (get_kernel_nofault(ops, (void *)addr) < 0 ||
> +		    ops != INT3_INSN_OPCODE)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
>   /* Decode whole function to ensure any instructions don't jump into target */
>   static int can_optimize(unsigned long paddr)
>   {
> @@ -287,9 +303,14 @@ static int can_optimize(unsigned long paddr)
>   			return 0;
>   		kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
>   		insn_get_length(&insn);
> -		/* Another subsystem puts a breakpoint */
> +		/*
> +		 * In the case of detecting unknown breakpoint, this could be
> +		 * a padding INT3 between functions. Let's check that all the
> +		 * rest of the bytes are also INT3.
> +		 */
>   		if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
> -			return 0;
> +			return is_padding_int3(addr, paddr - offset + size) ? 1 : 0;
> +
>   		/* Recover address */
>   		insn.kaddr = (void *)addr;
>   		insn.next_byte = (void *)(addr + insn.length);
> 




More information about the kernel-team mailing list