From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-eopbgr720093.outbound.protection.outlook.com ([40.107.72.93]:21257 "EHLO NAM05-CO1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1731150AbeIXUuz (ORCPT ); Mon, 24 Sep 2018 16:50:55 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Daniel Borkmann , Alexei Starovoitov , Sasha Levin Subject: [PATCH AUTOSEL 4.18 28/76] bpf: fix shift upon scatterlist ring wrap-around in bpf_msg_pull_data Date: Mon, 24 Sep 2018 14:48:18 +0000 Message-ID: <20180924144751.164410-28-alexander.levin@microsoft.com> References: <20180924144751.164410-1-alexander.levin@microsoft.com> In-Reply-To: <20180924144751.164410-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Daniel Borkmann [ Upstream commit 2e43f95dd8ee62bc8bf57f2afac37fbd70c8d565 ] If first_sg and last_sg wraps around in the scatterlist ring, then we need to account for that in the shift as well. E.g. crafting such msgs where this is the case leads to a hang as shift becomes negative. E.g. consider the following scenario: first_sg :=3D 14 |=3D> shift :=3D -12 msg->sg_start :=3D 10 last_sg :=3D 3 | msg->sg_end :=3D 5 round 1: i :=3D 15, move_from :=3D 3, sg[15] :=3D sg[ 3] round 2: i :=3D 0, move_from :=3D -12, sg[ 0] :=3D sg[-12] round 3: i :=3D 1, move_from :=3D -11, sg[ 1] :=3D sg[-11] round 4: i :=3D 2, move_from :=3D -10, sg[ 2] :=3D sg[-10] [...] round 13: i :=3D 11, move_from :=3D -1, sg[ 2] :=3D sg[ -1] round 14: i :=3D 12, move_from :=3D 0, sg[ 2] :=3D sg[ 0] round 15: i :=3D 13, move_from :=3D 1, sg[ 2] :=3D sg[ 1] round 16: i :=3D 14, move_from :=3D 2, sg[ 2] :=3D sg[ 2] round 17: i :=3D 15, move_from :=3D 3, sg[ 2] :=3D sg[ 3] [...] This means we will loop forever and never hit the msg->sg_end condition to break out of the loop. When we see that the ring wraps around, then the shift should be MAX_SKB_FRAGS - first_sg + last_sg - 1. Meaning, the remainder slots from the tail of the ring and the head until last_sg combined. Fixes: 015632bb30da ("bpf: sk_msg program helper bpf_sk_msg_pull_data") Signed-off-by: Daniel Borkmann Acked-by: John Fastabend Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- net/core/filter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index e713a8791815..cc4d660aafe1 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2360,7 +2360,10 @@ BPF_CALL_4(bpf_msg_pull_data, * had a single entry though we can just replace it and * be done. Otherwise walk the ring and shift the entries. */ - shift =3D last_sg - first_sg - 1; + WARN_ON_ONCE(last_sg =3D=3D first_sg); + shift =3D last_sg > first_sg ? + last_sg - first_sg - 1 : + MAX_SKB_FRAGS - first_sg + last_sg - 1; if (!shift) goto out; =20 --=20 2.17.1