From patchwork Thu Apr 18 16:58:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 10907735 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 32C3217E0 for ; Thu, 18 Apr 2019 16:58:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19AF428B51 for ; Thu, 18 Apr 2019 16:58:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0DE6828B53; Thu, 18 Apr 2019 16:58:48 +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=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 6390D28B51 for ; Thu, 18 Apr 2019 16:58:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389316AbfDRQ6q (ORCPT ); Thu, 18 Apr 2019 12:58:46 -0400 Received: from mail-pf1-f194.google.com ([209.85.210.194]:38574 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388401AbfDRQ6q (ORCPT ); Thu, 18 Apr 2019 12:58:46 -0400 Received: by mail-pf1-f194.google.com with SMTP id 10so1381968pfo.5; Thu, 18 Apr 2019 09:58:45 -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; bh=m3DeIylgBdEsp6d+HKmmt5aAC+EP51roAXacfc39ITk=; b=eGGIdI/casowTMzeTohXoNW1BWmnAFzab/YrrzDk4Ok95ftVY+l4Ji8cZZrny83Pyz AvMcQwj732f3JbbCm7GlfeJCgsf7bILCZM+x/iIvht3466SPJoAWEu3B6cMBLs4h/iwE msyhLyvq1B1xcWPyB5i3HG0PPO0qXL5f+0UFaWhmHQpJt0FhV/FroQjji9rKvn8sYDgs mxPAa7VJR4TaE4vTMknLJQ5teIBjJC4bbrmK2oYFWuOO3WhN311v9ivQ+Wi1S95mWDWD f0UMeHpTiJmBHHQ0Qyrmxh4WoEuYc2LJtCFrLcVCKAEhSTiOxC8Umzmn0ADqUo8dGToa jZPQ== 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; bh=m3DeIylgBdEsp6d+HKmmt5aAC+EP51roAXacfc39ITk=; b=O+E3ZW12qIgbTO9oGIT2RL+SdcjTiUMqBgb7JjcDM25UCb1GzA4GlYROMcxMXZw1Oo kHX02QA8j58dyv4KfeQM+5MM+nXJO27d0ZBL0i2iG9rElfk4/KatenJvgbmW6eZd2xKt /kEH+TwYcPX6OQ6V1+s3XKpaGXeiJTC76VL2lE19bth8OAWIE7HmXRLJ5HDl6eud6JZx 1kVfrD+PJsJHsj5HjdSeoiOfZRx5AIjQSvQx/atoZ3Yy0pUMGm+ZWawaPuxWPFoh2Oo6 QZEukFni5s1afDkCEA/NinqfwHs2jQ30uOMIFBg65icsEB6IMXh5YdkTCGH+dWzTJmIJ W8wA== X-Gm-Message-State: APjAAAVntJPCJl8FzT7Q0ZZr49PdEoqf8izx/Oulq4e3riaGR+m1/F92 yTl1wXvIIvlfuGYpmRxL4C4X9YqR X-Google-Smtp-Source: APXvYqwP5QwYQQ9HJHPJPbSEQ9o5NaRH5M0s2VmoEe5q5HV/AQncCZk1eBML63WKgZNtEjOdVpiBeQ== X-Received: by 2002:a62:e418:: with SMTP id r24mr97599861pfh.52.1555606725103; Thu, 18 Apr 2019 09:58:45 -0700 (PDT) Received: from localhost ([2600:1700:e321:62f0:329c:23ff:fee3:9d7c]) by smtp.gmail.com with ESMTPSA id n65sm10179134pfb.160.2019.04.18.09.58.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Apr 2019 09:58:43 -0700 (PDT) From: Guenter Roeck To: Jens Axboe Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck , Christoph Hellwig Subject: [PATCH -next] block: Warn if page offset is equal to or larger than page size Date: Thu, 18 Apr 2019 09:58:41 -0700 Message-Id: <1555606721-17679-1-git-send-email-linux@roeck-us.net> X-Mailer: git-send-email 2.7.4 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Prior to commit 8a96a0e40810 ("block: rewrite blk_bvec_map_sg to avoid a nth_page call"), it was valid to call blk_bvec_map_sg() with an offset equal to or larger than the page size. blk_bvec_map_sg() would then adjust page and offset by calling bvec_nth_page(). This is no longer possible. Large offsets are now directly passed without validation to sg_set_page(). This results in data corruption and crashes such as the following, observed when trying to boot arm:vexpress from mmc. Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b CPU: 0 PID: 1 Comm: init Tainted: G W 5.1.0-rc5-next-20190418-dirty #1 Hardware name: ARM-Versatile Express [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0xb4/0xc8) [] (dump_stack) from [] (panic+0x110/0x328) [] (panic) from [] (do_exit+0xbfc/0xc08) [] (do_exit) from [] (do_group_exit+0x3c/0xbc) [] (do_group_exit) from [] (get_signal+0x13c/0x9c4) [] (get_signal) from [] (do_work_pending+0x1a8/0x5e0) [] (do_work_pending) from [] (slow_work_pending+0xc/0x20) The above does not help at all when trying to track down the problem. Let's at least add a warning to generate a traceback. The crash will still be observed, but at least we'll have a hint what is causing it. With this patch applied, we'll see something like the following prior to the crash. WARNING: CPU: 0 PID: 84 at block/blk-merge.c:480 blk_rq_map_sg+0x3cc/0x6ac page offset 19456 larger than page size 4096 Modules linked in: CPU: 0 PID: 84 Comm: kworker/0:1H Not tainted 5.1.0-rc5-next-20190418-dirty #1 Hardware name: ARM-Versatile Express Workqueue: kblockd blk_mq_run_work_fn [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0xb4/0xc8) [] (dump_stack) from [] (__warn+0xe0/0xf8) [] (__warn) from [] (warn_slowpath_fmt+0x4c/0x70) [] (warn_slowpath_fmt) from [] (blk_rq_map_sg+0x3cc/0x6ac) [] (blk_rq_map_sg) from [] (mmc_blk_data_prep+0x1b0/0x2c8) [] (mmc_blk_data_prep) from [] (mmc_blk_rw_rq_prep+0x50/0x178) [] (mmc_blk_rw_rq_prep) from [] (mmc_blk_mq_issue_rq+0x294/0x880) [] (mmc_blk_mq_issue_rq) from [] (mmc_mq_queue_rq+0x128/0x230) [] (mmc_mq_queue_rq) from [] (blk_mq_dispatch_rq_list+0x3b4/0x5e0) [] (blk_mq_dispatch_rq_list) from [] (blk_mq_do_dispatch_sched+0x70/0x10c) [] (blk_mq_do_dispatch_sched) from [] (blk_mq_sched_dispatch_requests+0x11c/0x198) [] (blk_mq_sched_dispatch_requests) from [] (__blk_mq_run_hw_queue+0xe0/0x170) [] (__blk_mq_run_hw_queue) from [] (process_one_work+0x284/0x6b4) [] (process_one_work) from [] (worker_thread+0x44/0x528) [] (worker_thread) from [] (kthread+0x15c/0x164) [] (kthread) from [] (ret_from_fork+0x14/0x2c) Exception stack(0xc58d5fb0 to 0xc58d5ff8) 5fa0: 00000000 00000000 00000000 00000000 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000 ---[ end trace ef7077b559d20ddc ]--- This patch is needed even if the call from mmc_blk_data_prep() is fixed. We'll have to expect further problems from callers who are not aware about the API change. Those problems will be difficult to track down without extra information. Use WARN_ONCE to report the problem. If the problem is seen, it may be seen many times, and we don't want to flood the kernel log with repeated messages. Cc: Christoph Hellwig Signed-off-by: Guenter Roeck --- I don't know if there are situations where offset >= PAGE_SIZE is acceptable. A quick comparison with current mainline did not report any instances where offset >= PAGE_SIZE is passed to sg_set_page(). I do see a number of warnings triggered by this patch in -next (for example with alpha, m68k, ppc64, and riscv64 emulations) which do not (or not immediately) result in a crash. If there is a different / better means to detect a problem, please let me know and I'll be happy to adjust the patch accordingly. block/blk-merge.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/block/blk-merge.c b/block/blk-merge.c index 247b17f2a0f6..9432cd88bd7e 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -475,6 +475,10 @@ static unsigned blk_bvec_map_sg(struct request_queue *q, unsigned offset = bvec->bv_offset + total; unsigned len = min(get_max_segment_size(q, offset), nbytes); + WARN_ONCE(offset >= PAGE_SIZE, + "page offset %u larger than or equal to page size %ld\n", + offset, PAGE_SIZE); + *sg = blk_next_sg(sg, sglist); sg_set_page(*sg, bvec->bv_page, len, offset);