From patchwork Wed Jul 11 15:25:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 942559 X-Patchwork-Delegate: jagannadh.teki@gmail.com 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.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 41Qjn36PmCzB4MP for ; Thu, 12 Jul 2018 01:35:02 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 2EC73C21F76; Wed, 11 Jul 2018 15:27:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=KHOP_BIG_TO_CC autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 20B40C21CB1; Wed, 11 Jul 2018 15:25:48 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3EDDFC21E49; Wed, 11 Jul 2018 15:25:44 +0000 (UTC) Received: from mail.bootlin.com (mail.bootlin.com [62.4.15.54]) by lists.denx.de (Postfix) with ESMTP id 18027C21CB1 for ; Wed, 11 Jul 2018 15:25:43 +0000 (UTC) Received: by mail.bootlin.com (Postfix, from userid 110) id CDF4320893; Wed, 11 Jul 2018 17:25:42 +0200 (CEST) Received: from localhost.localdomain (AAubervilliers-681-1-12-56.w90-88.abo.wanadoo.fr [90.88.133.56]) by mail.bootlin.com (Postfix) with ESMTPSA id 5CFB5208B3; Wed, 11 Jul 2018 17:25:32 +0200 (CEST) From: Miquel Raynal To: Daniel Schwierzeck , Scott Wood , Jagan Teki Date: Wed, 11 Jul 2018 17:25:11 +0200 Message-Id: <20180711152529.24547-4-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180711152529.24547-1-miquel.raynal@bootlin.com> References: <20180711152529.24547-1-miquel.raynal@bootlin.com> Cc: Tom Rini , Alexandre Belloni , Boris Brezillon , Antoine Tenart , Boris Brezillon , Miquel Raynal , Allan Nielsen , u-boot@lists.denx.de, Richard Weinberger , Stefan Roese , Peter Pan Subject: [U-Boot] [PATCH v2 03/21] mtd: Add sanity checks in mtd_write/read_oob() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Boris Brezillon Unlike what's done in mtd_read/write(), there are no checks to make sure the parameters passed to mtd_read/write_oob() are consistent, which forces implementers of ->_read/write_oob() to do it, which in turn leads to code duplication and possibly errors in the logic. Do general sanity checks, like ops fields consistency and range checking. Signed-off-by: Boris Brezillon Cc: Peter Pan Signed-off-by: Richard Weinberger [Miquel: squashed the fix about the chip's size check] Signed-off-by: Miquel Raynal --- drivers/mtd/mtdcore.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c22ca20368..ba170f212e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1011,12 +1011,50 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, } EXPORT_SYMBOL_GPL(mtd_panic_write); +static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs, + struct mtd_oob_ops *ops) +{ + /* + * Some users are setting ->datbuf or ->oobbuf to NULL, but are leaving + * ->len or ->ooblen uninitialized. Force ->len and ->ooblen to 0 in + * this case. + */ + if (!ops->datbuf) + ops->len = 0; + + if (!ops->oobbuf) + ops->ooblen = 0; + + if (offs < 0 || offs + ops->len > mtd->size) + return -EINVAL; + + if (ops->ooblen) { + u64 maxooblen; + + if (ops->ooboffs >= mtd_oobavail(mtd, ops)) + return -EINVAL; + + maxooblen = ((mtd_div_by_ws(mtd->size, mtd) - + mtd_div_by_ws(offs, mtd)) * + mtd_oobavail(mtd, ops)) - ops->ooboffs; + if (ops->ooblen > maxooblen) + return -EINVAL; + } + + return 0; +} + int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) { int ret_code; ops->retlen = ops->oobretlen = 0; if (!mtd->_read_oob) return -EOPNOTSUPP; + + ret_code = mtd_check_oob_ops(mtd, from, ops); + if (ret_code) + return ret_code; + /* * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics * similar to mtd->_read(), returning a non-negative integer @@ -1035,11 +1073,18 @@ EXPORT_SYMBOL_GPL(mtd_read_oob); int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops) { + int ret; + ops->retlen = ops->oobretlen = 0; if (!mtd->_write_oob) return -EOPNOTSUPP; if (!(mtd->flags & MTD_WRITEABLE)) return -EROFS; + + ret = mtd_check_oob_ops(mtd, to, ops); + if (ret) + return ret; + return mtd->_write_oob(mtd, to, ops); } EXPORT_SYMBOL_GPL(mtd_write_oob);