Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp305430pxx; Wed, 28 Oct 2020 05:30:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJybSZrjww7uesVtbcVRLGy2GDyQU6IIVsp7xaFxgPfEIDybFsJ2Dh1Gz5VBeK3XB9bEJYIz X-Received: by 2002:aa7:d992:: with SMTP id u18mr7319111eds.284.1603888221019; Wed, 28 Oct 2020 05:30:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603888221; cv=none; d=google.com; s=arc-20160816; b=FT9ntGHBnfe+Nefs6HiJZNIaHRTJAxLBsKTrbSILsK35CWe3BooXFq5iitp3oWvXdZ RBv2/xUoSuhFmKHKGAB/6BuOVenZPvEkEiCxeS+izjDuaZrzz2dhafd1N3k8yQyv6ahc OMrhHGthAvdWIh494xFyKPOIjwc4RFyBhUMw5j/LFJmyOPfIj1m9/gWJowLy07lJpH6n mUr0yWhh5+12OLO0tPMCz1CfQo6ZQKSCHxrRH4LgdBIkynoZdyF9q6rNR0RH7LyE+aO3 s2JPodA6+vLeMRzI3C12OXwhRzMwuug3i/QXEcxeFj8mXTt2eUYlvlmtV/8WfKbKgDX9 /jUA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=wy47JojnjV72jEkDQWbfhiV9/3KNuux9V0GHLeh+TPU=; b=vxch3TK17uYoThaHxFgzN7W19CA8VRerSUBdn7YfZMHvnM9yky3NQYeVjspuUBgUT6 evQOmnm2/pLClaBarrcQnyTRC1F2OTuA4T21iMsFqr/YTkYaUHIEaS3kI5pjX05GC1U7 xoFG9RGtio/EHONrqxUIfejsKPu5xtCfSflaw60+jMzm8rFM+28Nx+1jB/McCTgZF0WU LGKhXHzMUAYRpOkj1bP1TdrGoIFoG+/GPDBBZEZ1TGDTA3ZWSe2a/c6y/GJuCGb8W+vt N35fBjLS1uQ3U9ijVQ4gbXIbWp1A+JubDDMTd58yLtl2FivxI5kx4eFfcmJW956dgqlk 116Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=h3Ob7HBI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id dk22si2709939edb.258.2020.10.28.05.29.59; Wed, 28 Oct 2020 05:30:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=h3Ob7HBI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1797124AbgJ0PVm (ORCPT + 99 others); Tue, 27 Oct 2020 11:21:42 -0400 Received: from mail.kernel.org ([198.145.29.99]:56956 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1796544AbgJ0PTS (ORCPT ); Tue, 27 Oct 2020 11:19:18 -0400 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2936021527; Tue, 27 Oct 2020 15:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1603811957; bh=R5Ah/Z4m1Y4HfCobwLE2cMeMwWKUGcMx0fkl35sJ05U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h3Ob7HBIbE8t/Ba7MardaMJ3Ihz7HMREUtHUDi7DbQzeCEFzygZ8zvACMMq2w7LqO Rl+FgKkCkhFLRFKQCN911xGMoO8XVGQC5YgORZgtpd2r2aYilTX7yxnSRdtZDtkAR9 tHbxyxyprWPZqSQwTacdEPh+rRsmXR9M8/mVpW94= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alexei Starovoitov , Vasily Averin , Yonghong Song , Martin KaFai Lau , Andrii Nakryiko , Jakub Kicinski Subject: [PATCH 5.9 011/757] net: fix pos incrementment in ipv6_route_seq_next Date: Tue, 27 Oct 2020 14:44:21 +0100 Message-Id: <20201027135451.058382477@linuxfoundation.org> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027135450.497324313@linuxfoundation.org> References: <20201027135450.497324313@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Yonghong Song [ Upstream commit 6617dfd440149e42ce4d2be615eb31a4755f4d30 ] Commit 4fc427e05158 ("ipv6_route_seq_next should increase position index") tried to fix the issue where seq_file pos is not increased if a NULL element is returned with seq_ops->next(). See bug https://bugzilla.kernel.org/show_bug.cgi?id=206283 The commit effectively does: - increase pos for all seq_ops->start() - increase pos for all seq_ops->next() For ipv6_route, increasing pos for all seq_ops->next() is correct. But increasing pos for seq_ops->start() is not correct since pos is used to determine how many items to skip during seq_ops->start(): iter->skip = *pos; seq_ops->start() just fetches the *current* pos item. The item can be skipped only after seq_ops->show() which essentially is the beginning of seq_ops->next(). For example, I have 7 ipv6 route entries, root@arch-fb-vm1:~/net-next dd if=/proc/net/ipv6_route bs=4096 00000000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000001 00000000 00000001 eth0 fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000001 00000000 00000001 eth0 00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo 00000000000000000000000000000001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000003 00000000 80200001 lo fe800000000000002050e3fffebd3be8 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000002 00000000 80200001 eth0 ff000000000000000000000000000000 08 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000004 00000000 00000001 eth0 00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo 0+1 records in 0+1 records out 1050 bytes (1.0 kB, 1.0 KiB) copied, 0.00707908 s, 148 kB/s root@arch-fb-vm1:~/net-next In the above, I specify buffer size 4096, so all records can be returned to user space with a single trip to the kernel. If I use buffer size 128, since each record size is 149, internally kernel seq_read() will read 149 into its internal buffer and return the data to user space in two read() syscalls. Then user read() syscall will trigger next seq_ops->start(). Since the current implementation increased pos even for seq_ops->start(), it will skip record #2, #4 and #6, assuming the first record is #1. root@arch-fb-vm1:~/net-next dd if=/proc/net/ipv6_route bs=128 00000000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000400 00000001 00000000 00000001 eth0 00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo fe800000000000002050e3fffebd3be8 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000002 00000000 80200001 eth0 00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 00000000 00200200 lo 4+1 records in 4+1 records out 600 bytes copied, 0.00127758 s, 470 kB/s To fix the problem, create a fake pos pointer so seq_ops->start() won't actually increase seq_file pos. With this fix, the above `dd` command with `bs=128` will show correct result. Fixes: 4fc427e05158 ("ipv6_route_seq_next should increase position index") Cc: Alexei Starovoitov Suggested-by: Vasily Averin Reviewed-by: Vasily Averin Signed-off-by: Yonghong Song Acked-by: Martin KaFai Lau Acked-by: Andrii Nakryiko Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/ipv6/ip6_fib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -2618,8 +2618,10 @@ static void *ipv6_route_seq_start(struct iter->skip = *pos; if (iter->tbl) { + loff_t p = 0; + ipv6_route_seq_setup_walk(iter, net); - return ipv6_route_seq_next(seq, NULL, pos); + return ipv6_route_seq_next(seq, NULL, &p); } else { return NULL; }