From patchwork Wed May 10 15:20:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Monakhov X-Patchwork-Id: 9720061 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 957AB60236 for ; Wed, 10 May 2017 15:21:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8857E28608 for ; Wed, 10 May 2017 15:21:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7D28A28610; Wed, 10 May 2017 15:21:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 29A8528608 for ; Wed, 10 May 2017 15:21:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753575AbdEJPVL (ORCPT ); Wed, 10 May 2017 11:21:11 -0400 Received: from mail-wr0-f196.google.com ([209.85.128.196]:33291 "EHLO mail-wr0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753544AbdEJPVI (ORCPT ); Wed, 10 May 2017 11:21:08 -0400 Received: by mail-wr0-f196.google.com with SMTP id w50so9045290wrc.0; Wed, 10 May 2017 08:21:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=Skd6ooUVQr5SNbMNFZP/E+lkht2xWz2Df88NTikbbgc=; b=QJcIkEjOXn3jBGtARhOSQpqjZGfh+iNTiWDsh5hzfq+Czx1gjOuDv4b35KbMi4ZUlf TI57G84qqQEF3Ht9Tslad7q9Jm87b/U3uYAwMVwo6MyyYO7U8gd6vABZweBMMf+0lvfZ JCTExkgTO7RrX1WATzVJ1mmC57p3jehWwUZAjBDFA3pioKmFFwDu+vNY+at5vb5bTUGl HG3HuSD/2UJc+ajvPlmTmnAFw0HF6laE0Gp+sIhwBxWYkmMbuT1GxZA3M6prVbPELwqh wohMY7NjVFPBuoie5eJB342dN3lpHhoQfDFXIcW1R9Y1xQu8yVZJqcLcNBsObF7QZm1J w8xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=Skd6ooUVQr5SNbMNFZP/E+lkht2xWz2Df88NTikbbgc=; b=kjGN76FfmhO8AYUVUvwUo6p7tSuZ7u+JKHZhDt/PPctErvVI8Y5IEokEqxPa7Hlja0 SQvQML1m9ePa+D7lNYvMJc/s6GQjC8cmJsBS1IswmiFaFnCa84KeH6jYmTlRBdz0s9nz vWjIf9f5lwKRyV7Q+Yc6fBZvNkl9+0XgOQW4eb7wWdI9VxgeDNDBkz7ceuQFenqE4kzc /aVcmnFG3qLEcPq2AOZSV/NqY3TYIBTMxnqvx5r4QwJX1BHflDKBtGuebIn8RgrjeIMv BNcQodHxnxwuB+vdsceTLQv/SUvYRUkllBuj5ROJnD5Vx5825jzWsfcQCEeLgtW/G2cN 5SkQ== X-Gm-Message-State: AODbwcAcGt7rRbTRmvMrjKF7vvAx4iIlmkt0Nuq1YyYEzoKUefHkVVrF 1Rq8zRKDwpONqJq7y1I= X-Received: by 10.46.32.24 with SMTP id g24mr3071289ljg.132.1494429665877; Wed, 10 May 2017 08:21:05 -0700 (PDT) Received: from smtp.gmail.com (msk-vpn.virtuozzo.com. [195.214.232.6]) by smtp.gmail.com with ESMTPSA id x2sm614242lfa.19.2017.05.10.08.21.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 May 2017 08:21:05 -0700 (PDT) From: Dmitry Monakhov To: fstests@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-block@vger.kernel.org, Dmitry Monakhov Subject: [PATCH 7/9] Guard bvec iteration logic Date: Wed, 10 May 2017 19:20:50 +0400 Message-Id: <1494429652-9488-8-git-send-email-dmonakhov@openvz.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1494429652-9488-1-git-send-email-dmonakhov@openvz.org> References: <1494429652-9488-1-git-send-email-dmonakhov@openvz.org> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently if some one try to advance bvec beyond it's size we simply dump WARN_ONCE and continue to iterate beyond bvec array boundaries. This simply means that we endup dereferencing/corrupting random memory region. Sane reaction would be to propagate error back to calling context But bvec_iter_advance's calling context is not always good for error handling. For safity reason let truncate iterator size to zero which will break external iteration loop which prevent us from unpredictable memory range corruption. And even it caller ignores an error, it will corrupt it's own bvecs, not others. This patch does: - Return error back to caller with hope that it will react on this - Truncate iterator size Code was added long time ago here 4550dd6c, luckily no one hit it in real life :) changes since V1: - Replace BUG_ON with error logic. Signed-off-by: Dmitry Monakhov Reviewed-by: Martin K. Petersen Reviewed-by: Christoph Hellwig Reviewed-by: Ming Lei --- drivers/nvdimm/blk.c | 4 +++- drivers/nvdimm/btt.c | 4 +++- include/linux/bio.h | 8 ++++++-- include/linux/bvec.h | 11 ++++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c index 0b49336..c82331b 100644 --- a/drivers/nvdimm/blk.c +++ b/drivers/nvdimm/blk.c @@ -106,7 +106,9 @@ static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk, len -= cur_len; dev_offset += cur_len; - bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len); + err = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len); + if (err) + return err; } return err; diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index 3d7a9fe..5a68681 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -942,7 +942,9 @@ static int btt_rw_integrity(struct btt *btt, struct bio_integrity_payload *bip, len -= cur_len; meta_nsoff += cur_len; - bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len); + ret = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len); + if (ret) + return ret; } return ret; diff --git a/include/linux/bio.h b/include/linux/bio.h index 1b4ebb4..643ecba 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -168,8 +168,12 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, if (bio_no_advance_iter(bio)) iter->bi_size -= bytes; - else - bvec_iter_advance(bio->bi_io_vec, iter, bytes); + else { + int err; + + err = bvec_iter_advance(bio->bi_io_vec, iter, bytes); + /* TODO: It is reasonable to complete bio with error here. */ + } } #define __bio_for_each_segment(bvl, bio, iter, start) \ diff --git a/include/linux/bvec.h b/include/linux/bvec.h index 89b65b8..984a7a8 100644 --- a/include/linux/bvec.h +++ b/include/linux/bvec.h @@ -22,6 +22,7 @@ #include #include +#include /* * was unsigned short, but we might as well be ready for > 64kB I/O pages @@ -66,12 +67,15 @@ struct bvec_iter { .bv_offset = bvec_iter_offset((bvec), (iter)), \ }) -static inline void bvec_iter_advance(const struct bio_vec *bv, +static inline int bvec_iter_advance(const struct bio_vec *bv, struct bvec_iter *iter, unsigned bytes) { - WARN_ONCE(bytes > iter->bi_size, - "Attempted to advance past end of bvec iter\n"); + if (WARN_ONCE(bytes > iter->bi_size, + "Attempted to advance past end of bvec iter\n")) { + iter->bi_size = 0; + return -EINVAL; + } while (bytes) { unsigned iter_len = bvec_iter_len(bv, *iter); @@ -86,6 +90,7 @@ static inline void bvec_iter_advance(const struct bio_vec *bv, iter->bi_idx++; } } + return 0; } #define for_each_bvec(bvl, bio_vec, iter, start) \