From patchwork Wed Dec 21 12:27:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Frederic Sowa X-Patchwork-Id: 707795 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3tkDSH51Qzz9syB for ; Wed, 21 Dec 2016 23:27:27 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=stressinduktion.org header.i=@stressinduktion.org header.b="SYZbxiEq"; dkim=pass (1024-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="UUhXlL2N"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934952AbcLUM1V (ORCPT ); Wed, 21 Dec 2016 07:27:21 -0500 Received: from out1-smtp.messagingengine.com ([66.111.4.25]:60292 "EHLO out1-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752933AbcLUM1T (ORCPT ); Wed, 21 Dec 2016 07:27:19 -0500 Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id A8B86207C6; Wed, 21 Dec 2016 07:27:18 -0500 (EST) Received: from frontend2 ([10.202.2.161]) by compute7.internal (MEProxy); Wed, 21 Dec 2016 07:27:18 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= stressinduktion.org; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s= mesmtp; bh=oicG9o8R2KByHjKJWsOBBX3sMuQ=; b=SYZbxiEqvhQgUrsMCv9u5 8Oe0GP5AbPP1HSZSNpsmMeS89DLKUN9N8wSAYA6A+ziivPBXmvuweEJZmIkEbo8l UiG0wydrj5KvMsBdtFy913MQCA4fchnKH3Bqd7OnQ9uHWHiEt7b2bQfTq1WqM/Ya EMQWoraIEcXqwDMZfELAfk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc:x-sasl-enc; s= smtpout; bh=oicG9o8R2KByHjKJWsOBBX3sMuQ=; b=UUhXlL2NWqt13+Vc98xN FepKQwZ/JwBVKo795Z4aEOS+nVz9AhRAmCsG8Rqj/mfRAssbH1C41OtobW/S5K68 yyjYiuzP+82iw5M8jBn/jw9xwlwbnhtfTNCOIVYxjD573XqL3LTrKJST9QXQYNvA nOcKOGPMlZPslQhh221a7po= X-ME-Sender: X-Sasl-enc: ebkav/n46or62eLatXyNyY4I3ff8lOenjs7Yi6OTJtju 1482323238 Received: from [172.20.10.11] (unknown [213.55.176.163]) by mail.messagingengine.com (Postfix) with ESMTPA id AEAEA2442C; Wed, 21 Dec 2016 07:27:17 -0500 (EST) Message-ID: <1482323232.2260.2.camel@stressinduktion.org> Subject: Re: ipv6: handle -EFAULT from skb_copy_bits From: Hannes Frederic Sowa To: Cong Wang , Dave Jones Cc: David Miller , Linux Kernel Network Developers Date: Wed, 21 Dec 2016 13:27:12 +0100 In-Reply-To: References: <20161219.144848.736886978545428136.davem@davemloft.net> <20161220003144.omoqyghgdfbxdyuu@codemonkey.org.uk> <20161220004013.43pcopemc6im32az@codemonkey.org.uk> <20161219.203623.119653805184192345.davem@davemloft.net> <20161220181728.dd2cynjwrceruwcu@codemonkey.org.uk> <20161220221214.w3zerfiy4wu6apee@codemonkey.org.uk> X-Mailer: Evolution 3.22.3 (3.22.3-1.fc25) Mime-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Tue, 2016-12-20 at 22:09 -0800, Cong Wang wrote: > On Tue, Dec 20, 2016 at 2:12 PM, Dave Jones wrote: > > fd = socket(AF_INET6, SOCK_RAW, 7); > > > > setsockopt(fd, SOL_IPV6, IPV6_CHECKSUM, &zero, 4); > > setsockopt(fd, SOL_IPV6, IPV6_DSTOPTS, &buf, LEN); > > > > Interesting, you set the checksum offset to be 0, but the packet size > is actually 49, transport header is located at offset 48, so apparently > the packet doesn't have room for a 16bit checksum after network header. > > Your original patch seems reasonable to me, unless there is some > check in __ip6_append_data() which is supposed to catch this, but > CHECKSUM is specific to raw socket only. The calculation of total_len is wrong here: total_len = inet_sk(sk)->cork.base.length; if (offset >= total_len - 1) { err = -EINVAL; ip6_flush_pending_frames(sk); goto out; } At least for this bug to fix we need to subtract the extension header length after the fragmentation header, so: --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -536,6 +536,17 @@ static int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, goto out; } +static unsigned int raw6_corked_transport_len(const struct sock *sk) +{ + unsigned int len = inet_sk(sk)->cork.base.length; + struct ipv6_txoptions *opt = inet6_sk(sk)->cork.opt; + + if (likely(!opt)) + return len; + + return len - opt->opt_flen; +} + static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct raw6_sock *rp) { @@ -543,7 +554,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, int err = 0; int offset; int len; - int total_len; + int transport_len; __wsum tmp_csum; __sum16 csum; @@ -555,8 +566,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, goto out; offset = rp->offset; - total_len = inet_sk(sk)->cork.base.length; - if (offset >= total_len - 1) { + transport_len = raw6_corked_transport_len(sk); + if (offset >= transport_len - 1) { err = -EINVAL; ip6_flush_pending_frames(sk); goto out; @@ -598,7 +609,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); csum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, - total_len, fl6->flowi6_proto, tmp_csum); + transport_len, fl6->flowi6_proto, tmp_csum); if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) csum = CSUM_MANGLED_0;