diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index d0e5cde27702224466905eea473709abf3e31525..9601acd2dc7bfdec15ac2b810c4664125c5593d1 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1303,6 +1303,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 d7a410d8374391c871ec5f099497457275cb216b..0148d819910ee96c3565d2c456421dcac0c1781c 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -441,12 +441,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; @@ -496,7 +499,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, }; @@ -514,7 +517,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 898de3bf884e468fedc9408e697d1eebfb8ffa49..a262a60b82c22848bb6124457524f90f4210f77c 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -466,7 +466,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(struct super_block *sb, const char *name); diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 95882b3f5f62f07380d8dbe242b0f89210e19f84..c7eeb841c2ad2daacb2817a29df3da46ee40ae4b 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -134,11 +134,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 b256911f03fc5be4b98f6285b4e8891617f7c3c5..7f899fffe96bab9bcef8b813ae9c32373d253e7a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1933,6 +1933,7 @@ struct inode_operations { umode_t create_mode); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*set_acl)(struct inode *, struct posix_acl *, int); + struct posix_acl * (*get_acl2)(struct inode *, int, bool); KABI_RESERVE(1) KABI_RESERVE(2)