diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-09-28 12:27:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-28 18:36:42 -0400 |
| commit | 54af3bb543c071769141387a42deaaab5074da55 (patch) | |
| tree | d24e5b23462a51a4e932b14feb5ae943b0dbba1e | |
| parent | bd8936632475665bfd90c1180c9c1301ee838db8 (diff) | |
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>
| -rw-r--r-- | fs/nfs/client.c | 29 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 2 | ||||
| -rw-r--r-- | fs/nfs/getroot.c | 3 |
3 files changed, 24 insertions, 10 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index a49f9feff776..a204484072f3 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -588,16 +588,6 @@ static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_dat | |||
| 588 | server->namelen = data->namlen; | 588 | server->namelen = data->namlen; |
| 589 | /* Create a client RPC handle for the NFSv3 ACL management interface */ | 589 | /* Create a client RPC handle for the NFSv3 ACL management interface */ |
| 590 | nfs_init_server_aclclient(server); | 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 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); | 591 | dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); |
| 602 | return 0; | 592 | return 0; |
| 603 | 593 | ||
| @@ -794,6 +784,16 @@ struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, | |||
| 794 | error = nfs_probe_fsinfo(server, mntfh, &fattr); | 784 | error = nfs_probe_fsinfo(server, mntfh, &fattr); |
| 795 | if (error < 0) | 785 | if (error < 0) |
| 796 | goto error; | 786 | goto error; |
| 787 | if (server->nfs_client->rpc_ops->version == 3) { | ||
| 788 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | ||
| 789 | server->namelen = NFS3_MAXNAMLEN; | ||
| 790 | if (!(data->flags & NFS_MOUNT_NORDIRPLUS)) | ||
| 791 | server->caps |= NFS_CAP_READDIRPLUS; | ||
| 792 | } else { | ||
| 793 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | ||
| 794 | server->namelen = NFS2_MAXNAMLEN; | ||
| 795 | } | ||
| 796 | |||
| 797 | if (!(fattr.valid & NFS_ATTR_FATTR)) { | 797 | if (!(fattr.valid & NFS_ATTR_FATTR)) { |
| 798 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 798 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); |
| 799 | if (error < 0) { | 799 | if (error < 0) { |
| @@ -984,6 +984,9 @@ struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, | |||
| 984 | if (error < 0) | 984 | if (error < 0) |
| 985 | goto error; | 985 | goto error; |
| 986 | 986 | ||
| 987 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 988 | server->namelen = NFS4_MAXNAMLEN; | ||
| 989 | |||
| 987 | BUG_ON(!server->nfs_client); | 990 | BUG_ON(!server->nfs_client); |
| 988 | BUG_ON(!server->nfs_client->rpc_ops); | 991 | BUG_ON(!server->nfs_client->rpc_ops); |
| 989 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 992 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
| @@ -1056,6 +1059,9 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
| 1056 | if (error < 0) | 1059 | if (error < 0) |
| 1057 | goto error; | 1060 | goto error; |
| 1058 | 1061 | ||
| 1062 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 1063 | server->namelen = NFS4_MAXNAMLEN; | ||
| 1064 | |||
| 1059 | dprintk("Referral FSID: %llx:%llx\n", | 1065 | dprintk("Referral FSID: %llx:%llx\n", |
| 1060 | (unsigned long long) server->fsid.major, | 1066 | (unsigned long long) server->fsid.major, |
| 1061 | (unsigned long long) server->fsid.minor); | 1067 | (unsigned long long) server->fsid.minor); |
| @@ -1115,6 +1121,9 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source, | |||
| 1115 | if (error < 0) | 1121 | if (error < 0) |
| 1116 | goto out_free_server; | 1122 | goto out_free_server; |
| 1117 | 1123 | ||
| 1124 | if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) | ||
| 1125 | server->namelen = NFS4_MAXNAMLEN; | ||
| 1126 | |||
| 1118 | dprintk("Cloned FSID: %llx:%llx\n", | 1127 | dprintk("Cloned FSID: %llx:%llx\n", |
| 1119 | (unsigned long long) server->fsid.major, | 1128 | (unsigned long long) server->fsid.major, |
| 1120 | (unsigned long long) server->fsid.minor); | 1129 | (unsigned long long) server->fsid.minor); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ea97408e423e..e4a04d16b8b0 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1162,6 +1162,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
| 1162 | } | 1162 | } |
| 1163 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) | 1163 | if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR)) |
| 1164 | return NULL; | 1164 | return NULL; |
| 1165 | if (name.len > NFS_SERVER(dir)->namelen) | ||
| 1166 | return NULL; | ||
| 1165 | /* Note: caller is already holding the dir->i_mutex! */ | 1167 | /* Note: caller is already holding the dir->i_mutex! */ |
| 1166 | dentry = d_alloc(parent, &name); | 1168 | dentry = d_alloc(parent, &name); |
| 1167 | if (dentry == NULL) | 1169 | if (dentry == NULL) |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index d1cbf0a0fbb2..522e5ad4d8ad 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
| @@ -175,6 +175,9 @@ next_component: | |||
| 175 | path++; | 175 | path++; |
| 176 | name.len = path - (const char *) name.name; | 176 | name.len = path - (const char *) name.name; |
| 177 | 177 | ||
| 178 | if (name.len > NFS4_MAXNAMLEN) | ||
| 179 | return -ENAMETOOLONG; | ||
| 180 | |||
| 178 | eat_dot_dir: | 181 | eat_dot_dir: |
| 179 | while (*path == '/') | 182 | while (*path == '/') |
| 180 | path++; | 183 | path++; |
