Message ID | 20201007210720.537880-3-trondmy@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Give containers a unique client id | expand |
On Wed, Oct 07, 2020 at 05:07:20PM -0400, trondmy@kernel.org wrote: > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > If a container sets a net namespace specific uniquifier, What you're actually checking is if nn->nfs_client != NULL, and that's pretty much always true. (The only time it's NULL is an allocation failure in some initialization code, I think.) > + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); > + struct nfs_netns_client *nn_clp = nn->nfs_client; > + const char *id; > + size_t len; > + > buf[0] = '\0'; > + > + if (nn_clp) { Are you sure you don't mean if (nn_clp->identifier) ? I think that's how you tell if someone's set it. --b. > + rcu_read_lock(); > + id = rcu_dereference(nn_clp->identifier); > + if (id && *id != '\0') > + len = strlcpy(buf, id, buflen); > + rcu_read_unlock(); > + if (len) > + return len; > + } > + > if (nfs4_client_id_uniquifier[0] != '\0') > return strlcpy(buf, nfs4_client_id_uniquifier, buflen); > return 0; > @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp) > 1; > rcu_read_unlock(); > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > if (buflen) > len += buflen + 1; > > @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct nfs_client *clp) > len = 10 + 10 + 1 + 10 + 1 + > strlen(clp->cl_rpcclient->cl_nodename) + 1; > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > if (buflen) > len += buflen + 1; > > -- > 2.26.2
On Wed, 2020-10-07 at 17:25 -0400, J. Bruce Fields wrote: > On Wed, Oct 07, 2020 at 05:07:20PM -0400, trondmy@kernel.org wrote: > > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > > > If a container sets a net namespace specific uniquifier, > > What you're actually checking is if nn->nfs_client != NULL, and > that's > pretty much always true. (The only time it's NULL is an allocation > failure in some initialization code, I think.) > > > + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); > > + struct nfs_netns_client *nn_clp = nn->nfs_client; > > + const char *id; > > + size_t len; > > + > > buf[0] = '\0'; > > + > > + if (nn_clp) { > > Are you sure you don't mean > > if (nn_clp->identifier) > > ? > > I think that's how you tell if someone's set it. We're not holding the rcu_read_lock() here, so there is no point in dereferencing the identifier pointer. That would cause a toctou race... > > --b. > > > + rcu_read_lock(); > > + id = rcu_dereference(nn_clp->identifier); > > + if (id && *id != '\0') > > + len = strlcpy(buf, id, buflen); > > + rcu_read_unlock(); > > + if (len) > > + return len; Oops. However I do need to ensure that 'len' is always initialised here. > > + } > > + > > if (nfs4_client_id_uniquifier[0] != '\0') > > return strlcpy(buf, nfs4_client_id_uniquifier, buflen); > > return 0; > > @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct > > nfs_client *clp) > > 1; > > rcu_read_unlock(); > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > if (buflen) > > len += buflen + 1; > > > > @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct > > nfs_client *clp) > > len = 10 + 10 + 1 + 10 + 1 + > > strlen(clp->cl_rpcclient->cl_nodename) + 1; > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > if (buflen) > > len += buflen + 1; > > > > -- > > 2.26.2
On Wed, Oct 07, 2020 at 09:34:17PM +0000, Trond Myklebust wrote: > On Wed, 2020-10-07 at 17:25 -0400, J. Bruce Fields wrote: > > On Wed, Oct 07, 2020 at 05:07:20PM -0400, trondmy@kernel.org wrote: > > > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > > > > > If a container sets a net namespace specific uniquifier, > > > > What you're actually checking is if nn->nfs_client != NULL, and > > that's > > pretty much always true. (The only time it's NULL is an allocation > > failure in some initialization code, I think.) > > > > > + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); > > > + struct nfs_netns_client *nn_clp = nn->nfs_client; > > > + const char *id; > > > + size_t len; > > > + > > > buf[0] = '\0'; > > > + > > > + if (nn_clp) { > > > > Are you sure you don't mean > > > > if (nn_clp->identifier) > > > > ? > > > > I think that's how you tell if someone's set it. > > We're not holding the rcu_read_lock() here, so there is no point in > dereferencing the identifier pointer. That would cause a toctou race... Oh, right: > > > + rcu_read_lock(); > > > + id = rcu_dereference(nn_clp->identifier); > > > + if (id && *id != '\0') My bad, I saw the first check and missed that one somehow. > > > + len = strlcpy(buf, id, buflen); > > > + rcu_read_unlock(); > > > + if (len) > > > + return len; > > Oops. However I do need to ensure that 'len' is always initialised > here. OK.--b. > > > > + } > > > + > > > if (nfs4_client_id_uniquifier[0] != '\0') > > > return strlcpy(buf, nfs4_client_id_uniquifier, buflen); > > > return 0; > > > @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct > > > nfs_client *clp) > > > 1; > > > rcu_read_unlock(); > > > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > > if (buflen) > > > len += buflen + 1; > > > > > > @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct > > > nfs_client *clp) > > > len = 10 + 10 + 1 + 10 + 1 + > > > strlen(clp->cl_rpcclient->cl_nodename) + 1; > > > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > > if (buflen) > > > len += buflen + 1; > > > > > > -- > > > 2.26.2 > -- > Trond Myklebust > Linux NFS client maintainer, Hammerspace > trond.myklebust@hammerspace.com > >
On 10/7/20 2:07 PM, trondmy@kernel.org wrote: > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > If a container sets a net namespace specific uniquifier, then use that > in the setclientid/exchangeid process. > > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> > --- > fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++--- > 1 file changed, 20 insertions(+), 3 deletions(-) > > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > index 3a39887e0e6e..a1dd46e7440b 100644 > --- a/fs/nfs/nfs4proc.c > +++ b/fs/nfs/nfs4proc.c > @@ -63,6 +63,7 @@ > #include "callback.h" > #include "pnfs.h" > #include "netns.h" > +#include "sysfs.h" > #include "nfs4idmap.h" > #include "nfs4session.h" > #include "fscache.h" > @@ -6007,9 +6008,25 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, > } > > static size_t > -nfs4_get_uniquifier(char *buf, size_t buflen) > +nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen) > { > + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); > + struct nfs_netns_client *nn_clp = nn->nfs_client; > + const char *id; > + size_t len; > + > buf[0] = '\0'; > + > + if (nn_clp) { > + rcu_read_lock(); > + id = rcu_dereference(nn_clp->identifier); > + if (id && *id != '\0') > + len = strlcpy(buf, id, buflen); > + rcu_read_unlock(); > + if (len) I think 'len' can be uninitialized here. -Dai > + return len; > + } > + > if (nfs4_client_id_uniquifier[0] != '\0') > return strlcpy(buf, nfs4_client_id_uniquifier, buflen); > return 0; > @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp) > 1; > rcu_read_unlock(); > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > if (buflen) > len += buflen + 1; > > @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct nfs_client *clp) > len = 10 + 10 + 1 + 10 + 1 + > strlen(clp->cl_rpcclient->cl_nodename) + 1; > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > if (buflen) > len += buflen + 1; >
On Wed, 2020-10-07 at 15:02 -0700, Dai Ngo wrote: > On 10/7/20 2:07 PM, trondmy@kernel.org wrote: > > From: Trond Myklebust <trond.myklebust@hammerspace.com> > > > > If a container sets a net namespace specific uniquifier, then use > > that > > in the setclientid/exchangeid process. > > > > Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> > > --- > > fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++--- > > 1 file changed, 20 insertions(+), 3 deletions(-) > > > > diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c > > index 3a39887e0e6e..a1dd46e7440b 100644 > > --- a/fs/nfs/nfs4proc.c > > +++ b/fs/nfs/nfs4proc.c > > @@ -63,6 +63,7 @@ > > #include "callback.h" > > #include "pnfs.h" > > #include "netns.h" > > +#include "sysfs.h" > > #include "nfs4idmap.h" > > #include "nfs4session.h" > > #include "fscache.h" > > @@ -6007,9 +6008,25 @@ static void nfs4_init_boot_verifier(const > > struct nfs_client *clp, > > } > > > > static size_t > > -nfs4_get_uniquifier(char *buf, size_t buflen) > > +nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t > > buflen) > > { > > + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); > > + struct nfs_netns_client *nn_clp = nn->nfs_client; > > + const char *id; > > + size_t len; > > + > > buf[0] = '\0'; > > + > > + if (nn_clp) { > > + rcu_read_lock(); > > + id = rcu_dereference(nn_clp->identifier); > > + if (id && *id != '\0') > > + len = strlcpy(buf, id, buflen); > > + rcu_read_unlock(); > > + if (len) > > I think 'len' can be uninitialized here. Thanks. Yes, already noted and fixed in v2. > > -Dai > > > + return len; > > + } > > + > > if (nfs4_client_id_uniquifier[0] != '\0') > > return strlcpy(buf, nfs4_client_id_uniquifier, buflen); > > return 0; > > @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct > > nfs_client *clp) > > 1; > > rcu_read_unlock(); > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > if (buflen) > > len += buflen + 1; > > > > @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct > > nfs_client *clp) > > len = 10 + 10 + 1 + 10 + 1 + > > strlen(clp->cl_rpcclient->cl_nodename) + 1; > > > > - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); > > + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); > > if (buflen) > > len += buflen + 1; > >
Hi, I love your patch! Perhaps something to improve: [auto build test WARNING on nfs/linux-next] [also build test WARNING on v5.9-rc8 next-20201007] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/trondmy-kernel-org/Give-containers-a-unique-client-id/20201008-050958 base: git://git.linux-nfs.org/projects/trondmy/linux-nfs.git linux-next config: s390-randconfig-s032-20201008 (attached as .config) compiler: s390-linux-gcc (GCC) 9.3.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.2-218-gc0e96d6d-dirty # https://github.com/0day-ci/linux/commit/440cb74f8b835271bd5e1f6574dc9cb002cec5be git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review trondmy-kernel-org/Give-containers-a-unique-client-id/20201008-050958 git checkout 440cb74f8b835271bd5e1f6574dc9cb002cec5be # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=s390 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> echo echo "sparse warnings: (new ones prefixed by >>)" echo >> fs/nfs/nfs4proc.c:6022:22: sparse: sparse: incompatible types in comparison expression (different address spaces): >> fs/nfs/nfs4proc.c:6022:22: sparse: char const [noderef] __rcu * >> fs/nfs/nfs4proc.c:6022:22: sparse: char const * vim +6022 fs/nfs/nfs4proc.c 6009 6010 static size_t 6011 nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen) 6012 { 6013 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); 6014 struct nfs_netns_client *nn_clp = nn->nfs_client; 6015 const char *id; 6016 size_t len; 6017 6018 buf[0] = '\0'; 6019 6020 if (nn_clp) { 6021 rcu_read_lock(); > 6022 id = rcu_dereference(nn_clp->identifier); 6023 if (id && *id != '\0') 6024 len = strlcpy(buf, id, buflen); 6025 rcu_read_unlock(); 6026 if (len) 6027 return len; 6028 } 6029 6030 if (nfs4_client_id_uniquifier[0] != '\0') 6031 return strlcpy(buf, nfs4_client_id_uniquifier, buflen); 6032 return 0; 6033 } 6034 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3a39887e0e6e..a1dd46e7440b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -63,6 +63,7 @@ #include "callback.h" #include "pnfs.h" #include "netns.h" +#include "sysfs.h" #include "nfs4idmap.h" #include "nfs4session.h" #include "fscache.h" @@ -6007,9 +6008,25 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, } static size_t -nfs4_get_uniquifier(char *buf, size_t buflen) +nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen) { + struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); + struct nfs_netns_client *nn_clp = nn->nfs_client; + const char *id; + size_t len; + buf[0] = '\0'; + + if (nn_clp) { + rcu_read_lock(); + id = rcu_dereference(nn_clp->identifier); + if (id && *id != '\0') + len = strlcpy(buf, id, buflen); + rcu_read_unlock(); + if (len) + return len; + } + if (nfs4_client_id_uniquifier[0] != '\0') return strlcpy(buf, nfs4_client_id_uniquifier, buflen); return 0; @@ -6034,7 +6051,7 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp) 1; rcu_read_unlock(); - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); if (buflen) len += buflen + 1; @@ -6081,7 +6098,7 @@ nfs4_init_uniform_client_string(struct nfs_client *clp) len = 10 + 10 + 1 + 10 + 1 + strlen(clp->cl_rpcclient->cl_nodename) + 1; - buflen = nfs4_get_uniquifier(buf, sizeof(buf)); + buflen = nfs4_get_uniquifier(clp, buf, sizeof(buf)); if (buflen) len += buflen + 1;