Commit 41887590 authored by Bryan Schumaker's avatar Bryan Schumaker Committed by Trond Myklebust

NFS: Fix a signed vs. unsigned secinfo bug

rpc_authflavor_t is cast from an unsigned int, but the
initial code tried to use it as a signed int.  I fix
this by passing an rpc_authflavor_t pointer around, and
returning signed integers from functions.
Signed-off-by: default avatarBryan Schumaker <bjschuma@netapp.com>
Reported-by: default avatarDan Carpenter <error27@gmail.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 0867659f
...@@ -148,67 +148,64 @@ static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, ...@@ -148,67 +148,64 @@ static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors,
return pseudoflavor; return pseudoflavor;
} }
static rpc_authflavor_t nfs_negotiate_security(const struct dentry *parent, const struct dentry *dentry) static int nfs_negotiate_security(const struct dentry *parent,
const struct dentry *dentry,
rpc_authflavor_t *flavor)
{ {
int status = 0;
struct page *page; struct page *page;
struct nfs4_secinfo_flavors *flavors; struct nfs4_secinfo_flavors *flavors;
int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
rpc_authflavor_t flavor = RPC_AUTH_UNIX; int ret = -EPERM;
secinfo = NFS_PROTO(parent->d_inode)->secinfo; secinfo = NFS_PROTO(parent->d_inode)->secinfo;
if (secinfo != NULL) { if (secinfo != NULL) {
page = alloc_page(GFP_KERNEL); page = alloc_page(GFP_KERNEL);
if (!page) { if (!page) {
status = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
flavors = page_address(page); flavors = page_address(page);
status = secinfo(parent->d_inode, &dentry->d_name, flavors); ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
flavor = nfs_find_best_sec(flavors, dentry->d_inode); *flavor = nfs_find_best_sec(flavors, dentry->d_inode);
put_page(page); put_page(page);
} }
return flavor;
out: out:
status = -ENOMEM; return ret;
return status;
} }
static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent,
struct dentry *dentry, struct path *path, struct dentry *dentry, struct path *path,
struct nfs_fh *fh, struct nfs_fattr *fattr) struct nfs_fh *fh, struct nfs_fattr *fattr,
rpc_authflavor_t *flavor)
{ {
rpc_authflavor_t flavor;
struct rpc_clnt *clone; struct rpc_clnt *clone;
struct rpc_auth *auth; struct rpc_auth *auth;
int err; int err;
flavor = nfs_negotiate_security(parent, path->dentry); err = nfs_negotiate_security(parent, path->dentry, flavor);
if (flavor < 0) if (err < 0)
goto out; goto out;
clone = rpc_clone_client(server->client); clone = rpc_clone_client(server->client);
auth = rpcauth_create(flavor, clone); auth = rpcauth_create(*flavor, clone);
if (!auth) { if (!auth) {
flavor = -EIO; err = -EIO;
goto out_shutdown; goto out_shutdown;
} }
err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode,
&path->dentry->d_name, &path->dentry->d_name,
fh, fattr); fh, fattr);
if (err < 0)
flavor = err;
out_shutdown: out_shutdown:
rpc_shutdown_client(clone); rpc_shutdown_client(clone);
out: out:
return flavor; return err;
} }
#else /* CONFIG_NFS_V4 */ #else /* CONFIG_NFS_V4 */
static inline rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, static inline int nfs_lookup_with_sec(struct nfs_server *server,
struct dentry *parent, struct dentry *dentry, struct dentry *parent, struct dentry *dentry,
struct path *path, struct nfs_fh *fh, struct path *path, struct nfs_fh *fh,
struct nfs_fattr *fattr) struct nfs_fattr *fattr,
rpc_authflavor_t *flavor)
{ {
return -EPERM; return -EPERM;
} }
...@@ -234,7 +231,7 @@ struct vfsmount *nfs_d_automount(struct path *path) ...@@ -234,7 +231,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
struct nfs_fh *fh = NULL; struct nfs_fh *fh = NULL;
struct nfs_fattr *fattr = NULL; struct nfs_fattr *fattr = NULL;
int err; int err;
rpc_authflavor_t flavor = 1; rpc_authflavor_t flavor = RPC_AUTH_UNIX;
dprintk("--> nfs_d_automount()\n"); dprintk("--> nfs_d_automount()\n");
...@@ -255,13 +252,8 @@ struct vfsmount *nfs_d_automount(struct path *path) ...@@ -255,13 +252,8 @@ struct vfsmount *nfs_d_automount(struct path *path)
err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
&path->dentry->d_name, &path->dentry->d_name,
fh, fattr); fh, fattr);
if (err == -EPERM) { if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
flavor = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr); err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
if (flavor < 0)
err = flavor;
else
err = 0;
}
dput(parent); dput(parent);
if (err != 0) { if (err != 0) {
mnt = ERR_PTR(err); mnt = ERR_PTR(err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment