2021-09-27 23:49:24

by NeilBrown

[permalink] [raw]
Subject: [PATCH 0/3] Don't store cred in nfs_access_entry

It turns out that storing a counted ref to 'struct cred' in
nfs_access_entry wasn't a good choice.
'struct cred' contains counted references to 'struct key', and users
have a quota on how many keys they can have. Keeping a cred in a cache
imposes on that quota.

The nfs access cache can keep a large number of entries, and keep them
indefinitely. This can cause a user to go over-quota.

This series removes the 'struct cred *' from nfs_access_entry and
instead stores the uid, gid, and a pointer to the group info.
This makes the nfs_access_entry 64 bits larger.

Thanks,
NeilBrown

---

NeilBrown (3):
NFS: change nfs_access_get_cached to only report the mask
NFS: pass cred explicitly for access tests
NFS: don't store 'struct cred *' in struct nfs_access_entry


fs/nfs/dir.c | 63 ++++++++++++++++++++++++++++++++++-------
fs/nfs/nfs3proc.c | 5 ++--
fs/nfs/nfs4proc.c | 13 +++++----
include/linux/nfs_fs.h | 6 ++--
include/linux/nfs_xdr.h | 2 +-
5 files changed, 67 insertions(+), 22 deletions(-)

--
Signature


2021-09-27 23:49:24

by NeilBrown

[permalink] [raw]
Subject: [PATCH 1/3] NFS: change nfs_access_get_cached to only report the mask

Currently the nfs_access_get_cached family of functions report a
'struct nfs_access_entry' as the result, with both .mask and .cred set.
However the .cred is never used. This is probably good and there is no
guarantee that it won't be freed before use.

Change to only report the 'mask' - as this is all that is used or needed.

Signed-off-by: NeilBrown <[email protected]>
---
fs/nfs/dir.c | 20 +++++++++-----------
fs/nfs/nfs4proc.c | 18 +++++++++---------
include/linux/nfs_fs.h | 4 ++--
3 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 1a6d2867fba4..96b5019c6748 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2676,7 +2676,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
return NULL;
}

-static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block)
+static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, u32 *mask, bool may_block)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_access_entry *cache;
@@ -2706,8 +2706,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
spin_lock(&inode->i_lock);
retry = false;
}
- res->cred = cache->cred;
- res->mask = cache->mask;
+ *mask = cache->mask;
list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru);
err = 0;
out:
@@ -2719,7 +2718,7 @@ static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *
return -ENOENT;
}

-static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res)
+static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cred, u32 *mask)
{
/* Only check the most recently returned cache entry,
* but do it without locking.
@@ -2741,22 +2740,21 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
goto out;
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS))
goto out;
- res->cred = cache->cred;
- res->mask = cache->mask;
+ *mask = cache->mask;
err = 0;
out:
rcu_read_unlock();
return err;
}

-int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct
-nfs_access_entry *res, bool may_block)
+int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
+ u32 *mask, bool may_block)
{
int status;

- status = nfs_access_get_cached_rcu(inode, cred, res);
+ status = nfs_access_get_cached_rcu(inode, cred, mask);
if (status != 0)
- status = nfs_access_get_cached_locked(inode, cred, res,
+ status = nfs_access_get_cached_locked(inode, cred, mask,
may_block);

return status;
@@ -2877,7 +2875,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)

trace_nfs_access_enter(inode);

- status = nfs_access_get_cached(inode, cred, &cache, may_block);
+ status = nfs_access_get_cached(inode, cred, &cache.mask, may_block);
if (status == 0)
goto out_cached;

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e1214bb6b7ee..dabea09060e6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7676,7 +7676,7 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
const char *key, const void *buf,
size_t buflen, int flags)
{
- struct nfs_access_entry cache;
+ u32 mask;
int ret;

if (!nfs_server_capable(inode, NFS_CAP_XATTR))
@@ -7691,8 +7691,8 @@ static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
* do a cached access check for the XA* flags to possibly avoid
* doing an RPC and getting EACCES back.
*/
- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
- if (!(cache.mask & NFS_ACCESS_XAWRITE))
+ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
+ if (!(mask & NFS_ACCESS_XAWRITE))
return -EACCES;
}

@@ -7713,14 +7713,14 @@ static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
const char *key, void *buf, size_t buflen)
{
- struct nfs_access_entry cache;
+ u32 mask;
ssize_t ret;

if (!nfs_server_capable(inode, NFS_CAP_XATTR))
return -EOPNOTSUPP;

- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
- if (!(cache.mask & NFS_ACCESS_XAREAD))
+ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
+ if (!(mask & NFS_ACCESS_XAREAD))
return -EACCES;
}

@@ -7745,13 +7745,13 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
ssize_t ret, size;
char *buf;
size_t buflen;
- struct nfs_access_entry cache;
+ u32 mask;

if (!nfs_server_capable(inode, NFS_CAP_XATTR))
return 0;

- if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
- if (!(cache.mask & NFS_ACCESS_XALIST))
+ if (!nfs_access_get_cached(inode, current_cred(), &mask, true)) {
+ if (!(mask & NFS_ACCESS_XALIST))
return 0;
}

diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b9a8b925db43..56609378159f 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -517,8 +517,8 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh,
struct nfs_fattr *fattr, struct nfs4_label *label);
extern int nfs_may_open(struct inode *inode, const struct cred *cred, int openflags);
extern void nfs_access_zap_cache(struct inode *inode);
-extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res,
- bool may_block);
+extern int nfs_access_get_cached(struct inode *inode, const struct cred *cred,
+ u32 *mask, bool may_block);

/*
* linux/fs/nfs/symlink.c


2021-09-27 23:49:25

by NeilBrown

[permalink] [raw]
Subject: [PATCH 2/3] 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 <[email protected]>
---
fs/nfs/dir.c | 17 ++++++++++-------
fs/nfs/nfs3proc.c | 5 +++--
fs/nfs/nfs4proc.c | 12 +++++++-----
include/linux/nfs_fs.h | 2 +-
include/linux/nfs_xdr.h | 2 +-
5 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 96b5019c6748..0cd66ff2b8ba 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2761,7 +2761,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;
@@ -2774,7 +2776,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;
@@ -2796,13 +2798,14 @@ static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_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);
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
@@ -2810,7 +2813,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();
@@ -2896,7 +2899,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))
@@ -2906,7 +2909,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)
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index f7524310ddf4..c18103292a73 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -222,7 +222,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),
@@ -233,7 +234,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;

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index dabea09060e6..5f622b099412 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -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)
@@ -4472,7 +4472,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 = {
@@ -4486,7 +4487,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;

@@ -4506,14 +4507,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);
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 56609378159f..6e356dbda519 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -391,7 +391,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 *);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e9698b6278a5..80e8f8ce1bb2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1747,7 +1747,7 @@ struct nfs_rpc_ops {
struct nfs4_label *);
int (*lookupp) (struct inode *, struct nfs_fh *,
struct nfs_fattr *, struct nfs4_label *);
- 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 *,


2021-09-27 23:49:25

by NeilBrown

[permalink] [raw]
Subject: [PATCH 3/3] NFS: don't store 'struct cred *' in struct nfs_access_entry

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 remove the 'struct cred *' and replace it with the fields we need:
kuid_t, kgid_t, and struct group_info *

This makes the 'struct nfs_access_entry' 64 bits larger.

New function "access_cmp" is introduced which is identical to
cred_fscmp() except that the second arg is an 'nfs_access_entry', rather
than a 'cred'

Fixes: b68572e07c58 ("NFS: change access cache to use 'struct cred'.")
Signed-off-by: NeilBrown <[email protected]>
---
fs/nfs/dir.c | 50 ++++++++++++++++++++++++++++++++++++++++++------
fs/nfs/nfs4proc.c | 1 -
include/linux/nfs_fs.h | 4 +++-
3 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 0cd66ff2b8ba..34d1669bf163 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2531,7 +2531,7 @@ MODULE_PARM_DESC(nfs_access_max_cachesize, "NFS access maximum total cache lengt

static void nfs_access_free_entry(struct nfs_access_entry *entry)
{
- put_cred(entry->cred);
+ put_group_info(entry->group_info);
kfree_rcu(entry, rcu_head);
smp_mb__before_atomic();
atomic_long_dec(&nfs_access_nr_entries);
@@ -2657,6 +2657,43 @@ void nfs_access_zap_cache(struct inode *inode)
}
EXPORT_SYMBOL_GPL(nfs_access_zap_cache);

+static int access_cmp(const struct cred *a, const struct nfs_access_entry *b)
+{
+ struct group_info *ga, *gb;
+ int g;
+
+ if (uid_lt(a->fsuid, b->fsuid))
+ return -1;
+ if (uid_gt(a->fsuid, b->fsuid))
+ return 1;
+
+ if (gid_lt(a->fsgid, b->fsgid))
+ return -1;
+ if (gid_gt(a->fsgid, b->fsgid))
+ return 1;
+
+ ga = a->group_info;
+ gb = b->group_info;
+ if (ga == gb)
+ return 0;
+ if (ga == NULL)
+ return -1;
+ if (gb == NULL)
+ return 1;
+ if (ga->ngroups < gb->ngroups)
+ return -1;
+ if (ga->ngroups > gb->ngroups)
+ return 1;
+
+ for (g = 0; g < ga->ngroups; g++) {
+ if (gid_lt(ga->gid[g], gb->gid[g]))
+ return -1;
+ if (gid_gt(ga->gid[g], gb->gid[g]))
+ return 1;
+ }
+ return 0;
+}
+
static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, const struct cred *cred)
{
struct rb_node *n = NFS_I(inode)->access_cache.rb_node;
@@ -2664,7 +2701,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
while (n != NULL) {
struct nfs_access_entry *entry =
rb_entry(n, struct nfs_access_entry, rb_node);
- int cmp = cred_fscmp(cred, entry->cred);
+ int cmp = access_cmp(cred, entry);

if (cmp < 0)
n = n->rb_left;
@@ -2734,7 +2771,7 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
lh = rcu_dereference(list_tail_rcu(&nfsi->access_cache_entry_lru));
cache = list_entry(lh, struct nfs_access_entry, lru);
if (lh == &nfsi->access_cache_entry_lru ||
- cred_fscmp(cred, cache->cred) != 0)
+ access_cmp(cred, cache) != 0)
cache = NULL;
if (cache == NULL)
goto out;
@@ -2776,7 +2813,7 @@ static void nfs_access_add_rbtree(struct inode *inode,
while (*p != NULL) {
parent = *p;
entry = rb_entry(parent, struct nfs_access_entry, rb_node);
- cmp = cred_fscmp(cred, entry->cred);
+ cmp = access_cmp(cred, entry);

if (cmp < 0)
p = &parent->rb_left;
@@ -2805,7 +2842,9 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
if (cache == NULL)
return;
RB_CLEAR_NODE(&cache->rb_node);
- cache->cred = get_cred(cred);
+ cache->fsuid = cred->fsuid;
+ cache->fsgid = cred->fsgid;
+ cache->group_info = get_group_info(cred->group_info);
cache->mask = set->mask;

/* The above field assignments must be visible
@@ -2898,7 +2937,6 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
else
cache.mask |= NFS_ACCESS_EXECUTE;
- cache.cred = cred;
status = NFS_PROTO(inode)->access(inode, &cache, cred);
if (status != 0) {
if (status == -ESTALE) {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5f622b099412..27d3c694bc8a 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2653,7 +2653,6 @@ static int nfs4_opendata_access(const struct cred *cred,
} else if ((fmode & FMODE_READ) && !opendata->file_created)
mask = NFS4_ACCESS_READ;

- cache.cred = cred;
nfs_access_set_mask(&cache, opendata->o_res.access_result);
nfs_access_add_cache(state->inode, &cache, cred);

diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 6e356dbda519..86dcb300b0fd 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -61,7 +61,9 @@
struct nfs_access_entry {
struct rb_node rb_node;
struct list_head lru;
- const struct cred * cred;
+ kuid_t fsuid;
+ kgid_t fsgid;
+ struct group_info *group_info;
__u32 mask;
struct rcu_head rcu_head;
};


2021-11-16 20:49:30

by NeilBrown

[permalink] [raw]
Subject: Re: [PATCH 0/3] Don't store cred in nfs_access_entry


Hi Trond/Anna,
have you had a chance to look at these patches?

Thanks,
NeilBrown

On Tue, 28 Sep 2021, NeilBrown wrote:
> It turns out that storing a counted ref to 'struct cred' in
> nfs_access_entry wasn't a good choice.
> 'struct cred' contains counted references to 'struct key', and users
> have a quota on how many keys they can have. Keeping a cred in a cache
> imposes on that quota.
>
> The nfs access cache can keep a large number of entries, and keep them
> indefinitely. This can cause a user to go over-quota.
>
> This series removes the 'struct cred *' from nfs_access_entry and
> instead stores the uid, gid, and a pointer to the group info.
> This makes the nfs_access_entry 64 bits larger.
>
> Thanks,
> NeilBrown
>
> ---
>
> NeilBrown (3):
> NFS: change nfs_access_get_cached to only report the mask
> NFS: pass cred explicitly for access tests
> NFS: don't store 'struct cred *' in struct nfs_access_entry
>
>
> fs/nfs/dir.c | 63 ++++++++++++++++++++++++++++++++++-------
> fs/nfs/nfs3proc.c | 5 ++--
> fs/nfs/nfs4proc.c | 13 +++++----
> include/linux/nfs_fs.h | 6 ++--
> include/linux/nfs_xdr.h | 2 +-
> 5 files changed, 67 insertions(+), 22 deletions(-)
>
> --
> Signature
>
>

2021-11-16 20:57:38

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 0/3] Don't store cred in nfs_access_entry

On Wed, 2021-11-17 at 07:49 +1100, NeilBrown wrote:
>
> Hi Trond/Anna,
>  have you had a chance to look at these patches?
>

Oh crap... I did see those patches, and intended to pick them up for
this last merge window, but somehow forgot to move them into my
'testing' branch.

Anna, can you please queue them up for the next merge window?

Apologies
Trond

> Thanks,
> NeilBrown
>
> On Tue, 28 Sep 2021, NeilBrown wrote:
> > It turns out that storing a counted ref to 'struct cred' in
> > nfs_access_entry wasn't a good choice.
> > 'struct cred' contains counted references to 'struct key', and
> > users
> > have a quota on how many keys they can have.  Keeping a cred in a
> > cache
> > imposes on that quota.
> >
> > The nfs access cache can keep a large number of entries, and keep
> > them
> > indefinitely.  This can cause a user to go over-quota.
> >
> > This series removes the 'struct cred *' from nfs_access_entry and
> > instead stores the uid, gid, and a pointer to the group info.
> > This makes the nfs_access_entry 64 bits larger.
> >
> > Thanks,
> > NeilBrown
> >
> > ---
> >
> > NeilBrown (3):
> >       NFS: change nfs_access_get_cached to only report the mask
> >       NFS: pass cred explicitly for access tests
> >       NFS: don't store 'struct cred *' in struct nfs_access_entry
> >
> >
> >  fs/nfs/dir.c            | 63 ++++++++++++++++++++++++++++++++++---
> > ----
> >  fs/nfs/nfs3proc.c       |  5 ++--
> >  fs/nfs/nfs4proc.c       | 13 +++++----
> >  include/linux/nfs_fs.h  |  6 ++--
> >  include/linux/nfs_xdr.h |  2 +-
> >  5 files changed, 67 insertions(+), 22 deletions(-)
> >
> > --
> > Signature
> >
> >

--
Trond Myklebust
Linux NFS client maintainer, Hammerspace
[email protected]


2021-11-16 21:03:11

by NeilBrown

[permalink] [raw]
Subject: Re: [PATCH 0/3] Don't store cred in nfs_access_entry

On Wed, 17 Nov 2021, Trond Myklebust wrote:
> On Wed, 2021-11-17 at 07:49 +1100, NeilBrown wrote:
> >
> > Hi Trond/Anna,
> >  have you had a chance to look at these patches?
> >
>
> Oh crap... I did see those patches, and intended to pick them up for
> this last merge window, but somehow forgot to move them into my
> 'testing' branch.
>
> Anna, can you please queue them up for the next merge window?
>
> Apologies
> Trond

No problem - thanks.

NeilBrown

2021-11-16 21:35:49

by Anna Schumaker

[permalink] [raw]
Subject: Re: [PATCH 0/3] Don't store cred in nfs_access_entry

On Tue, Nov 16, 2021 at 3:58 PM Trond Myklebust <[email protected]> wrote:
>
> On Wed, 2021-11-17 at 07:49 +1100, NeilBrown wrote:
> >
> > Hi Trond/Anna,
> > have you had a chance to look at these patches?
> >
>
> Oh crap... I did see those patches, and intended to pick them up for
> this last merge window, but somehow forgot to move them into my
> 'testing' branch.
>
> Anna, can you please queue them up for the next merge window?

Sure! I have them applied to my private testing branch now. I'll push
them out to a public linux-next sometime in the next few weeks.

Anna
>
> Apologies
> Trond
>
> > Thanks,
> > NeilBrown
> >
> > On Tue, 28 Sep 2021, NeilBrown wrote:
> > > It turns out that storing a counted ref to 'struct cred' in
> > > nfs_access_entry wasn't a good choice.
> > > 'struct cred' contains counted references to 'struct key', and
> > > users
> > > have a quota on how many keys they can have. Keeping a cred in a
> > > cache
> > > imposes on that quota.
> > >
> > > The nfs access cache can keep a large number of entries, and keep
> > > them
> > > indefinitely. This can cause a user to go over-quota.
> > >
> > > This series removes the 'struct cred *' from nfs_access_entry and
> > > instead stores the uid, gid, and a pointer to the group info.
> > > This makes the nfs_access_entry 64 bits larger.
> > >
> > > Thanks,
> > > NeilBrown
> > >
> > > ---
> > >
> > > NeilBrown (3):
> > > NFS: change nfs_access_get_cached to only report the mask
> > > NFS: pass cred explicitly for access tests
> > > NFS: don't store 'struct cred *' in struct nfs_access_entry
> > >
> > >
> > > fs/nfs/dir.c | 63 ++++++++++++++++++++++++++++++++++---
> > > ----
> > > fs/nfs/nfs3proc.c | 5 ++--
> > > fs/nfs/nfs4proc.c | 13 +++++----
> > > include/linux/nfs_fs.h | 6 ++--
> > > include/linux/nfs_xdr.h | 2 +-
> > > 5 files changed, 67 insertions(+), 22 deletions(-)
> > >
> > > --
> > > Signature
> > >
> > >
>
> --
> Trond Myklebust
> Linux NFS client maintainer, Hammerspace
> [email protected]
>
>