Received: by 10.223.185.116 with SMTP id b49csp1086468wrg; Fri, 23 Feb 2018 11:41:09 -0800 (PST) X-Google-Smtp-Source: AH8x226vx6GTeHwRKrQZH5weFDq+8lPsOihetz4vRlXAQUaB+BVZtVYNXYF4WpYPRbgOC6FGarWx X-Received: by 2002:a17:902:6f17:: with SMTP id w23-v6mr2695350plk.336.1519414869856; Fri, 23 Feb 2018 11:41:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519414869; cv=none; d=google.com; s=arc-20160816; b=wdpxIrM7ZWxp0MhkIpTxFpdnnFItAYnh6rxhahob85d/NCTnUG4tvaexW+Lbcg8Us9 KQr+7DkLPIQHMpJcrZ6OGSTwEoI9A2eDrHWbtWs5cQT6z5DeIoFfczu142Gzn0YneUEe s+D6L8lavOuf+/2ksUxCpU97beDLrlLtoiNlFjMPGSW7fMLIEgTIyrS7SIkmZpFRnkNM x3ILIyKJ15dgX3LyuuhCidopF9OGFKRYONaUd+7YenD/lbevEcMcks85c+yXmJHHFFdD mAOp920OcAQu9jP+z2yGIEoeUuig1vmE2gxOZY1Cfg9Qw3QR1vQBjIf5bKyLqwOjlM9V q67A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=dteXsPpF51qloexJ6WpxCE8xtyRp0PeLtF+1+7sOBn8=; b=h8FzdWUmXTeFOBYj3TCoWmOe/bXJnUkhYislPMci3N4JQb+2VFuBi+OQB1tFW0GEKy cJiWKV1A1NL4KfPeHH7ScjJmAkdLofwRWuXUl2w+240Rn7IvYkZjc6LNUcLqdboFQNd3 1v5VYDTlkP7JC8z92eFV4Z2WMvkKmUdNzw66F03heQrVEb9PkzzSVCut7aUB5ih76yad zSYiOtaqybZwhu6tMbRO+SQAW47w+FrS+R5sHIHDsRWJxKAwyXvMoip/fKhEmavU4OfL 9J8EEuQR+b9riligGGydnhF+G6UHwpZUQm5BkanNf0uAC7vMMNpi7Eaq+LWA4RtDZuow n9/Q== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s19si2239797pfk.260.2018.02.23.11.40.55; Fri, 23 Feb 2018 11:41:09 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934597AbeBWStr (ORCPT + 99 others); Fri, 23 Feb 2018 13:49:47 -0500 Received: from mail.linuxfoundation.org ([140.211.169.12]:45414 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934578AbeBWStn (ORCPT ); Fri, 23 Feb 2018 13:49:43 -0500 Received: from localhost (LFbn-1-12258-90.w90-92.abo.wanadoo.fr [90.92.71.90]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 10DC511B0; Fri, 23 Feb 2018 18:49:42 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Marcelo Ricardo Leitner , Hangbin Liu , Xin Long , "David S. Miller" Subject: [PATCH 4.14 017/159] sctp: set frag_point in sctp_setsockopt_maxseg correctly Date: Fri, 23 Feb 2018 19:25:25 +0100 Message-Id: <20180223170745.310285813@linuxfoundation.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180223170743.086611315@linuxfoundation.org> References: <20180223170743.086611315@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Xin Long commit ecca8f88da5c4260cc2bccfefd2a24976704c366 upstream. Now in sctp_setsockopt_maxseg user_frag or frag_point can be set with val >= 8 and val <= SCTP_MAX_CHUNK_LEN. But both checks are incorrect. val >= 8 means frag_point can even be less than SCTP_DEFAULT_MINSEGMENT. Then in sctp_datamsg_from_user(), when it's value is greater than cookie echo len and trying to bundle with cookie echo chunk, the first_len will overflow. The worse case is when it's value is equal as cookie echo len, first_len becomes 0, it will go into a dead loop for fragment later on. In Hangbin syzkaller testing env, oom was even triggered due to consecutive memory allocation in that loop. Besides, SCTP_MAX_CHUNK_LEN is the max size of the whole chunk, it should deduct the data header for frag_point or user_frag check. This patch does a proper check with SCTP_DEFAULT_MINSEGMENT subtracting the sctphdr and datahdr, SCTP_MAX_CHUNK_LEN subtracting datahdr when setting frag_point via sockopt. It also improves sctp_setsockopt_maxseg codes. Suggested-by: Marcelo Ricardo Leitner Reported-by: Hangbin Liu Signed-off-by: Xin Long Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/sctp/sctp.h | 3 ++- net/sctp/socket.c | 29 +++++++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -444,7 +444,8 @@ static inline int sctp_frag_point(const if (asoc->user_frag) frag = min_t(int, frag, asoc->user_frag); - frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN)); + frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN - + sizeof(struct sctp_data_chunk))); return frag; } --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3136,9 +3136,9 @@ static int sctp_setsockopt_mappedv4(stru */ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) { + struct sctp_sock *sp = sctp_sk(sk); struct sctp_assoc_value params; struct sctp_association *asoc; - struct sctp_sock *sp = sctp_sk(sk); int val; if (optlen == sizeof(int)) { @@ -3154,26 +3154,35 @@ static int sctp_setsockopt_maxseg(struct if (copy_from_user(¶ms, optval, optlen)) return -EFAULT; val = params.assoc_value; - } else + } else { return -EINVAL; + } - if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))) - return -EINVAL; + if (val) { + int min_len, max_len; - asoc = sctp_id2assoc(sk, params.assoc_id); - if (!asoc && params.assoc_id && sctp_style(sk, UDP)) - return -EINVAL; + min_len = SCTP_DEFAULT_MINSEGMENT - sp->pf->af->net_header_len; + min_len -= sizeof(struct sctphdr) + + sizeof(struct sctp_data_chunk); + + max_len = SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_data_chunk); + if (val < min_len || val > max_len) + return -EINVAL; + } + + asoc = sctp_id2assoc(sk, params.assoc_id); if (asoc) { if (val == 0) { - val = asoc->pathmtu; - val -= sp->pf->af->net_header_len; + val = asoc->pathmtu - sp->pf->af->net_header_len; val -= sizeof(struct sctphdr) + - sizeof(struct sctp_data_chunk); + sizeof(struct sctp_data_chunk); } asoc->user_frag = val; asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu); } else { + if (params.assoc_id && sctp_style(sk, UDP)) + return -EINVAL; sp->user_frag = val; }