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 --]
next prev parent 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 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.