Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp5597217img; Wed, 27 Mar 2019 11:23:23 -0700 (PDT) X-Google-Smtp-Source: APXvYqzcOYaERHT4HIdXpwQ/LYia6KXBTVkCPJow+Kp/OEMlxxwU9R7qETvzyDRk/1WA2GFPdSnS X-Received: by 2002:a17:902:703:: with SMTP id 3mr5269973pli.224.1553711003879; Wed, 27 Mar 2019 11:23:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553711003; cv=none; d=google.com; s=arc-20160816; b=BlTxVbEv2YLJyVbtzvQWlOvMyJP/jXt/VcnC5d7yWXJj2d/fyRXgjfc1goPqS41i0h t5jx3aIfmI3HB+znINtlCfD0WZ6khMYw242vQ0AlwyTbMLbEsh3ZzMp9SOjUomb6o9Y1 RK8mDry6zfbcpzD72DLg3MwGigxzQwcb2TibX8nryfHmDehRIV3JLDfZELj+ixObIRFL yLKCQAlMk7QHzEeH0YYc5yiegtDxmUKKaKFe5W3AygV+OdKZxWufNu+wJYllIuh4PxVB M8L0xAlHqA7j6Je+KZcZqoucvJFhzH89UfVctsK52A8TXnEMOAfBSal92n7V/FORTYh/ RA+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=mjByGZq56lY5ljTrDA1zm9SqjcNwLIL35rE26+6ECZk=; b=PdElaKM95b5FSOc/+CSOpwhgAn2ZvHu/zDgwRQJVGYet1UUd8DXNLa7nV6jGi15sRS q2jvBF3QTJkfX48rnDubN9CBPqJopK3x+/9QU1QLmAXIhEbTaCobPbI6TJkH20c7Ch4y sWMqJ2tw3uHaVtvxGgP7RCP1iu20bHw3RnSQZdwIRS9PVkX98xWqqmUgg53RXqXuXzgb zGALhi71Cvj2POMwTnRmGoJI625bUna7S9pSAXv6PRhH+pSSuN588hMV2B01ILMqOzgY JWE6xG/GRrh8PYalfXE2As7ouaF99arFBWt3HydkpzRve+et1sl6koVF/HklSYnBiLFF 2Pyg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bsiWDPHL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b5si19209916plx.64.2019.03.27.11.23.08; Wed, 27 Mar 2019 11:23:23 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=bsiWDPHL; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391131AbfC0SVT (ORCPT + 99 others); Wed, 27 Mar 2019 14:21:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:39148 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391118AbfC0SVS (ORCPT ); Wed, 27 Mar 2019 14:21:18 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 1987F20651; Wed, 27 Mar 2019 18:21:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1553710877; bh=iN4MjlgVncUEJlNHijfSXSeSk/aW+uo9xn2V4+xe4GE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bsiWDPHLbPcvdl56k0FGKDge8YyC7ZtrjB0ZYeUgMFlfqQzVxzegQM30ezbbteEK4 s/pyTh53n8idHOdHHX8utBDGkonKD0vPYX8xGUKd0c4+w+e2V9lMfclTZgt05oB481 79rB1B5rk52QhFI+fuX1ACZdveurQHjDPK0XNL80= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Carlos Maiolino , Jens Axboe , Sasha Levin , linux-fsdevel@vger.kernel.org Subject: [PATCH AUTOSEL 4.9 22/87] fs: fix guard_bio_eod to check for real EOD errors Date: Wed, 27 Mar 2019 14:19:35 -0400 Message-Id: <20190327182040.17444-22-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190327182040.17444-1-sashal@kernel.org> References: <20190327182040.17444-1-sashal@kernel.org> MIME-Version: 1.0 X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Carlos Maiolino [ Upstream commit dce30ca9e3b676fb288c33c1f4725a0621361185 ] guard_bio_eod() can truncate a segment in bio to allow it to do IO on odd last sectors of a device. It already checks if the IO starts past EOD, but it does not consider the possibility of an IO request starting within device boundaries can contain more than one segment past EOD. In such cases, truncated_bytes can be bigger than PAGE_SIZE, and will underflow bvec->bv_len. Fix this by checking if truncated_bytes is lower than PAGE_SIZE. This situation has been found on filesystems such as isofs and vfat, which doesn't check the device size before mount, if the device is smaller than the filesystem itself, a readahead on such filesystem, which spans EOD, can trigger this situation, leading a call to zero_user() with a wrong size possibly corrupting memory. I didn't see any crash, or didn't let the system run long enough to check if memory corruption will be hit somewhere, but adding instrumentation to guard_bio_end() to check truncated_bytes size, was enough to see the error. The following script can trigger the error. MNT=/mnt IMG=./DISK.img DEV=/dev/loop0 mkfs.vfat $IMG mount $IMG $MNT cp -R /etc $MNT &> /dev/null umount $MNT losetup -D losetup --find --show --sizelimit 16247280 $IMG mount $DEV $MNT find $MNT -type f -exec cat {} + >/dev/null Kudos to Eric Sandeen for coming up with the reproducer above Reviewed-by: Ming Lei Signed-off-by: Carlos Maiolino Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- fs/buffer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/buffer.c b/fs/buffer.c index e0d46d47e358..a89be9741d12 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3041,6 +3041,13 @@ void guard_bio_eod(int op, struct bio *bio) /* Uhhuh. We've got a bio that straddles the device size! */ truncated_bytes = bio->bi_iter.bi_size - (maxsector << 9); + /* + * The bio contains more than one segment which spans EOD, just return + * and let IO layer turn it into an EIO + */ + if (truncated_bytes > bvec->bv_len) + return; + /* Truncate the bio.. */ bio->bi_iter.bi_size -= truncated_bytes; bvec->bv_len -= truncated_bytes; -- 2.19.1