Blob Blame History Raw
From: NeilBrown <neilb@suse.de>
Date: Mon, 27 Sep 2021 11:51:37 +1000
Subject: [PATCH] Restore kabi after NFS: pass cred explicitly for access tests
Patch-mainline: Never, kabi
References: bsc#1190746 bsc#1191172

Changing nfs_access_entry, and paassing the cred around differently breaks kabi.

So revert back to passing the cred around in nfs_access_entry,
overloading the group_info field, and hide the struct change from kabi.
No other module ever allocates these or looks in them, so this should be safe.

---
 fs/nfs/dir.c            |   10 ++++++----
 fs/nfs/nfs3proc.c       |    5 ++---
 fs/nfs/nfs4proc.c       |    7 ++++---
 include/linux/nfs_fs.h  |   12 +++++++++---
 include/linux/nfs_xdr.h |    2 +-
 5 files changed, 22 insertions(+), 14 deletions(-)

--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2466,10 +2466,11 @@ found:
 	nfs_access_free_entry(entry);
 }
 
-void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
-			  const struct cred *cred)
+void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
 {
 	struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL);
+	struct cred *cred = (void*)set->group_info;
+
 	if (cache == NULL)
 		return;
 	RB_CLEAR_NODE(&cache->rb_node);
@@ -2566,7 +2567,8 @@ static int nfs_do_access(struct inode *i
 		cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
 	else
 		cache.mask |= NFS_ACCESS_EXECUTE;
-	status = NFS_PROTO(inode)->access(inode, &cache, cred);
+	cache.group_info = (void*)cred;
+	status = NFS_PROTO(inode)->access(inode, &cache);
 	if (status != 0) {
 		if (status == -ESTALE) {
 			nfs_zap_caches(inode);
@@ -2575,7 +2577,7 @@ static int nfs_do_access(struct inode *i
 		}
 		goto out;
 	}
-	nfs_access_add_cache(inode, &cache, cred);
+	nfs_access_add_cache(inode, &cache);
 out_cached:
 	cache_mask = nfs_access_calc_mask(cache.mask, inode->i_mode);
 	if ((mask & ~cache_mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) != 0)
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -188,8 +188,7 @@ nfs3_proc_lookup(struct inode *dir, cons
 	return status;
 }
 
-static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry,
-			    const struct cred *cred)
+static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
 	struct nfs3_accessargs	arg = {
 		.fh		= NFS_FH(inode),
@@ -200,7 +199,7 @@ static int nfs3_proc_access(struct inode
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
-		.rpc_cred	= cred,
+		.rpc_cred	= (void*)entry->group_info,
 	};
 	int status = -ENOMEM;
 
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2585,7 +2585,8 @@ static int nfs4_opendata_access(const st
 		mask = NFS4_ACCESS_READ;
 
 	nfs_access_set_mask(&cache, opendata->o_res.access_result);
-	nfs_access_add_cache(state->inode, &cache, cred);
+	cache.group_info = (void*)cred;
+	nfs_access_add_cache(state->inode, &cache);
 
 	flags = NFS4_ACCESS_READ | NFS4_ACCESS_EXECUTE | NFS4_ACCESS_LOOKUP;
 	if ((mask & ~cache.mask & flags) == 0)
@@ -4409,13 +4410,13 @@ static int _nfs4_proc_access(struct inod
 	return status;
 }
 
-static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry,
-			    const struct cred *cred)
+static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
 	struct nfs4_exception exception = {
 		.interruptible = true,
 	};
 	int err;
+	const struct cred *cred = (void*)entry->group_info;
 	do {
 		err = _nfs4_proc_access(inode, entry, cred);
 		trace_nfs4_access(inode, err);
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -51,11 +51,17 @@
 struct nfs_access_entry {
 	struct rb_node		rb_node;
 	struct list_head	lru;
-	kuid_t			fsuid;
-	kgid_t			fsgid;
+#ifdef __GENKSYMS__
+	const struct cred	*cred;
+#else
 	struct group_info	*group_info;
+#endif
 	__u32			mask;
 	struct rcu_head		rcu_head;
+#ifndef __GENKSYMS__
+	kuid_t			fsuid;
+	kgid_t			fsgid;
+#endif
 };
 
 struct nfs_lock_context {
@@ -379,7 +385,7 @@ extern int nfs_post_op_update_inode(stru
 extern int nfs_post_op_update_inode_force_wcc(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(const struct path *, struct kstat *, u32, unsigned int);
-extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *, const struct cred *);
+extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
 extern void nfs_access_set_mask(struct nfs_access_entry *, u32);
 extern int nfs_permission(struct inode *, int);
 extern int nfs_open(struct inode *, struct file *);
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1652,7 +1652,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 *, const struct cred *);
+	int	(*access)  (struct inode *, struct nfs_access_entry *);
 	int	(*readlink)(struct inode *, struct page *, unsigned int,
 			    unsigned int);
 	int	(*create)  (struct inode *, struct dentry *,