From patchwork Sat Sep 16 03:02:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Worsley X-Patchwork-Id: 814456 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=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="SAK0rSMn"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3xvHC22rG1z9sPm for ; Sat, 16 Sep 2017 13:03:10 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751259AbdIPDDJ (ORCPT ); Fri, 15 Sep 2017 23:03:09 -0400 Received: from mail-pg0-f68.google.com ([74.125.83.68]:35699 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751257AbdIPDDI (ORCPT ); Fri, 15 Sep 2017 23:03:08 -0400 Received: by mail-pg0-f68.google.com with SMTP id j16so2201041pga.2 for ; Fri, 15 Sep 2017 20:03:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=dRPv5HkreBzERqVyPkhWIZLWRL0cbVr4OXiZNfuPeUk=; b=SAK0rSMnmuvLwbNYrJ26TSQFx55XCS6fQ4BKzzgr49aqEET38R426a2QPyCaff5wbS inzgovhpPWKz/bkKa6cW7KoSsu4ptXpzMBPUUS73S1zXT7lWYAgmPd0PmbNfT/NBM3QZ C6qSP3zy2So45KrIgmRHKcc3AxKZxGcwTDWsuibxF+IwonXh07u07yPotfgthnMrQPDT U9rskr900eFQSqvkQn4rq170LNFipbZGal4h+NO6vzBpbdJbxwfLTrlkMumsAlA/BmKH Di8qOqU8xICv9Yxxd8rF02w/HSzXa18qZ+KhYorxM+MpOru3hqyH/EDVGHyJmeoW1iH+ 523g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=dRPv5HkreBzERqVyPkhWIZLWRL0cbVr4OXiZNfuPeUk=; b=E4aZ9IjhzeWMl725s5sa+9u9uJlf4nbDkvrAeZ4Eb4W5wP1AoHgG/zMCQdwYZ6GdQh MEJR+JOPjXlPjUOTFV+PtLNuyirXSfcFnCKYVI6jnnFSqEARybK/KXJpMBPSbYyrEJp7 tvtwAa/wS9y3KrPehkOS+HMFlYru+RclEXYl1okQ2H9sB9cy8CvvUBTnx/+rxVICfJsk d9KqOANw7/IHH1qFqVd/SLXepr2vSKh8GzPOm5K7VuCz8gD3SLzp1o1Pr3EGHp8/89xq Hz6LoBonfNgPlnUo8BXE5zKReDy6ar2HNxLx/v/2KeRJzaXWcjt1WySiwxbX7Jhsq6gR JJxQ== X-Gm-Message-State: AHPjjUhVuhGuP8rnRZdGM5hbVu/TcA0TcYgL37zBW1jpinkWx4IaLXkw Wg4k9MbyrnA+sQ== X-Google-Smtp-Source: ADKCNb4FL2DIRz2dZD7mKtSi/7I1nI/O7DA/xCuRIZav0ir3kSL8LaOmd7XB28muWuOm2MsNFm89DQ== X-Received: by 10.84.196.131 with SMTP id l3mr26308268pld.195.1505530988435; Fri, 15 Sep 2017 20:03:08 -0700 (PDT) Received: from localhost (27-32-189-129.static.tpgi.com.au. [27.32.189.129]) by smtp.gmail.com with ESMTPSA id s81sm5799139pfg.162.2017.09.15.20.03.06 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 15 Sep 2017 20:03:07 -0700 (PDT) From: Andrew Worsley To: michal.simek@xilinx.com Cc: soren.brinkmann@xilinx.com, linux-arm-kernel@lists.infradead.org, linux-i2c@vger.kernel.org, Andrew Worsley Subject: [PATCH] Fix Bug for cadence i2c interrupt overrunning buffer Date: Sat, 16 Sep 2017 13:02:52 +1000 Message-Id: <20170916030252.10680-1-amworsley@gmail.com> X-Mailer: git-send-email 2.11.0 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The i2c interrupt handler was not checking against the length of supplied buffer so if the hardware supplied more data than requested in the i2c transfer it happily copies it right past the end of the buffer! Signed-off-by: Andrew Worsley --- This bug reliably caused a stack corruption when the hardware provided more data than asked for in the i2c request. The hardware (a tpm) very occasionally appends a burst of 0xff to the end of the data requested and the i2c interrupt handler mindlessly copies all the data right past the end of the buffer and in my case across the stack. :-( With this patch the transfer now terminates with an -EIO but with out voilating the buffer boundaries. I would prefer to just make the transfer succeed while not retrieving additional bytes but I wasn't able to find an easy way to do this. As this is definitely a fault that causes a kernel oops I just wanted to get a fix out there for others to avoid the problem as it has taken me a few weeks to chase down this oops. If someone has a better or nicer fix I would appreciate it or a pointer to how to do this. Thanks Andrew drivers/i2c/busses/i2c-cadence.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index b13605718291..c1f61ca6843e 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -234,6 +234,7 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) if (id->p_recv_buf && ((isr_status & CDNS_I2C_IXR_COMP) || (isr_status & CDNS_I2C_IXR_DATA))) { + unsigned char *p = id->p_recv_buf; /* Read data if receive data valid is set */ while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_RXDV) { @@ -246,6 +247,12 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) !id->bus_hold_flag) cdns_i2c_clear_bus_hold(id); + if (id->recv_count == 0) { + pr_notice("%s: i2c receive buffer filled : %u aborting transfer %p - %p\n", + __func__, (id->p_recv_buf - p)); + break; + } + *(id->p_recv_buf)++ = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); id->recv_count--;