From 0867659fa3c245bf203d837a82e0f6ea5079c2c5 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 6 Apr 2011 10:13:32 -0700 Subject: Revert "net/sunrpc: Use static const char arrays" This reverts commit 411b5e05617593efebc06241dbc56f42150f2abe. Olga Kornievskaia reports: Problem: linux client mounting linux server using rc4-hmac-md5 enctype. gssd fails with create a context after receiving a reply from the server. Diagnose: putting printout statements in the server kernel and kerberos libraries revealed that client and server derived different integrity keys. Server kernel code was at fault due the the commit [aglo@skydive linux-pnfs]$ git show 411b5e05617593efebc06241dbc56f42150f2abe Trond: The problem is that since it relies on virt_to_page(), you cannot call sg_set_buf() for data in the const section. Reported-by: Olga Kornievskaia Signed-off-by: Trond Myklebust Cc: stable@kernel.org [2.6.36+] diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9022f0a..0a9a2ec 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -427,7 +427,7 @@ static int context_derive_keys_rc4(struct krb5_ctx *ctx) { struct crypto_hash *hmac; - static const char sigkeyconstant[] = "signaturekey"; + char sigkeyconstant[] = "signaturekey"; int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ struct hash_desc desc; struct scatterlist sg[1]; -- cgit v0.10.2 From 418875900e3de4831c84f86ae4756690dac5be77 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 6 Apr 2011 14:33:28 -0400 Subject: 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: Bryan Schumaker Reported-by: Dan Carpenter Signed-off-by: Trond Myklebust diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 9166fcb..89fc160 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -148,67 +148,64 @@ static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, 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 nfs4_secinfo_flavors *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; if (secinfo != NULL) { page = alloc_page(GFP_KERNEL); if (!page) { - status = -ENOMEM; + ret = -ENOMEM; goto out; } flavors = page_address(page); - status = secinfo(parent->d_inode, &dentry->d_name, flavors); - flavor = nfs_find_best_sec(flavors, dentry->d_inode); + ret = secinfo(parent->d_inode, &dentry->d_name, flavors); + *flavor = nfs_find_best_sec(flavors, dentry->d_inode); put_page(page); } - return flavor; - out: - status = -ENOMEM; - return status; + return ret; } -static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, - struct dentry *dentry, struct path *path, - struct nfs_fh *fh, struct nfs_fattr *fattr) +static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, + struct dentry *dentry, struct path *path, + struct nfs_fh *fh, struct nfs_fattr *fattr, + rpc_authflavor_t *flavor) { - rpc_authflavor_t flavor; struct rpc_clnt *clone; struct rpc_auth *auth; int err; - flavor = nfs_negotiate_security(parent, path->dentry); - if (flavor < 0) + err = nfs_negotiate_security(parent, path->dentry, flavor); + if (err < 0) goto out; clone = rpc_clone_client(server->client); - auth = rpcauth_create(flavor, clone); + auth = rpcauth_create(*flavor, clone); if (!auth) { - flavor = -EIO; + err = -EIO; goto out_shutdown; } err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, &path->dentry->d_name, fh, fattr); - if (err < 0) - flavor = err; out_shutdown: rpc_shutdown_client(clone); out: - return flavor; + return err; } #else /* CONFIG_NFS_V4 */ -static inline rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, - struct dentry *parent, struct dentry *dentry, - struct path *path, struct nfs_fh *fh, - struct nfs_fattr *fattr) +static inline int nfs_lookup_with_sec(struct nfs_server *server, + struct dentry *parent, struct dentry *dentry, + struct path *path, struct nfs_fh *fh, + struct nfs_fattr *fattr, + rpc_authflavor_t *flavor) { return -EPERM; } @@ -234,7 +231,7 @@ struct vfsmount *nfs_d_automount(struct path *path) struct nfs_fh *fh = NULL; struct nfs_fattr *fattr = NULL; int err; - rpc_authflavor_t flavor = 1; + rpc_authflavor_t flavor = RPC_AUTH_UNIX; dprintk("--> nfs_d_automount()\n"); @@ -255,13 +252,8 @@ struct vfsmount *nfs_d_automount(struct path *path) err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, &path->dentry->d_name, fh, fattr); - if (err == -EPERM) { - flavor = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr); - if (flavor < 0) - err = flavor; - else - err = 0; - } + if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL) + err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor); dput(parent); if (err != 0) { mnt = ERR_PTR(err); -- cgit v0.10.2 From 37adb89fadd65ce47f7e5cfd564938a76b351948 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 7 Apr 2011 16:02:20 -0400 Subject: NFS: Change initial mount authflavor only when server returns NFS4ERR_WRONGSEC When attempting an initial mount, we should only attempt other authflavors if AUTH_UNIX receives a NFS4ERR_WRONGSEC error. This allows other errors to be passed back to userspace programs. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index dfd1e6d..9bf41ea 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2204,8 +2204,6 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl goto out; } ret = nfs4_lookup_root(server, fhandle, info); - if (ret < 0) - ret = -EAGAIN; out: return ret; } @@ -2226,7 +2224,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, for (i = 0; i < len; i++) { status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); - if (status == 0) + if (status != -EPERM) break; } if (status == 0) -- cgit v0.10.2