linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bagas Sanjaya <bagasdotme@gmail.com>
To: Kunbo Zhang <absoler@smail.nju.edu.cn>
Cc: dmitry.torokhov@gmail.com, tiwai@suse.de,
	wsa+renesas@sang-engineering.com, linux-kernel@vger.kernel.org,
	linux-input@vger.kernel.org, security@kernel.org
Subject: Re: [PATCH] input: i8042 - fix a double-fetch vulnerability introduced by GCC
Date: Fri, 4 Nov 2022 15:04:05 +0700	[thread overview]
Message-ID: <Y2THdZRV7Wg/1mSC@debian.me> (raw)
In-Reply-To: <20221104072347.74314-1-absoler@smail.nju.edu.cn>

[-- Attachment #1: Type: text/plain, Size: 4287 bytes --]

On Fri, Nov 04, 2022 at 03:23:47PM +0800, Kunbo Zhang wrote:
> We found GCC (at least 9.4.0 and 12.1) introduces a double-fetch of `i8042_ports[I8042_AUX_PORT_NO].serio` at drivers/input/serio/i8042.c:408.
> 
> One comparison of the global variable `i8042_ports[I8042_AUX_PORT_NO].serio` has been compiled to three ones,
> and thus two extra fetches are introduced.
> As in the source code, the global variable is tested (at line 408) before three assignments of irq_bit, disable_bit and port_name.
> However, as shown in the following disassembly of i8042_port_close(), 
> the variable (0x0(%rip)) is fetched and tested three times for each 
> assignment of irq_bit, disable_bit and port_name.
> 
> 0000000000000e50 <i8042_port_close>:
> i8042_port_close():
> ./drivers/input/serio/i8042.c:408
>      e50:	48 39 3d 00 00 00 00    cmp    %rdi,0x0(%rip)        # first load
> ./drivers/input/serio/i8042.c:403
>      e57:	41 54                   push   %r12
> ./drivers/input/serio/i8042.c:408
>      e59:	b8 ef ff ff ff          mov    $0xffffffef,%eax
>      e5e:	49 c7 c4 00 00 00 00    mov    $0x0,%r12
> ./drivers/input/serio/i8042.c:403
>      e65:	55                      push   %rbp
> ./drivers/input/serio/i8042.c:408
>      e66:	48 c7 c2 00 00 00 00    mov    $0x0,%rdx
> ./drivers/input/serio/i8042.c:419
>      e6d:	be 60 10 00 00          mov    $0x1060,%esi
> ./drivers/input/serio/i8042.c:403
>      e72:	53                      push   %rbx
> ./drivers/input/serio/i8042.c:408
>      e73:	bb df ff ff ff          mov    $0xffffffdf,%ebx
>      e78:	0f 45 d8                cmovne %eax,%ebx
>      e7b:	0f 95 c0                setne  %al
>      e7e:	83 e8 03                sub    $0x3,%eax
>      e81:	48 39 3d 00 00 00 00    cmp    %rdi,0x0(%rip)        # second load
>      e88:	40 0f 94 c5             sete   %bpl
>      e8c:	83 c5 01                add    $0x1,%ebp
>      e8f:	48 39 3d 00 00 00 00    cmp    %rdi,0x0(%rip)        # third load
> ./drivers/input/serio/i8042.c:419
>      e96:	48 c7 c7 00 00 00 00    mov    $0x0,%rdi
> ./drivers/input/serio/i8042.c:408
>      e9d:	4c 0f 45 e2             cmovne %rdx,%r12
> 
> We have not found any lock protection for the three fetches of `i8042_ports[I8042_AUX_PORT_NO].serio` yet.
> If the value of this global variable is modified concurrently among the three fetches, the corresponding assignment of 
> disable_bit or port_name will possibly be incorrect.
> 
> This patch fixs this by saving the checked value in advance and using a barrier() to prevent compiler optimizations.
> This is inspired by a similar compiler-introduced double fetch situation [1] in driver/xen (?).
> 
> [1] GitHub link of commit <8135cf8b092723dbfcc611fe6fdcb3a36c9951c5> ( Save xen_pci_op commands before processing it )
> ---
>  drivers/input/serio/i8042.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
> index f9486495baef..554a2340ca84 100644
> --- a/drivers/input/serio/i8042.c
> +++ b/drivers/input/serio/i8042.c
> @@ -405,7 +405,9 @@ static void i8042_port_close(struct serio *serio)
>  	int disable_bit;
>  	const char *port_name;
>  
> -	if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) {
> +	struct serio *tmp = i8042_ports[I8042_AUX_PORT_NO].serio;
> +	barrier();
> +	if (serio == tmp) {
>  		irq_bit = I8042_CTR_AUXINT;
>  		disable_bit = I8042_CTR_AUXDIS;
>  		port_name = "AUX";
> 
> Signed-off-by: Kunbo Zhang <absoler@smail.nju.edu.cn>
> 

Regarding patch description, there are several guides:

  * Wrap the text (excluding code or terminal output) at 80 character
    or less.
  * Please write in imperative mood instead (no first-person pronouns [I, we],
    "make foo do bar").
  * When referring to past commits, the format should be
    --pretty=format:'%h ("%s")'. The commit hash is at least 12
    characters long (set core.abbrev to 12 on your .gitconfig)
  * Last but not least, place your SoB at the end of description (before
    three dash line).

Also, is this patch also applies to stable branches? If so, add Cc:
stable@vger.kernel.org to the SoB area.

Thanks.

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

  reply	other threads:[~2022-11-04  8:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-04  7:23 [PATCH] input: i8042 - fix a double-fetch vulnerability introduced by GCC Kunbo Zhang
2022-11-04  8:04 ` Bagas Sanjaya [this message]
2022-11-04 10:45 ` Greg KH
2022-11-04 18:23   ` Dmitry Torokhov

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=Y2THdZRV7Wg/1mSC@debian.me \
    --to=bagasdotme@gmail.com \
    --cc=absoler@smail.nju.edu.cn \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=security@kernel.org \
    --cc=tiwai@suse.de \
    --cc=wsa+renesas@sang-engineering.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).