`4.18-stable review patch.  If anyone has any objections, please let me know.------------------From: Daniel Borkmann <daniel@iogearbox.net>[ Upstream commit 2e43f95dd8ee62bc8bf57f2afac37fbd70c8d565 ]If first_sg and last_sg wraps around in the scatterlist ring, then weneed to account for that in the shift as well. E.g. crafting such msgswhere this is the case leads to a hang as shift becomes negative. E.g.consider the following scenario:  first_sg := 14     |=>    shift := -12     msg->sg_start := 10  last_sg  :=  3     |                       msg->sg_end   :=  5round  1:  i := 15, move_from :=   3, sg[15] := sg[  3]round  2:  i :=  0, move_from := -12, sg[ 0] := sg[-12]round  3:  i :=  1, move_from := -11, sg[ 1] := sg[-11]round  4:  i :=  2, move_from := -10, sg[ 2] := sg[-10][...]round 13:  i := 11, move_from :=  -1, sg[ 2] := sg[ -1]round 14:  i := 12, move_from :=   0, sg[ 2] := sg[  0]round 15:  i := 13, move_from :=   1, sg[ 2] := sg[  1]round 16:  i := 14, move_from :=   2, sg[ 2] := sg[  2]round 17:  i := 15, move_from :=   3, sg[ 2] := sg[  3][...]This means we will loop forever and never hit the msg->sg_end conditionto break out of the loop. When we see that the ring wraps around, thenthe 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_sgcombined.Fixes: 015632bb30da ("bpf: sk_msg program helper bpf_sk_msg_pull_data")Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>Acked-by: John Fastabend <john.fastabend@gmail.com>Signed-off-by: Alexei Starovoitov <ast@kernel.org>Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>--- net/core/filter.c |    5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)--- 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 = last_sg - first_sg - 1;+	WARN_ON_ONCE(last_sg == first_sg);+	shift = last_sg > first_sg ?+		last_sg - first_sg - 1 :+		MAX_SKB_FRAGS - first_sg + last_sg - 1; 	if (!shift) 		goto out; `