Commit 73fbb3fa authored by NeilBrown's avatar NeilBrown Committed by Anna Schumaker

NFS: pass cred explicitly for access tests

Storing the 'struct cred *' in nfs_access_entry is problematic.
An active 'cred' can keep a 'struct key *' active, and a quota is
imposed on the number of such keys that a user can maintain.
Cached 'nfs_access_entry' structs have indefinite lifetime, and having
these keep 'struct key's alive imposes on that quota.

So a future patch will remove the ->cred ref from nfs_access_entry.

To prepare, change various functions to not assume there is a 'cred' in
the nfs_access_entry, but to pass the cred around explicitly.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent b5e7b59c
...@@ -2758,7 +2758,9 @@ int nfs_access_get_cached(struct inode *inode, const struct cred *cred, ...@@ -2758,7 +2758,9 @@ int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
} }
EXPORT_SYMBOL_GPL(nfs_access_get_cached); EXPORT_SYMBOL_GPL(nfs_access_get_cached);
static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) static void nfs_access_add_rbtree(struct inode *inode,
struct nfs_access_entry *set,
const struct cred *cred)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct rb_root *root_node = &nfsi->access_cache; struct rb_root *root_node = &nfsi->access_cache;
...@@ -2771,7 +2773,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry * ...@@ -2771,7 +2773,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
while (*p != NULL) { while (*p != NULL) {
parent = *p; parent = *p;
entry = rb_entry(parent, struct nfs_access_entry, rb_node); entry = rb_entry(parent, struct nfs_access_entry, rb_node);
cmp = cred_fscmp(set->cred, entry->cred); cmp = cred_fscmp(cred, entry->cred);
if (cmp < 0) if (cmp < 0)
p = &parent->rb_left; p = &parent->rb_left;
...@@ -2793,13 +2795,14 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry * ...@@ -2793,13 +2795,14 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
nfs_access_free_entry(entry); nfs_access_free_entry(entry);
} }
void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
const struct cred *cred)
{ {
struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
if (cache == NULL) if (cache == NULL)
return; return;
RB_CLEAR_NODE(&cache->rb_node); RB_CLEAR_NODE(&cache->rb_node);
cache->cred = get_cred(set->cred); cache->cred = get_cred(cred);
cache->mask = set->mask; cache->mask = set->mask;
/* The above field assignments must be visible /* The above field assignments must be visible
...@@ -2807,7 +2810,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) ...@@ -2807,7 +2810,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
* use rcu_assign_pointer, so just force the memory barrier. * use rcu_assign_pointer, so just force the memory barrier.
*/ */
smp_wmb(); smp_wmb();
nfs_access_add_rbtree(inode, cache); nfs_access_add_rbtree(inode, cache, cred);
/* Update accounting */ /* Update accounting */
smp_mb__before_atomic(); smp_mb__before_atomic();
...@@ -2893,7 +2896,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask) ...@@ -2893,7 +2896,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
else else
cache.mask |= NFS_ACCESS_EXECUTE; cache.mask |= NFS_ACCESS_EXECUTE;
cache.cred = cred; cache.cred = cred;
status = NFS_PROTO(inode)->access(inode, &cache); status = NFS_PROTO(inode)->access(inode, &cache, cred);
if (status != 0) { if (status != 0) {
if (status == -ESTALE) { if (status == -ESTALE) {
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
...@@ -2903,7 +2906,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask) ...@@ -2903,7 +2906,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
} }
goto out; goto out;
} }
nfs_access_add_cache(inode, &cache); nfs_access_add_cache(inode, &cache, cred);
out_cached: out_cached:
cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode); cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0) if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
......
...@@ -220,7 +220,8 @@ static int nfs3_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, ...@@ -220,7 +220,8 @@ static int nfs3_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
task_flags); task_flags);
} }
static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs3_accessargs arg = { struct nfs3_accessargs arg = {
.fh = NFS_FH(inode), .fh = NFS_FH(inode),
...@@ -231,7 +232,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) ...@@ -231,7 +232,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
.rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS], .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
.rpc_argp = &arg, .rpc_argp = &arg,
.rpc_resp = &res, .rpc_resp = &res,
.rpc_cred = entry->cred, .rpc_cred = cred,
}; };
int status = -ENOMEM; int status = -ENOMEM;
......
...@@ -2655,7 +2655,7 @@ static int nfs4_opendata_access(const struct cred *cred, ...@@ -2655,7 +2655,7 @@ static int nfs4_opendata_access(const struct cred *cred,
cache.cred = cred; cache.cred = cred;
nfs_access_set_mask(&cache, opendata->o_res.access_result); nfs_access_set_mask(&cache, opendata->o_res.access_result);
nfs_access_add_cache(state->inode, &cache); nfs_access_add_cache(state->inode, &cache, cred);
flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP; flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
if ((mask & ~cache.mask & flags) == 0) if ((mask & ~cache.mask & flags) == 0)
...@@ -4441,7 +4441,8 @@ static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, ...@@ -4441,7 +4441,8 @@ static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
return err; return err;
} }
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_accessargs args = { struct nfs4_accessargs args = {
...@@ -4455,7 +4456,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry ...@@ -4455,7 +4456,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
.rpc_argp = &args, .rpc_argp = &args,
.rpc_resp = &res, .rpc_resp = &res,
.rpc_cred = entry->cred, .rpc_cred = cred,
}; };
int status = 0; int status = 0;
...@@ -4475,14 +4476,15 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry ...@@ -4475,14 +4476,15 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
return status; return status;
} }
static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
const struct cred *cred)
{ {
struct nfs4_exception exception = { struct nfs4_exception exception = {
.interruptible = true, .interruptible = true,
}; };
int err; int err;
do { do {
err = _nfs4_proc_access(inode, entry); err = _nfs4_proc_access(inode, entry, cred);
trace_nfs4_access(inode, err); trace_nfs4_access(inode, err);
err = nfs4_handle_exception(NFS_SERVER(inode), err, err = nfs4_handle_exception(NFS_SERVER(inode), err,
&exception); &exception);
......
...@@ -396,7 +396,7 @@ extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fa ...@@ -396,7 +396,7 @@ extern int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fa
extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr); extern int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fattr *fattr);
extern int nfs_getattr(struct user_namespace *, const struct path *, extern int nfs_getattr(struct user_namespace *, const struct path *,
struct kstat *, u32, unsigned int); struct kstat *, u32, unsigned int);
extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *, const struct cred *);
extern void nfs_access_set_mask(struct nfs_access_entry *, u32); extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
extern int nfs_permission(struct user_namespace *, struct inode *, int); extern int nfs_permission(struct user_namespace *, struct inode *, int);
extern int nfs_open(struct inode *, struct file *); extern int nfs_open(struct inode *, struct file *);
......
...@@ -1737,7 +1737,7 @@ struct nfs_rpc_ops { ...@@ -1737,7 +1737,7 @@ struct nfs_rpc_ops {
struct nfs_fh *, struct nfs_fattr *); struct nfs_fh *, struct nfs_fattr *);
int (*lookupp) (struct inode *, struct nfs_fh *, int (*lookupp) (struct inode *, struct nfs_fh *,
struct nfs_fattr *); struct nfs_fattr *);
int (*access) (struct inode *, struct nfs_access_entry *); int (*access) (struct inode *, struct nfs_access_entry *, const struct cred *);
int (*readlink)(struct inode *, struct page *, unsigned int, int (*readlink)(struct inode *, struct page *, unsigned int,
unsigned int); unsigned int);
int (*create) (struct inode *, struct dentry *, int (*create) (struct inode *, struct dentry *,
......
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