From nobody Sat Nov 30 02:48:27 2024 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E39D31D7E33 for ; Fri, 13 Sep 2024 09:39:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726220370; cv=none; b=f1BaaRlzF4PQCXrvC9kIiya9PNRLmKUdv6DWcYNjQumhGGtEC6M7TsLw0LBcOqf5pDfzZXeHfmxyDkaaryBAUqCiYk5TgYlTlnK2CURb90wmAQgCDt1ZJZM0VPOHMavdkDllvHV15vY8AeI+2cdE38L464q/mp1EkR7BZgSpz2o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1726220370; c=relaxed/simple; bh=14Em+5LUfU07AZhRuhVZlV8I2kuQVcaRcYhuB3emakA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BO/c3GespiYYZtqWD2jb6rewj+YCmZBf3EnJcB1Ozmgc2JRGCYxQX6beSvzc4VA0Z9bMI3qDFZgNV6mETFuWspDzajcXJOauygMqT17+t4EFwW+kPSSDgaIlpEI6WiSCdi2p4wcLvu1VabZWAlXWhPx6TEoz4tMLb3sM2gYNR+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com; spf=pass smtp.mailfrom=cloudflare.com; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b=L6C0V1B9; arc=none smtp.client-ip=209.85.221.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cloudflare.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cloudflare.com header.i=@cloudflare.com header.b="L6C0V1B9" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-3770320574aso1379363f8f.2 for ; Fri, 13 Sep 2024 02:39:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloudflare.com; s=google09082023; t=1726220366; x=1726825166; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=8SPUqN3GZrlcNjwE+u8cOJWfk91PGP0vK3hoXybkak4=; b=L6C0V1B9ThCrvHNddoT3ljveUKthVAwHmpOMbVvijk+yXwYtNmcNyorq7uVlnS/XEh I2YxoCo/5/SqWFzdfSvLSdu1rD+e/6HrZm5O6ClpO3KujnXuAUjUvRghtp4nzfs5MvqA B0XmM0avdW7fy2vNtkvckbZ42nK+93NKL+m9OnCBPR6pEvuSMXzNSI4A3Mp7DfnkZ89Z F9/jV66nd5IGX3oOReLmT3dFnADxYDXr7VneQqkap225cS33dXbNtWDYjV4GUN9Yfr1u nvyspk7NYMTVdKHRKEcg7lMmTzZJO9U55IeFyt2CAIh8EmdwGKc3tfQo3qCBa+ZjVbtZ 014g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726220366; x=1726825166; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8SPUqN3GZrlcNjwE+u8cOJWfk91PGP0vK3hoXybkak4=; b=c1JAzuKELd73NwodGDU7eSuQY9okCqqPdSn29UF/RC5YzD6OjCvu4kew80CONM7yFG RLNjo58ZVGbw+8QjNI9pggSCMM3ZldGeB3kpllNtyzLyyvA8U90tnhQFuqAprlA984fg jAVsa9sfANbrSfZincVJDuZXTSLJH8tIrHlL/tapNz/Sj2GcnMxWMqL+Z3Ld3Gs4SIx9 RTI1/mADLgoPCOS9JgzIiBIv/aMFJCiW9nJ+FyIWZLEHi1ne82yXzvsg/bK6XSh8RYkR hrV1MQ4PiUHRV0O7eBo9Z3gLGmTNVIsqRsl1DV3ZeGzUIibRWA2/Z5XSohWnwRfL9ahL RLvg== X-Forwarded-Encrypted: i=1; AJvYcCUIib4izTgULI0x3CNaVrqzT8Wr305WSQH0vdLg8uAvn8hp/gi6psOK6qlY+fI5rlaXpO95TSO9ydjtBW4=@vger.kernel.org X-Gm-Message-State: AOJu0YzGFctqjYLsiBgG9Q5ZmWpDZlazT2p6qZ7dmGnN693o7oRplhla ixwslxD8mHvZcDezeQ44e600CFRC5R7tpLQrPop2qTG6EaYLRo4KY1cbwqnNDfw= X-Google-Smtp-Source: AGHT+IEP6gH+9G56Ca89xPoHtYf+GM04fd32svCb2j76cjibtD28Ka5SMKWWnsCP22WUeZmsjTzWEA== X-Received: by 2002:a05:6000:e09:b0:374:ca92:5e44 with SMTP id ffacd0b85a97d-378c2d121d6mr3535737f8f.32.1726220365954; Fri, 13 Sep 2024 02:39:25 -0700 (PDT) Received: from [127.0.1.1] ([2a09:bac5:3802:d2::15:37a]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-37895665548sm16474484f8f.34.2024.09.13.02.39.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Sep 2024 02:39:25 -0700 (PDT) From: Tiago Lam Date: Fri, 13 Sep 2024 10:39:20 +0100 Subject: [RFC PATCH 2/3] ipv6: Run a reverse sk_lookup on sendmsg. Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20240913-reverse-sk-lookup-v1-2-e721ea003d4c@cloudflare.com> References: <20240913-reverse-sk-lookup-v1-0-e721ea003d4c@cloudflare.com> In-Reply-To: <20240913-reverse-sk-lookup-v1-0-e721ea003d4c@cloudflare.com> To: "David S. Miller" , David Ahern , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Willem de Bruijn , Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Mykola Lysenko , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, linux-kselftest@vger.kernel.org, Jakub Sitnicki , Tiago Lam , kernel-team@cloudflare.com X-Mailer: b4 0.14.1 This follows the same rationale provided for the ipv4 counterpart, where it now runs a reverse socket lookup when source addresses and/or ports are changed, on sendmsg, to check whether egress traffic should be allowed to go through or not. As with ipv4, the ipv6 sendmsg path is also extended here to support the IPV6_ORIGDSTADDR ancilliary message to be able to specify a source address/port. Suggested-by: Jakub Sitnicki Signed-off-by: Tiago Lam --- net/ipv6/datagram.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ net/ipv6/udp.c | 8 ++++-- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index fff78496803d..4214dda1c320 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -756,6 +756,27 @@ void ip6_datagram_recv_ctl(struct sock *sk, struct msg= hdr *msg, } EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl); =20 +static inline bool reverse_sk_lookup(struct flowi6 *fl6, struct sock *sk, + struct in6_addr *saddr, __be16 sport) +{ + if (static_branch_unlikely(&bpf_sk_lookup_enabled) && + (saddr && sport) && + (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, saddr) || inet_sk(sk)->inet_spor= t !=3D sport)) { + struct sock *sk_egress; + + bpf_sk_lookup_run_v6(sock_net(sk), IPPROTO_UDP, &fl6->daddr, fl6->fl6_dp= ort, + saddr, ntohs(sport), 0, &sk_egress); + if (!IS_ERR_OR_NULL(sk_egress) && + atomic64_read(&sk_egress->sk_cookie) =3D=3D atomic64_read(&sk->sk_co= okie)) + return true; + + net_info_ratelimited("No reverse socket lookup match for local addr %pI6= :%d remote addr %pI6:%d\n", + &saddr, ntohs(sport), &fl6->daddr, ntohs(fl6->fl6_dport)); + } + + return false; +} + int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, struct flowi6 *fl6, struct ipcm6_cookie *ipc6) @@ -844,7 +865,62 @@ int ip6_datagram_send_ctl(struct net *net, struct sock= *sk, =20 break; } + case IPV6_ORIGDSTADDR: + { + struct sockaddr_in6 *sockaddr_in; + struct net_device *dev =3D NULL; + + if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct sockaddr_in6))) { + err =3D -EINVAL; + goto exit_f; + } + + sockaddr_in =3D (struct sockaddr_in6 *)CMSG_DATA(cmsg); + + addr_type =3D __ipv6_addr_type(&sockaddr_in->sin6_addr); + + if (addr_type & IPV6_ADDR_LINKLOCAL) + return -EINVAL; + + /* If we're egressing with a different source address and/or port, we + * perform a reverse socket lookup. The rationale behind this is that = we + * can allow return UDP traffic that has ingressed through sk_lookup to + * also egress correctly. In case the reverse lookup fails, we + * continue with the normal path. + * + * The lookup is performed if either source address and/or port changed= , and + * neither is "0". + */ + if (reverse_sk_lookup(fl6, sk, &sockaddr_in->sin6_addr, + sockaddr_in->sin6_port)) { + /* Override the source port and address to use with the one we + * got in cmsg and bail early. + */ + fl6->saddr =3D sockaddr_in->sin6_addr; + fl6->fl6_sport =3D sockaddr_in->sin6_port; + break; + } =20 + if (addr_type !=3D IPV6_ADDR_ANY) { + int strict =3D __ipv6_addr_src_scope(addr_type) <=3D IPV6_ADDR_SCOPE_L= INKLOCAL; + + if (!ipv6_can_nonlocal_bind(net, inet_sk(sk)) && + !ipv6_chk_addr_and_flags(net, + &sockaddr_in->sin6_addr, + dev, !strict, 0, + IFA_F_TENTATIVE) && + !ipv6_chk_acast_addr_src(net, dev, + &sockaddr_in->sin6_addr)) + err =3D -EINVAL; + else + fl6->saddr =3D sockaddr_in->sin6_addr; + } + + if (err) + goto exit_f; + + break; + } case IPV6_FLOWINFO: if (cmsg->cmsg_len < CMSG_LEN(4)) { err =3D -EINVAL; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 6602a2e9cdb5..6121cbb71ad3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1476,6 +1476,12 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *ms= g, size_t len) =20 fl6->flowi6_uid =3D sk->sk_uid; =20 + /* We use fl6's daddr and fl6_sport in the reverse sk_lookup done + * within ip6_datagram_send_ctl() now. + */ + fl6->daddr =3D *daddr; + fl6->fl6_sport =3D inet->inet_sport; + if (msg->msg_controllen) { opt =3D &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); @@ -1511,10 +1517,8 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *ms= g, size_t len) =20 fl6->flowi6_proto =3D sk->sk_protocol; fl6->flowi6_mark =3D ipc6.sockc.mark; - fl6->daddr =3D *daddr; if (ipv6_addr_any(&fl6->saddr) && !ipv6_addr_any(&np->saddr)) fl6->saddr =3D np->saddr; - fl6->fl6_sport =3D inet->inet_sport; =20 if (cgroup_bpf_enabled(CGROUP_UDP6_SENDMSG) && !connected) { err =3D BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, --=20 2.34.1