forked from Minki/linux
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: NeilBrown <neilb@suse.de> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
b5e7b59c34
commit
73fbb3fa64
17
fs/nfs/dir.c
17
fs/nfs/dir.c
@ -2758,7 +2758,9 @@ int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
|
||||
}
|
||||
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 rb_root *root_node = &nfsi->access_cache;
|
||||
@ -2771,7 +2773,7 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *
|
||||
while (*p != NULL) {
|
||||
parent = *p;
|
||||
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)
|
||||
p = &parent->rb_left;
|
||||
@ -2793,13 +2795,14 @@ found:
|
||||
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);
|
||||
if (cache == NULL)
|
||||
return;
|
||||
RB_CLEAR_NODE(&cache->rb_node);
|
||||
cache->cred = get_cred(set->cred);
|
||||
cache->cred = get_cred(cred);
|
||||
cache->mask = set->mask;
|
||||
|
||||
/* The above field assignments must be visible
|
||||
@ -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.
|
||||
*/
|
||||
smp_wmb();
|
||||
nfs_access_add_rbtree(inode, cache);
|
||||
nfs_access_add_rbtree(inode, cache, cred);
|
||||
|
||||
/* Update accounting */
|
||||
smp_mb__before_atomic();
|
||||
@ -2893,7 +2896,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
|
||||
else
|
||||
cache.mask |= NFS_ACCESS_EXECUTE;
|
||||
cache.cred = cred;
|
||||
status = NFS_PROTO(inode)->access(inode, &cache);
|
||||
status = NFS_PROTO(inode)->access(inode, &cache, cred);
|
||||
if (status != 0) {
|
||||
if (status == -ESTALE) {
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
@ -2903,7 +2906,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
nfs_access_add_cache(inode, &cache);
|
||||
nfs_access_add_cache(inode, &cache, cred);
|
||||
out_cached:
|
||||
cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
|
||||
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,
|
||||
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 = {
|
||||
.fh = NFS_FH(inode),
|
||||
@ -231,7 +232,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
|
||||
.rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
|
||||
.rpc_argp = &arg,
|
||||
.rpc_resp = &res,
|
||||
.rpc_cred = entry->cred,
|
||||
.rpc_cred = cred,
|
||||
};
|
||||
int status = -ENOMEM;
|
||||
|
||||
|
@ -2655,7 +2655,7 @@ static int nfs4_opendata_access(const struct cred *cred,
|
||||
|
||||
cache.cred = cred;
|
||||
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;
|
||||
if ((mask & ~cache.mask & flags) == 0)
|
||||
@ -4441,7 +4441,8 @@ static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle,
|
||||
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 nfs4_accessargs args = {
|
||||
@ -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_argp = &args,
|
||||
.rpc_resp = &res,
|
||||
.rpc_cred = entry->cred,
|
||||
.rpc_cred = cred,
|
||||
};
|
||||
int status = 0;
|
||||
|
||||
@ -4475,14 +4476,15 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
|
||||
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 = {
|
||||
.interruptible = true,
|
||||
};
|
||||
int err;
|
||||
do {
|
||||
err = _nfs4_proc_access(inode, entry);
|
||||
err = _nfs4_proc_access(inode, entry, cred);
|
||||
trace_nfs4_access(inode, err);
|
||||
err = nfs4_handle_exception(NFS_SERVER(inode), err,
|
||||
&exception);
|
||||
|
@ -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_getattr(struct user_namespace *, const struct path *,
|
||||
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 int nfs_permission(struct user_namespace *, struct inode *, int);
|
||||
extern int nfs_open(struct inode *, struct file *);
|
||||
|
@ -1737,7 +1737,7 @@ struct nfs_rpc_ops {
|
||||
struct nfs_fh *, struct nfs_fattr *);
|
||||
int (*lookupp) (struct inode *, struct nfs_fh *,
|
||||
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,
|
||||
unsigned int);
|
||||
int (*create) (struct inode *, struct dentry *,
|
||||
|
Loading…
Reference in New Issue
Block a user