From patchwork Mon Jul 23 20:16:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 10540881 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 6FBCF17FD for ; Mon, 23 Jul 2018 20:27:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5EFC21FF66 for ; Mon, 23 Jul 2018 20:27:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 53972205AD; Mon, 23 Jul 2018 20:27: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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C0E941FF66 for ; Mon, 23 Jul 2018 20:27:47 +0000 (UTC) Received: from localhost ([::1]:36378 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fhhQo-0001Js-Ts for patchwork-qemu-devel@patchwork.kernel.org; Mon, 23 Jul 2018 16:27:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40767) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fhhIM-0001X2-Uv for qemu-devel@nongnu.org; Mon, 23 Jul 2018 16:19:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fhhIL-0002an-Ev for qemu-devel@nongnu.org; Mon, 23 Jul 2018 16:19:02 -0400 Received: from mail-oi0-x235.google.com ([2607:f8b0:4003:c06::235]:46732) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fhhIL-0002Zd-8P; Mon, 23 Jul 2018 16:19:01 -0400 Received: by mail-oi0-x235.google.com with SMTP id y207-v6so3451459oie.13; Mon, 23 Jul 2018 13:19:01 -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=w6rthY66HSu0q2eoXSyGNZPu3utRhfMXTLBgJTlEVnw=; b=W/wDlnejvm722ztUQ7Re5GIYtLImwCPu55MkzqOiLqL4I6+hG12IPYY83jEf395aHy NOZGIV6+AcRHXXKDLpMVtSnjFjG92CAw8X6tjrc9jjM5M7IswHHUdrSTz4EGcrX9WTes GAxLugPmB+ObNfs51zLcRMfBFzdwVHQxA33wwOYH/K66dqUp7/laeeFNs0BAaKiC+m0n moWAPA+y6/VIBhMXmgTuiu98NdJML+N7LSIn2XWGwQIhmXElwUxlZkd9lAnWRQCqAcU9 Q9kkQZj5JErGrdX0tNdmcI8hefxP0cgtTB3Torr1AuIOErtXc6MKbRp0OPQwzArF38Xk 7Maw== 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=w6rthY66HSu0q2eoXSyGNZPu3utRhfMXTLBgJTlEVnw=; b=Za/E/EhPOCYLw+FDgxEXY/7I0RL6lzQtg/3CQQOT7ia/n31ANUWs9PGgUkUbYC0Ctw l23AQ6DqZ6EuemaC/IxuxnDYmiQLdmGAVtPyuGDJRfcjGoOH+Q5X+caZa0G6o4T4ItHI 9yl0w11rWXTqObdDJcUT2aDdil/NMDWLE3y9PW3d194HUzGst1/gAq6aG5FA//VRyy8A v9C/WTDqIxQVLhdY2/B63DSqqh8Tal2kiCZzC983b0A1x4rTgzhEAvZGCjg+sYunEsAC 6huyK8oI4uENqwnppqEZu0TOnolCgisido0K8Cs4l4cB4Y1i2GrmIb5JMzJBxfeAXNi4 Qf6Q== X-Gm-Message-State: AOUpUlG64vju/g4s1jyCDhL3GUoQHBMDS2oDDBHa1WlUdnisbTrS6/EB ux7sA7tbUThQNNMJxWcbLIFsNzRH6Z8= X-Google-Smtp-Source: AAOMgpdiLAmKELxDrod+KEDvdkOI5zbGGROF4z9XBJ+To4iO3nixkiBuV49Gf6Qdt7jgCVTqDcLeCQ== X-Received: by 2002:aca:e142:: with SMTP id y63-v6mr335842oig.128.1532377140145; Mon, 23 Jul 2018 13:19:00 -0700 (PDT) Received: from localhost (76-251-165-188.lightspeed.austtx.sbcglobal.net. [76.251.165.188]) by smtp.gmail.com with ESMTPSA id x23-v6sm6180815oie.0.2018.07.23.13.18.58 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Jul 2018 13:18:59 -0700 (PDT) From: Michael Roth To: qemu-devel@nongnu.org Date: Mon, 23 Jul 2018 15:16:27 -0500 Message-Id: <20180723201748.25573-19-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180723201748.25573-1-mdroth@linux.vnet.ibm.com> References: <20180723201748.25573-1-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4003:c06::235 Subject: [Qemu-devel] [PATCH 18/99] raw: Check byte range uniformly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , qemu-stable@nongnu.org, Stefan Hajnoczi Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Fam Zheng We don't verify the request range against s->size in the I/O callbacks except for raw_co_pwritev. This is inconsistent (especially for raw_co_pwrite_zeroes and raw_co_pdiscard), so fix them, in the meanwhile make the helper reusable by the coming new callbacks. Note that in most cases the block layer already verifies the request byte range against our reported image length, before invoking the driver callbacks. The exception is during image creating, after blk_set_allow_write_beyond_eof(blk, true) is called. But in that case, the requests are not directly from the user or guest. So there is no visible behavior change in adding the check code. The int64_t -> uint64_t inconsistency, as shown by the type casting, is pre-existing due to the interface. Reviewed-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Fam Zheng Message-id: 20180601092648.24614-3-famz@redhat.com Signed-off-by: Stefan Hajnoczi (cherry picked from commit 384455385248762e74a080978f18f0c8f74757fe) Signed-off-by: Michael Roth --- block/raw-format.c | 64 ++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/block/raw-format.c b/block/raw-format.c index a378547c99..17b9d4e052 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -167,16 +167,37 @@ static void raw_reopen_abort(BDRVReopenState *state) state->opaque = NULL; } +/* Check and adjust the offset, against 'offset' and 'size' options. */ +static inline int raw_adjust_offset(BlockDriverState *bs, uint64_t *offset, + uint64_t bytes, bool is_write) +{ + BDRVRawState *s = bs->opaque; + + if (s->has_size && (*offset > s->size || bytes > (s->size - *offset))) { + /* There's not enough space for the write, or the read request is + * out-of-range. Don't read/write anything to prevent leaking out of + * the size specified in options. */ + return is_write ? -ENOSPC : -EINVAL;; + } + + if (*offset > INT64_MAX - s->offset) { + return -EINVAL; + } + *offset += s->offset; + + return 0; +} + static int coroutine_fn raw_co_preadv(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { - BDRVRawState *s = bs->opaque; + int ret; - if (offset > UINT64_MAX - s->offset) { - return -EINVAL; + ret = raw_adjust_offset(bs, &offset, bytes, false); + if (ret) { + return ret; } - offset += s->offset; BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO); return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags); @@ -186,23 +207,11 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags) { - BDRVRawState *s = bs->opaque; void *buf = NULL; BlockDriver *drv; QEMUIOVector local_qiov; int ret; - if (s->has_size && (offset > s->size || bytes > (s->size - offset))) { - /* There's not enough space for the data. Don't write anything and just - * fail to prevent leaking out of the size specified in options. */ - return -ENOSPC; - } - - if (offset > UINT64_MAX - s->offset) { - ret = -EINVAL; - goto fail; - } - if (bs->probed && offset < BLOCK_PROBE_BUF_SIZE && bytes) { /* Handling partial writes would be a pain - so we just * require that guests have 512-byte request alignment if @@ -237,7 +246,10 @@ static int coroutine_fn raw_co_pwritev(BlockDriverState *bs, uint64_t offset, qiov = &local_qiov; } - offset += s->offset; + ret = raw_adjust_offset(bs, &offset, bytes, true); + if (ret) { + goto fail; + } BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO); ret = bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags); @@ -267,22 +279,24 @@ static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes, BdrvRequestFlags flags) { - BDRVRawState *s = bs->opaque; - if (offset > UINT64_MAX - s->offset) { - return -EINVAL; + int ret; + + ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true); + if (ret) { + return ret; } - offset += s->offset; return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags); } static int coroutine_fn raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes) { - BDRVRawState *s = bs->opaque; - if (offset > UINT64_MAX - s->offset) { - return -EINVAL; + int ret; + + ret = raw_adjust_offset(bs, (uint64_t *)&offset, bytes, true); + if (ret) { + return ret; } - offset += s->offset; return bdrv_co_pdiscard(bs->file->bs, offset, bytes); }