From: Miklos Szeredi mszeredi@redhat.com
mainline inclusion from mainline-v5.15-rc1 commit 0cad6246621b5887d5b33fea84219d2a71f2f99a category: perf bugzilla: https://gitee.com/openeuler/kernel/issues/I6ZCW0 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Add a rcu argument to the ->get_acl() callback to allow get_cached_acl_rcu() to call the ->get_acl() method in the next patch.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com [chengzhihao: rename get_acl to get_acl2 to prevent KABI changes, and only backport(realize) overlayfs] Conflicts: fs/overlayfs/dir.c fs/overlayfs/inode.c fs/overlayfs/overlayfs.h fs/posix_acl.c include/linux/fs.h Signed-off-by: Zhihao Cheng chengzhihao1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- fs/overlayfs/dir.c | 2 +- fs/overlayfs/inode.c | 9 ++++++--- fs/overlayfs/overlayfs.h | 2 +- fs/posix_acl.c | 7 +++++-- include/linux/fs.h | 1 + 5 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 8570e755a392..cdbb916aa636 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1292,6 +1292,6 @@ const struct inode_operations ovl_dir_inode_operations = { .permission = ovl_permission, .getattr = ovl_getattr, .listxattr = ovl_listxattr, - .get_acl = ovl_get_acl, + .get_acl2 = ovl_get_acl, .update_time = ovl_update_time, }; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 3eabe457a5d5..3aa33c18cb80 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -421,12 +421,15 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) return res; }
-struct posix_acl *ovl_get_acl(struct inode *inode, int type) +struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu) { struct inode *realinode = ovl_inode_real(inode); const struct cred *old_cred; struct posix_acl *acl;
+ if (rcu) + return ERR_PTR(-ECHILD); + if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode)) return NULL;
@@ -480,7 +483,7 @@ static const struct inode_operations ovl_file_inode_operations = { .permission = ovl_permission, .getattr = ovl_getattr, .listxattr = ovl_listxattr, - .get_acl = ovl_get_acl, + .get_acl2 = ovl_get_acl, .update_time = ovl_update_time, .fiemap = ovl_fiemap, }; @@ -498,7 +501,7 @@ static const struct inode_operations ovl_special_inode_operations = { .permission = ovl_permission, .getattr = ovl_getattr, .listxattr = ovl_listxattr, - .get_acl = ovl_get_acl, + .get_acl2 = ovl_get_acl, .update_time = ovl_update_time, };
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 76e096ad2ef9..38fada5fa552 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -358,7 +358,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, void *value, size_t size); ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); -struct posix_acl *ovl_get_acl(struct inode *inode, int type); +struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu); int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags); bool ovl_is_private_xattr(const char *name);
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 2fd0fde16fe1..8e3fe9cbb28c 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -133,11 +133,14 @@ struct posix_acl *get_acl(struct inode *inode, int type) * If the filesystem doesn't have a get_acl() function at all, we'll * just create the negative cache entry. */ - if (!inode->i_op->get_acl) { + if (!inode->i_op->get_acl && !inode->i_op->get_acl2) { set_cached_acl(inode, type, NULL); return NULL; } - acl = inode->i_op->get_acl(inode, type); + if (inode->i_op->get_acl) + acl = inode->i_op->get_acl(inode, type); + else + acl = inode->i_op->get_acl2(inode, type, false);
if (IS_ERR(acl)) { /* diff --git a/include/linux/fs.h b/include/linux/fs.h index 6363c0a67af5..bd3e09a3c9a9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1838,6 +1838,7 @@ struct inode_operations { const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); int (*permission) (struct inode *, int); struct posix_acl * (*get_acl)(struct inode *, int); + struct posix_acl * (*get_acl2)(struct inode *, int, bool);
int (*readlink) (struct dentry *, char __user *,int);