From: Sean Christopherson <seanjc@google.com>
To: Borislav Petkov <bp@alien8.de>
Cc: Andy Lutomirski <luto@amacapital.net>,
Masami Hiramatsu <mhiramat@kernel.org>, X86 ML <x86@kernel.org>,
LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v1 04/19] x86/insn-eval: Handle return values from the decoder
Date: Mon, 28 Dec 2020 10:51:15 -0800 [thread overview]
Message-ID: <X+opI92rzCNZ151F@google.com> (raw)
In-Reply-To: <20201223174233.28638-5-bp@alien8.de>
On Wed, Dec 23, 2020, Borislav Petkov wrote:
> From: Borislav Petkov <bp@suse.de>
>
> Now that the different instruction-inspecting functions return a value,
> test that and return early from callers if error has been encountered.
>
> While at it, do not call insn_get_modrm() when calling
> insn_get_displacement() because latter will make sure to call
> insn_get_modrm() if ModRM hasn't been parsed yet.
>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> ---
> arch/x86/lib/insn-eval.c | 19 +++++++++++++------
> 1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
> index 265d23a0c334..7e49aaf5454c 100644
> --- a/arch/x86/lib/insn-eval.c
> +++ b/arch/x86/lib/insn-eval.c
> @@ -1106,18 +1106,21 @@ static int get_eff_addr_modrm_16(struct insn *insn, struct pt_regs *regs,
> * @base_offset will have a register, as an offset from the base of pt_regs,
> * that can be used to resolve the associated segment.
> *
> - * -EINVAL on error.
> + * Negative value on error.
> */
> static int get_eff_addr_sib(struct insn *insn, struct pt_regs *regs,
> int *base_offset, long *eff_addr)
> {
> long base, indx;
> int indx_offset;
> + int ret;
>
> if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
> return -EINVAL;
>
> - insn_get_modrm(insn);
> + ret = insn_get_modrm(insn);
This patch is incomplete/inconsistent, and arguably wrong.
- get_eff_addr_reg() and get_eff_addr_modrm() still ignore the return of
insn_get_modrm() after this patch.
- Calling insn_get_modrm() from get_eff_addr_sib() is unnecessary (unless the
caller passed uninitialized garbage in @insn) as get_eff_addr_sib() is
called if and only if sib.nbytes!=0, and sib.nbytes can be non-zero if and
only if the modrm and sib have been got.
- get_addr_ref_16() does insn_get_displacement, i.e. guarantees the modrm is
parsed, while the 32/64 variants do not.
What about adding a prereq patch (or three) to call insn_get_displacement() in
insn_get_addr_ref() prior to switching on insn->addr_bytes? Then the various
internal helpers could be changed to either omit the sanity checks entirely or
WARN on invalid calls? Or better yet, add an INSN_WARN_ON() macro that compiles
out the checks by default? E.g. something like:
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 7e49aaf5454c..348969146e0f 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -928,12 +928,8 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index 7e49aaf5454c..348969146e0f 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -928,12 +928,8 @@ static int get_seg_base_limit(struct insn *insn, struct pt_regs *regs,
static int get_eff_addr_reg(struct insn *insn, struct pt_regs *regs,
int *regoff, long *eff_addr)
{
- insn_get_modrm(insn);
-
- if (!insn->modrm.nbytes)
- return -EINVAL;
-
- if (X86_MODRM_MOD(insn->modrm.value) != 3)
+ if (INSN_WARN_ON(!insn->modrm.got || !insn->modrm.nbytes ||
+ X86_MODRM_MOD(insn->modrm.value) != 3)
return -EINVAL;
*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
@@ -978,15 +974,9 @@ static int get_eff_addr_modrm(struct insn *insn, struct pt_regs *regs,
{
long tmp;
- if (insn->addr_bytes != 8 && insn->addr_bytes != 4)
- return -EINVAL;
-
- insn_get_modrm(insn);
-
- if (!insn->modrm.nbytes)
- return -EINVAL;
-
- if (X86_MODRM_MOD(insn->modrm.value) > 2)
+ if (INSN_WARN_ON((insn->addr_bytes != 8 && insn->addr_bytes != 4) ||
+ !insn->modrm.got || !insn->modrm.nbytes ||
+ X86_MODRM_MOD(insn->modrm.value) > 2)
return -EINVAL;
*regoff = get_reg_offset(insn, regs, REG_TYPE_RM);
@@ -1046,15 +1036,8 @@ static int get_eff_addr_modrm_16(struct insn *insn, struct pt_regs *regs,
int addr_offset1, addr_offset2, ret;
short addr1 = 0, addr2 = 0, displacement;
- if (insn->addr_bytes != 2)
- return -EINVAL;
-
- insn_get_modrm(insn);
-
- if (!insn->modrm.nbytes)
- return -EINVAL;
-
- if (X86_MODRM_MOD(insn->modrm.value) > 2)
+ if (WARN_ON_ONCE(insn->addr_bytes != 2 || !insn->modrm.got ||
+ !insn->modrm.nbytes || insn->modrm.value > 2))
return -EINVAL;
ret = get_reg_offset_16(insn, regs, &addr_offset1, &addr_offset2);
@@ -1199,10 +1182,7 @@ static void __user *get_addr_ref_16(struct insn *insn, struct pt_regs *regs)
short eff_addr;
long tmp;
- if (insn_get_displacement(insn))
- goto out;
-
- if (insn->addr_bytes != 2)
+ if (INSN_WARN_ON(insn->addr_bytes != 2))
goto out;
if (X86_MODRM_MOD(insn->modrm.value) == 3) {
@@ -1263,7 +1243,7 @@ static void __user *get_addr_ref_32(struct insn *insn, struct pt_regs *regs)
long tmp;
int ret;
- if (insn->addr_bytes != 4)
+ if (INSN_WARN_ON(insn->addr_bytes != 4))
goto out;
if (X86_MODRM_MOD(insn->modrm.value) == 3) {
@@ -1356,7 +1336,7 @@ static void __user *get_addr_ref_64(struct insn *insn, struct pt_regs *regs)
int regoff, ret;
long eff_addr;
- if (insn->addr_bytes != 8)
+ if (INSN_WARN_ON(insn->addr_bytes != 8))
goto out;
if (X86_MODRM_MOD(insn->modrm.value) == 3) {
@@ -1408,6 +1388,9 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
if (!insn || !regs)
return (void __user *)-1L;
+ if (insn_get_displacement(insn))
+ return (void __user *)-1L;
+
switch (insn->addr_bytes) {
case 2:
return get_addr_ref_16(insn, regs);
next prev parent reply other threads:[~2020-12-28 18:52 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-23 17:42 [PATCH v1 00/19] x86/insn: Add an insn_decode() API Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 01/19] x86/insn: Rename insn_decode() to insn_decode_regs() Borislav Petkov
2020-12-28 17:16 ` Sean Christopherson
2020-12-29 19:36 ` Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 02/19] x86/insn: Add @buf_len param to insn_init() kernel-doc comment Borislav Petkov
2020-12-28 1:44 ` Masami Hiramatsu
2020-12-23 17:42 ` [PATCH v1 03/19] x86/insn: Add an insn_decode() API Borislav Petkov
2020-12-28 1:15 ` Masami Hiramatsu
2020-12-29 20:06 ` Borislav Petkov
2020-12-30 9:00 ` Masami Hiramatsu
2020-12-30 9:28 ` Borislav Petkov
2021-01-06 5:21 ` Masami Hiramatsu
2021-01-08 18:59 ` Borislav Petkov
2021-01-12 11:34 ` Masami Hiramatsu
2021-01-13 18:06 ` Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 04/19] x86/insn-eval: Handle return values from the decoder Borislav Petkov
2020-12-28 18:51 ` Sean Christopherson [this message]
2020-12-28 19:06 ` Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 05/19] x86/boot/compressed/sev-es: Convert to insn_decode() Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 06/19] perf/x86/intel/ds: Check insn_get_length() retval Borislav Petkov
2021-01-04 13:19 ` Peter Zijlstra
2021-01-19 10:40 ` Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 07/19] perf/x86/intel/ds: Check return values of insn decoder functions Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 08/19] x86/alternative: Use insn_decode() Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 09/19] x86/mce: Convert to insn_decode() Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 10/19] x86/kprobes: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 11/19] x86/sev-es: " Borislav Petkov
2020-12-25 10:50 ` kernel test robot
2020-12-25 10:50 ` kernel test robot
2020-12-25 12:33 ` Borislav Petkov
2020-12-25 12:33 ` Borislav Petkov
2020-12-28 19:15 ` Sean Christopherson
2020-12-28 19:15 ` Sean Christopherson
2021-01-21 16:58 ` Borislav Petkov
2021-01-21 16:58 ` Borislav Petkov
2021-01-21 22:35 ` Sean Christopherson
2021-01-21 22:35 ` Sean Christopherson
2020-12-23 17:42 ` [PATCH v1 12/19] x86/traps: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 13/19] x86/uprobes: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 14/19] x86/tools/insn_decoder_test: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 15/19] tools/objtool: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 16/19] x86/tools/insn_sanity: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 17/19] tools/perf: " Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 18/19] x86/insn: Remove kernel_insn_init() Borislav Petkov
2020-12-23 17:42 ` [PATCH v1 19/19] x86/insn: Make insn_complete() static Borislav Petkov
2020-12-27 15:26 ` [PATCH v1 00/19] x86/insn: Add an insn_decode() API Tom Lendacky
2021-02-03 12:00 ` Borislav Petkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=X+opI92rzCNZ151F@google.com \
--to=seanjc@google.com \
--cc=bp@alien8.de \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=mhiramat@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.