From patchwork Thu Apr 19 13:04:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kleber Sacilotto de Souza X-Patchwork-Id: 901065 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 40RfMn3lgnz9s2B; Thu, 19 Apr 2018 23:04:37 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1f99Ek-0003JM-0c; Thu, 19 Apr 2018 13:04:30 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1f99Ei-0003In-TO for kernel-team@lists.ubuntu.com; Thu, 19 Apr 2018 13:04:28 +0000 Received: from mail-wr0-f198.google.com ([209.85.128.198]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1f99Ei-0007Af-MF for kernel-team@lists.ubuntu.com; Thu, 19 Apr 2018 13:04:28 +0000 Received: by mail-wr0-f198.google.com with SMTP id u13-v6so5150879wre.1 for ; Thu, 19 Apr 2018 06:04:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=FaxkR6rCFwObPjtE4Jfyk3upJWoYz6Hee4n8fN7Bx+4=; b=TOztwnPgRJ1oqAnNoAjSHq1R+884npnYKx03KYBsba9lbKr0E25DX3Tot2vTuJgCd+ zv1ebsiEodXu9o6Ei9GIgVA0xEM/8FeonMOjt4zTJFMf3APB3FkoP+k4FbQK7WdC/vIq +7zp4384BrnyUSNcdV8jQyyrJtymxdarleUwX1LZmXGWDZeGb4iJjXe1MeQ4IZtWaGjW 43Yu0ezf9l5o29tyCCILsYvLDg/sMJnY2CF5qf5kVWQ3VCiMuS/6GgMZqQE/qDAshlRH dqUtCaPV8LhSJEIZ5fJVLRdY0xQiGcCnnYcwd0sm9374DDGLw4EWoL8utOxct6HSEVBa ybPA== X-Gm-Message-State: ALQs6tCrygZli86hxjqj8Mjv7Cc+/7FlMNHNOrcxz0wzbQA1sxBNxsbp lgQzxbo4w4npGGlZ/9eaIsLsSNcvm/CcKhtg4pno75EClUJ8S1qgJcc+7CXGF+WJNUtaLlLS1v9 mXk1Zs1F2fl0CHAw4Ym7Vp4yx6LYPLxyVBW+3rv8kFg== X-Received: by 10.80.202.202 with SMTP id f10mr8473016edi.157.1524143068089; Thu, 19 Apr 2018 06:04:28 -0700 (PDT) X-Google-Smtp-Source: AIpwx4852bbmh/pSlkF7cSl4fiDjkxbw5izs+KNBi6mH9TcstOrIh7rFCk94dGow34m//qzbuzDLsA== X-Received: by 10.80.202.202 with SMTP id f10mr8472994edi.157.1524143067864; Thu, 19 Apr 2018 06:04:27 -0700 (PDT) Received: from localhost ([2a02:8109:98c0:1604:55ca:c9ac:ade4:9bbd]) by smtp.gmail.com with ESMTPSA id x18sm1796085edi.58.2018.04.19.06.04.26 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 19 Apr 2018 06:04:27 -0700 (PDT) From: Kleber Sacilotto de Souza To: kernel-team@lists.ubuntu.com Subject: [SRU][Trusty][CVE-2017-18079][PATCH] Input: i8042 - fix crash at boot time Date: Thu, 19 Apr 2018 15:04:25 +0200 Message-Id: <20180419130425.32065-1-kleber.souza@canonical.com> X-Mailer: git-send-email 2.14.1 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Chen Hong CVE-2017-18079 The driver checks port->exists twice in i8042_interrupt(), first when trying to assign temporary "serio" variable, and second time when deciding whether it should call serio_interrupt(). The value of port->exists may change between the 2 checks, and we may end up calling serio_interrupt() with a NULL pointer: BUG: unable to handle kernel NULL pointer dereference at 0000000000000050 IP: [] _spin_lock_irqsave+0x1f/0x40 PGD 0 Oops: 0002 [#1] SMP last sysfs file: CPU 0 Modules linked in: Pid: 1, comm: swapper Not tainted 2.6.32-358.el6.x86_64 #1 QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:[] [] _spin_lock_irqsave+0x1f/0x40 RSP: 0018:ffff880028203cc0 EFLAGS: 00010082 RAX: 0000000000010000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000282 RSI: 0000000000000098 RDI: 0000000000000050 RBP: ffff880028203cc0 R08: ffff88013e79c000 R09: ffff880028203ee0 R10: 0000000000000298 R11: 0000000000000282 R12: 0000000000000050 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000098 FS: 0000000000000000(0000) GS:ffff880028200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 0000000000000050 CR3: 0000000001a85000 CR4: 00000000001407f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 1, threadinfo ffff88013e79c000, task ffff88013e79b500) Stack: ffff880028203d00 ffffffff813de186 ffffffffffffff02 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000098 ffff880028203d70 ffffffff813e0162 ffff880028203d20 ffffffff8103b8ac Call Trace: [] serio_interrupt+0x36/0xa0 [] i8042_interrupt+0x132/0x3a0 [] ? kvm_clock_read+0x1c/0x20 [] ? kvm_clock_get_cycles+0x9/0x10 [] handle_IRQ_event+0x60/0x170 [] ? kvm_guest_apic_eoi_write+0x44/0x50 [] handle_edge_irq+0xde/0x180 [] handle_irq+0x49/0xa0 [] do_IRQ+0x6c/0xf0 [] ret_from_intr+0x0/0x11 [] ? __do_softirq+0x73/0x1e0 [] ? hrtimer_interrupt+0x14b/0x260 [] ? call_softirq+0x1c/0x30 [] ? do_softirq+0x65/0xa0 [] ? irq_exit+0x85/0x90 [] ? smp_apic_timer_interrupt+0x70/0x9b [] ? apic_timer_interrupt+0x13/0x20 To avoid the issue let's change the second check to test whether serio is NULL or not. Also, let's take i8042_lock in i8042_start() and i8042_stop() instead of trying to be overly smart and using memory barriers. Signed-off-by: Chen Hong [dtor: take lock in i8042_start()/i8042_stop()] Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov (cherry picked from commit 340d394a789518018f834ff70f7534fc463d3226) Signed-off-by: Kleber Sacilotto de Souza Acked-by: Thadeu Lima de Souza Cascardo Acked-by: Khalid Elmously --- drivers/input/serio/i8042.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index eb796fff9e62..ccf971a8629f 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -397,8 +397,10 @@ static int i8042_start(struct serio *serio) { struct i8042_port *port = serio->port_data; + spin_lock_irq(&i8042_lock); port->exists = true; - mb(); + spin_unlock_irq(&i8042_lock); + return 0; } @@ -411,16 +413,20 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; + spin_lock_irq(&i8042_lock); port->exists = false; + port->serio = NULL; + spin_unlock_irq(&i8042_lock); /* + * We need to make sure that interrupt handler finishes using + * our serio port before we return from this function. * We synchronize with both AUX and KBD IRQs because there is * a (very unlikely) chance that AUX IRQ is raised for KBD port * and vice versa. */ synchronize_irq(I8042_AUX_IRQ); synchronize_irq(I8042_KBD_IRQ); - port->serio = NULL; } /* @@ -537,7 +543,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) spin_unlock_irqrestore(&i8042_lock, flags); - if (likely(port->exists && !filtered)) + if (likely(serio && !filtered)) serio_interrupt(serio, data, dfl); out: