Received: by 2002:a05:6358:3188:b0:123:57c1:9b43 with SMTP id q8csp487691rwd; Wed, 31 May 2023 00:52:09 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5kmgNb4mfqRA69pDGsWuQFPKH1Jd9RTs4NZXZNlq0hO9b6XCc7hJ12tGlVCYQsAI66jGpb X-Received: by 2002:a17:90b:38cf:b0:247:afed:6d62 with SMTP id nn15-20020a17090b38cf00b00247afed6d62mr5032014pjb.46.1685519528733; Wed, 31 May 2023 00:52:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685519528; cv=none; d=google.com; s=arc-20160816; b=RJblQ84FXAw4EfZRsF5xQ4E+8MpGbFj0qJ/VKgr432ZJYqyaVjS8pah3bmC5E29tS3 5iKd+ReUIbN46Hhlp/xCIZmPLiWcOXmkxVCWoLPob9GBAo9f8h4j37atRiyEdsTtFBG8 5Z+qVPyeyRksiOSG8qINmCGEHqLjwj1D7cixPHPpJZiee+vqQRoN63pVYwTn3mit/JK0 WNvmOlz9PCROFNXSGD5UFaGqRcVWWELtOuGQUjUG9BiI4a3YOAKQZFTEkMPfg0JNaiGw AZ1gcxjayFGn9EsVgeF9oef9293pAOEuFO7KnmUpB1Q6cA22TxT9D+O+gzO1m/pyNndG HhmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=+tRSEdxP8IM2jGH9SQvtWqET/153WHbcp/+/2iayQMU=; b=ytoMUulgg1BQXvGsbJmsaa4kaZ/qqW/3HkhJGEJC5i7PFCNu4KHxp08hul62gG3vJq 2mO+LNrJmNgexCItGVVKNxevtQ1V2lvRjCGWi5OclgOy7SNfamZ/fp/WztUTXQAMecNl ZhwDLLM3yCLjHUS/kIQTTRFjlcXQwgn5XYKJfwwSaKePLVWbwN07cwedbSBjcRmRp0qE s5fSL1AWuieAsXyYsKuycnwL15SxXhCt9LtirK8jr2LRHxNeCx1aoPzxElbL6uhe+/Ix scl3ysu//VcImV8PPElv/pJxEXhwvvIjxdHoT42IbLqPr9SkWkt++gLVOJNbJljr8D/O gOmg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YXbMxXdW; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n90-20020a17090a5ae300b002586dbee167si493172pji.170.2023.05.31.00.51.47; Wed, 31 May 2023 00:52:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=YXbMxXdW; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231785AbjEaHsW (ORCPT + 99 others); Wed, 31 May 2023 03:48:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234758AbjEaHsU (ORCPT ); Wed, 31 May 2023 03:48:20 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 71C54125 for ; Wed, 31 May 2023 00:48:17 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-30aea656e36so2495129f8f.1 for ; Wed, 31 May 2023 00:48:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1685519296; x=1688111296; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=+tRSEdxP8IM2jGH9SQvtWqET/153WHbcp/+/2iayQMU=; b=YXbMxXdWgXfUU0qf80s17Bl0IXn2Mnyry5L1rrzIdyXr3fLNdZCXDGRehczX0f16VP bRBIEGNElh8ih3eLiHyFGF1LIxYeY4J2BT+vd2c2CXwVadyYRWh/dpUmLwCAHeEuWB2H bgEEoFZ0XujkJfdKZbc61voLWN+nrcT2vxLK8lCAya/kyjZ+qcFpfUTLqg0MWZgt+pms r4I2n7bXr0impDYuk8TngNUPYJJtzBl7U2bTb7q9WIyqoBQMil7u+hQ2IV9O8oq/pCcC YQpcxb4Z9vSlB6kQa/jjczflaR+190dcR/sINyQ6iMmbDibLluP4TUjv40cGcbvreu8h CerA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685519296; x=1688111296; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=+tRSEdxP8IM2jGH9SQvtWqET/153WHbcp/+/2iayQMU=; b=YWBLhMp6v8p96x/T3jzKPV4BU18335ln57g1sjWxT/FmXYjhO/qAz7ikuXREW4WDZN qNt4YLoJBbxBnhaUQ1IvzOLZ4lHMa+FhRLPs4qChIfR3gqcQvx8gVa9SVi8oV9RO7DhF gJN0NmkwSU186hKZx6hnoRp7uty7s4L0Hqa9d5fz7n/yPhP6wjC1To2VGZ4KfxjoN+Tk JIpaljbeaD/Vv1EvIfPiP03qGc1PhG9AR7+9v06xkQnqrpkt9NmSi4DNt7EbqCsdzEVP yNxbYJ26ElQdaoDEcwb3RErrTdn8fw5gTYPkFqlWEkPDYK9PRdHl3szskxwMR64RvJwc ypEg== X-Gm-Message-State: AC+VfDwmJ5TyMwaTtDqxuJuf5tb+TL/VYR0WqxuU/h2lmGF84FSMScwJ 02ICFoWZaWWW8ud1ygPoynmtQg== X-Received: by 2002:a05:6000:1245:b0:306:297b:927f with SMTP id j5-20020a056000124500b00306297b927fmr3203075wrx.25.1685519295779; Wed, 31 May 2023 00:48:15 -0700 (PDT) Received: from localhost ([102.36.222.112]) by smtp.gmail.com with ESMTPSA id b17-20020adff251000000b002c71b4d476asm5757981wrp.106.2023.05.31.00.48.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 31 May 2023 00:48:13 -0700 (PDT) Date: Wed, 31 May 2023 10:48:09 +0300 From: Dan Carpenter To: NeilBrown Cc: Stanislav Kinsbursky , Chuck Lever , Jeff Layton , Trond Myklebust , Anna Schumaker , "J. Bruce Fields" , linux-nfs@vger.kernel.org, netdev@vger.kernel.org, kernel-janitors@vger.kernel.org Subject: Re: [PATCH] nfsd: fix double fget() bug in __write_ports_addfd() Message-ID: <58fd7e35-ba6c-432e-8e02-9c5476c854b4@kili.mountain> References: <9c90e813-c7fb-4c90-b52b-131481640a78@kili.mountain> <168548566376.23533.14778348024215909777@noble.neil.brown.name> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <168548566376.23533.14778348024215909777@noble.neil.brown.name> X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org On Wed, May 31, 2023 at 08:27:43AM +1000, NeilBrown wrote: > On Mon, 29 May 2023, Dan Carpenter wrote: > > The bug here is that you cannot rely on getting the same socket > > from multiple calls to fget() because userspace can influence > > that. This is a kind of double fetch bug. > > > > The fix is to delete the svc_alien_sock() function and insted do > > the checking inside the svc_addsock() function. > > Hi, > I definitely agree with the change to pass the 'net' into > svc_addsock(), and check the the fd has the correct net. > > I'm not sure I agree with the removal of the svc_alien_sock() test. It > is best to perform sanity tests before allocation things, and > nfsd_create_serv() can create a new 'serv' - though most often it just > incs the refcount. That's true. But the other philosophical rule is that we shouldn't optimize for the failure path. If someone gives us bad data they deserve a slow down. I also think leaving svc_alien_sock() is a trap for the unwary because it will lead to more double fget() bugs. The svc_alien_sock() function is weird because it returns false on success and false on failure and true for alien sock. > > Maybe instead svc_alien_sock() could return the struct socket (if > successful), and it could be passed to svc_addsock()??? > > I would probably then change the name of svc_alien_sock() Yeah, because we don't want alien sockets, we want Earth sockets. Doing this is much more complicated... The name svc_get_earth_sock() is just a joke. Tell me what name to use if we decide to go this route. To be honest, I would probably still go with my v1 patch. regards, dan carpenter diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index e0e98b40a6e5d..affcd44f03d6b 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -689,6 +689,7 @@ static ssize_t __write_ports_names(char *buf, struct net *net) */ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred *cred) { + struct socket *so; char *mesg = buf; int fd, err; struct nfsd_net *nn = net_generic(net, nfsd_net_id); @@ -698,22 +699,30 @@ static ssize_t __write_ports_addfd(char *buf, struct net *net, const struct cred return -EINVAL; trace_nfsd_ctl_ports_addfd(net, fd); - if (svc_alien_sock(net, fd)) { + so = svc_get_earth_sock(net, fd); + if (!so) { printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__); return -EINVAL; } err = nfsd_create_serv(net); if (err != 0) - return err; + goto out_put_sock; - err = svc_addsock(nn->nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT, cred); + err = svc_addsock(nn->nfsd_serv, so, buf, SIMPLE_TRANSACTION_LIMIT, cred); + if (err) + goto out_put_net; - if (err >= 0 && - !nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1)) + if (!nn->nfsd_serv->sv_nrthreads && !xchg(&nn->keep_active, 1)) svc_get(nn->nfsd_serv); nfsd_put(net); + return 0; + +out_put_net: + nfsd_put(net); +out_put_sock: + sockfd_put(so); return err; } diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index d16ae621782c0..2422d260591bb 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -61,8 +61,8 @@ int svc_recv(struct svc_rqst *, long); void svc_send(struct svc_rqst *rqstp); void svc_drop(struct svc_rqst *); void svc_sock_update_bufs(struct svc_serv *serv); -bool svc_alien_sock(struct net *net, int fd); -int svc_addsock(struct svc_serv *serv, const int fd, +struct socket *svc_get_earth_sock(struct net *net, int fd); +int svc_addsock(struct svc_serv *serv, struct socket *so, char *name_return, const size_t len, const struct cred *cred); void svc_init_xprt_sock(void); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 46845cb6465d7..78f6ae9fa42d4 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1474,21 +1474,20 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, return svsk; } -bool svc_alien_sock(struct net *net, int fd) +struct socket *svc_get_earth_sock(struct net *net, int fd) { int err; struct socket *sock = sockfd_lookup(fd, &err); - bool ret = false; if (!sock) - goto out; - if (sock_net(sock->sk) != net) - ret = true; - sockfd_put(sock); -out: - return ret; + return NULL; + if (sock_net(sock->sk) != net) { + sockfd_put(sock); + return NULL; + } + return sock; } -EXPORT_SYMBOL_GPL(svc_alien_sock); +EXPORT_SYMBOL_GPL(svc_get_earth_sock); /** * svc_addsock - add a listener socket to an RPC service @@ -1502,36 +1501,27 @@ EXPORT_SYMBOL_GPL(svc_alien_sock); * Name is terminated with '\n'. On error, returns a negative errno * value. */ -int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, +int svc_addsock(struct svc_serv *serv, struct socket *so, char *name_return, const size_t len, const struct cred *cred) { - int err = 0; - struct socket *so = sockfd_lookup(fd, &err); struct svc_sock *svsk = NULL; struct sockaddr_storage addr; struct sockaddr *sin = (struct sockaddr *)&addr; int salen; - if (!so) - return err; - err = -EAFNOSUPPORT; if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) - goto out; - err = -EPROTONOSUPPORT; + return -EAFNOSUPPORT; if (so->sk->sk_protocol != IPPROTO_TCP && so->sk->sk_protocol != IPPROTO_UDP) - goto out; - err = -EISCONN; + return -EPROTONOSUPPORT; if (so->state > SS_UNCONNECTED) - goto out; - err = -ENOENT; + return -EISCONN; if (!try_module_get(THIS_MODULE)) - goto out; + return -ENOENT; svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); if (IS_ERR(svsk)) { module_put(THIS_MODULE); - err = PTR_ERR(svsk); - goto out; + return PTR_ERR(svsk); } salen = kernel_getsockname(svsk->sk_sock, sin); if (salen >= 0) @@ -1539,9 +1529,6 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, svsk->sk_xprt.xpt_cred = get_cred(cred); svc_add_new_perm_xprt(serv, &svsk->sk_xprt); return svc_one_sock_name(svsk, name_return, len); -out: - sockfd_put(so); - return err; } EXPORT_SYMBOL_GPL(svc_addsock);