17336d0e6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2b3b94faaSDavid Teigland /* 3b3b94faaSDavid Teigland * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 43a8a9a10SSteven Whitehouse * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 5b3b94faaSDavid Teigland */ 6b3b94faaSDavid Teigland 7b3b94faaSDavid Teigland #include <linux/sched.h> 8b3b94faaSDavid Teigland #include <linux/slab.h> 9b3b94faaSDavid Teigland #include <linux/spinlock.h> 10b3b94faaSDavid Teigland #include <linux/completion.h> 11b3b94faaSDavid Teigland #include <linux/buffer_head.h> 122646a1f6SSteven Whitehouse #include <linux/xattr.h> 13b3b94faaSDavid Teigland #include <linux/posix_acl.h> 14b3b94faaSDavid Teigland #include <linux/posix_acl_xattr.h> 155c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h> 16b3b94faaSDavid Teigland 17b3b94faaSDavid Teigland #include "gfs2.h" 185c676f6dSSteven Whitehouse #include "incore.h" 19b3b94faaSDavid Teigland #include "acl.h" 20307cf6e6SSteven Whitehouse #include "xattr.h" 21b3b94faaSDavid Teigland #include "glock.h" 22b3b94faaSDavid Teigland #include "inode.h" 23b3b94faaSDavid Teigland #include "meta_io.h" 24d580712aSBob Peterson #include "quota.h" 251a39ba99SAl Viro #include "rgrp.h" 26b3b94faaSDavid Teigland #include "trans.h" 275c676f6dSSteven Whitehouse #include "util.h" 28b3b94faaSDavid Teigland 29479c427dSSteven Whitehouse static const char *gfs2_acl_name(int type) 30b3b94faaSDavid Teigland { 31479c427dSSteven Whitehouse switch (type) { 32479c427dSSteven Whitehouse case ACL_TYPE_ACCESS: 3397d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_ACCESS; 34479c427dSSteven Whitehouse case ACL_TYPE_DEFAULT: 3597d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_DEFAULT; 36479c427dSSteven Whitehouse } 37479c427dSSteven Whitehouse return NULL; 38479c427dSSteven Whitehouse } 39b3b94faaSDavid Teigland 401a39ba99SAl Viro static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) 41479c427dSSteven Whitehouse { 42018a01cdSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode); 43479c427dSSteven Whitehouse struct posix_acl *acl; 44479c427dSSteven Whitehouse const char *name; 45479c427dSSteven Whitehouse char *data; 46479c427dSSteven Whitehouse int len; 4740b78a32SSteven Whitehouse 483767ac21SSteven Whitehouse if (!ip->i_eattr) 49479c427dSSteven Whitehouse return NULL; 50b3b94faaSDavid Teigland 51479c427dSSteven Whitehouse name = gfs2_acl_name(type); 52479c427dSSteven Whitehouse len = gfs2_xattr_acl_get(ip, name, &data); 531a39ba99SAl Viro if (len <= 0) 54479c427dSSteven Whitehouse return ERR_PTR(len); 555f3a4a28SEric W. Biederman acl = posix_acl_from_xattr(&init_user_ns, data, len); 5640b78a32SSteven Whitehouse kfree(data); 57479c427dSSteven Whitehouse return acl; 58b3b94faaSDavid Teigland } 59b3b94faaSDavid Teigland 600cad6246SMiklos Szeredi struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu) 611a39ba99SAl Viro { 621a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 631a39ba99SAl Viro struct gfs2_holder gh; 641a39ba99SAl Viro bool need_unlock = false; 651a39ba99SAl Viro struct posix_acl *acl; 661a39ba99SAl Viro 670cad6246SMiklos Szeredi if (rcu) 680cad6246SMiklos Szeredi return ERR_PTR(-ECHILD); 690cad6246SMiklos Szeredi 701a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 711a39ba99SAl Viro int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 721a39ba99SAl Viro LM_FLAG_ANY, &gh); 731a39ba99SAl Viro if (ret) 741a39ba99SAl Viro return ERR_PTR(ret); 751a39ba99SAl Viro need_unlock = true; 761a39ba99SAl Viro } 771a39ba99SAl Viro acl = __gfs2_get_acl(inode, type); 781a39ba99SAl Viro if (need_unlock) 791a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 801a39ba99SAl Viro return acl; 811a39ba99SAl Viro } 821a39ba99SAl Viro 831a39ba99SAl Viro int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 84b3b94faaSDavid Teigland { 85b3b94faaSDavid Teigland int error; 86910f3d58SChengguang Xu size_t len; 87479c427dSSteven Whitehouse char *data; 88479c427dSSteven Whitehouse const char *name = gfs2_acl_name(type); 89479c427dSSteven Whitehouse 90e01580bfSChristoph Hellwig if (acl) { 91910f3d58SChengguang Xu len = posix_acl_xattr_size(acl->a_count); 92479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 93479c427dSSteven Whitehouse if (data == NULL) 94479c427dSSteven Whitehouse return -ENOMEM; 955f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 96479c427dSSteven Whitehouse if (error < 0) 97479c427dSSteven Whitehouse goto out; 98e01580bfSChristoph Hellwig } else { 99e01580bfSChristoph Hellwig data = NULL; 100e01580bfSChristoph Hellwig len = 0; 101e01580bfSChristoph Hellwig } 102e01580bfSChristoph Hellwig 103431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 104479c427dSSteven Whitehouse if (error) 105479c427dSSteven Whitehouse goto out; 106106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 1072646a1f6SSteven Whitehouse out: 108e01580bfSChristoph Hellwig kfree(data); 1092646a1f6SSteven Whitehouse return error; 1102646a1f6SSteven Whitehouse } 1111a39ba99SAl Viro 112*13e83a49SChristian Brauner int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, 113549c7297SChristian Brauner struct posix_acl *acl, int type) 1141a39ba99SAl Viro { 115138060baSChristian Brauner struct inode *inode = d_inode(dentry); 1161a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 1171a39ba99SAl Viro struct gfs2_holder gh; 1181a39ba99SAl Viro bool need_unlock = false; 1191a39ba99SAl Viro int ret; 120309e8cdaSErnesto A. Fernández umode_t mode; 1211a39ba99SAl Viro 122914cea93SJan Kara if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 123914cea93SJan Kara return -E2BIG; 124914cea93SJan Kara 1252fba46a0SBob Peterson ret = gfs2_qa_get(ip); 1261a39ba99SAl Viro if (ret) 1271a39ba99SAl Viro return ret; 1281a39ba99SAl Viro 1291a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1301a39ba99SAl Viro ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 1311a39ba99SAl Viro if (ret) 1322fba46a0SBob Peterson goto out; 1331a39ba99SAl Viro need_unlock = true; 1341a39ba99SAl Viro } 135914cea93SJan Kara 136309e8cdaSErnesto A. Fernández mode = inode->i_mode; 137309e8cdaSErnesto A. Fernández if (type == ACL_TYPE_ACCESS && acl) { 138e65ce2a5SChristian Brauner ret = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl); 139914cea93SJan Kara if (ret) 140914cea93SJan Kara goto unlock; 141914cea93SJan Kara } 142914cea93SJan Kara 1431a39ba99SAl Viro ret = __gfs2_set_acl(inode, acl, type); 144309e8cdaSErnesto A. Fernández if (!ret && mode != inode->i_mode) { 145c2c4be28SAndreas Gruenbacher inode->i_ctime = current_time(inode); 146309e8cdaSErnesto A. Fernández inode->i_mode = mode; 147309e8cdaSErnesto A. Fernández mark_inode_dirty(inode); 148309e8cdaSErnesto A. Fernández } 149914cea93SJan Kara unlock: 1501a39ba99SAl Viro if (need_unlock) 1511a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 1522fba46a0SBob Peterson out: 1532fba46a0SBob Peterson gfs2_qa_put(ip); 1541a39ba99SAl Viro return ret; 1551a39ba99SAl Viro } 156