NFS: Fix an Oops in encode_lookup()

It doesn't look as if the NFS file name limit is being initialised correctly
in the struct nfs_server. Make sure that we limit whatever is being set in
nfs_probe_fsinfo() and nfs_init_server().

Also ensure that readdirplus and nfs4_path_walk respect our file name
limits.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Trond Myklebust and committed by Linus Torvalds 54af3bb5 bd893663

+24 -10
+19 -10
fs/nfs/client.c
··· 588 588 server->namelen = data->namlen; 589 589 /* Create a client RPC handle for the NFSv3 ACL management interface */ 590 590 nfs_init_server_aclclient(server); 591 - if (clp->cl_nfsversion == 3) { 592 - if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) 593 - server->namelen = NFS3_MAXNAMLEN; 594 - if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) 595 - server->caps |= NFS_CAP_READDIRPLUS; 596 - } else { 597 - if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) 598 - server->namelen = NFS2_MAXNAMLEN; 599 - } 600 - 601 591 dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); 602 592 return 0; 603 593 ··· 784 794 error = nfs_probe_fsinfo(server, mntfh, &fattr); 785 795 if (error < 0) 786 796 goto error; 797 + if (server->nfs_client->rpc_ops->version == 3) { 798 + if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) 799 + server->namelen = NFS3_MAXNAMLEN; 800 + if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) 801 + server->caps |= NFS_CAP_READDIRPLUS; 802 + } else { 803 + if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) 804 + server->namelen = NFS2_MAXNAMLEN; 805 + } 806 + 787 807 if (!(fattr.valid & NFS_ATTR_FATTR)) { 788 808 error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); 789 809 if (error < 0) { ··· 984 984 if (error < 0) 985 985 goto error; 986 986 987 + if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 988 + server->namelen = NFS4_MAXNAMLEN; 989 + 987 990 BUG_ON(!server->nfs_client); 988 991 BUG_ON(!server->nfs_client->rpc_ops); 989 992 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); ··· 1059 1056 if (error < 0) 1060 1057 goto error; 1061 1058 1059 + if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 1060 + server->namelen = NFS4_MAXNAMLEN; 1061 + 1062 1062 dprintk("Referral FSID: %llx:%llx\n", 1063 1063 (unsigned long long) server->fsid.major, 1064 1064 (unsigned long long) server->fsid.minor); ··· 1120 1114 error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); 1121 1115 if (error < 0) 1122 1116 goto out_free_server; 1117 + 1118 + if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 1119 + server->namelen = NFS4_MAXNAMLEN; 1123 1120 1124 1121 dprintk("Cloned FSID: %llx:%llx\n", 1125 1122 (unsigned long long) server->fsid.major,
+2
fs/nfs/dir.c
··· 1162 1162 } 1163 1163 if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) 1164 1164 return NULL; 1165 + if (name.len > NFS_SERVER(dir)->namelen) 1166 + return NULL; 1165 1167 /* Note: caller is already holding the dir->i_mutex! */ 1166 1168 dentry = d_alloc(parent, &name); 1167 1169 if (dentry == NULL)
+3
fs/nfs/getroot.c
··· 175 175 path++; 176 176 name.len = path - (const char *) name.name; 177 177 178 + if (name.len > NFS4_MAXNAMLEN) 179 + return -ENAMETOOLONG; 180 + 178 181 eat_dot_dir: 179 182 while (*path == '/') 180 183 path++;