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 601a39ba99SAl Viro struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 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 671a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 681a39ba99SAl Viro int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 691a39ba99SAl Viro LM_FLAG_ANY, &gh); 701a39ba99SAl Viro if (ret) 711a39ba99SAl Viro return ERR_PTR(ret); 721a39ba99SAl Viro need_unlock = true; 731a39ba99SAl Viro } 741a39ba99SAl Viro acl = __gfs2_get_acl(inode, type); 751a39ba99SAl Viro if (need_unlock) 761a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 771a39ba99SAl Viro return acl; 781a39ba99SAl Viro } 791a39ba99SAl Viro 801a39ba99SAl Viro int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 81b3b94faaSDavid Teigland { 82b3b94faaSDavid Teigland int error; 83910f3d58SChengguang Xu size_t len; 84479c427dSSteven Whitehouse char *data; 85479c427dSSteven Whitehouse const char *name = gfs2_acl_name(type); 86479c427dSSteven Whitehouse 87e01580bfSChristoph Hellwig if (acl) { 88910f3d58SChengguang Xu len = posix_acl_xattr_size(acl->a_count); 89479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 90479c427dSSteven Whitehouse if (data == NULL) 91479c427dSSteven Whitehouse return -ENOMEM; 925f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 93479c427dSSteven Whitehouse if (error < 0) 94479c427dSSteven Whitehouse goto out; 95e01580bfSChristoph Hellwig } else { 96e01580bfSChristoph Hellwig data = NULL; 97e01580bfSChristoph Hellwig len = 0; 98e01580bfSChristoph Hellwig } 99e01580bfSChristoph Hellwig 100431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 101479c427dSSteven Whitehouse if (error) 102479c427dSSteven Whitehouse goto out; 103106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 1042646a1f6SSteven Whitehouse out: 105e01580bfSChristoph Hellwig kfree(data); 1062646a1f6SSteven Whitehouse return error; 1072646a1f6SSteven Whitehouse } 1081a39ba99SAl Viro 109*549c7297SChristian Brauner int gfs2_set_acl(struct user_namespace *mnt_userns, struct inode *inode, 110*549c7297SChristian Brauner struct posix_acl *acl, int type) 1111a39ba99SAl Viro { 1121a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 1131a39ba99SAl Viro struct gfs2_holder gh; 1141a39ba99SAl Viro bool need_unlock = false; 1151a39ba99SAl Viro int ret; 116309e8cdaSErnesto A. Fernández umode_t mode; 1171a39ba99SAl Viro 118914cea93SJan Kara if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 119914cea93SJan Kara return -E2BIG; 120914cea93SJan Kara 1212fba46a0SBob Peterson ret = gfs2_qa_get(ip); 1221a39ba99SAl Viro if (ret) 1231a39ba99SAl Viro return ret; 1241a39ba99SAl Viro 1251a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1261a39ba99SAl Viro ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 1271a39ba99SAl Viro if (ret) 1282fba46a0SBob Peterson goto out; 1291a39ba99SAl Viro need_unlock = true; 1301a39ba99SAl Viro } 131914cea93SJan Kara 132309e8cdaSErnesto A. Fernández mode = inode->i_mode; 133309e8cdaSErnesto A. Fernández if (type == ACL_TYPE_ACCESS && acl) { 134e65ce2a5SChristian Brauner ret = posix_acl_update_mode(&init_user_ns, inode, &mode, &acl); 135914cea93SJan Kara if (ret) 136914cea93SJan Kara goto unlock; 137914cea93SJan Kara } 138914cea93SJan Kara 1391a39ba99SAl Viro ret = __gfs2_set_acl(inode, acl, type); 140309e8cdaSErnesto A. Fernández if (!ret && mode != inode->i_mode) { 141c2c4be28SAndreas Gruenbacher inode->i_ctime = current_time(inode); 142309e8cdaSErnesto A. Fernández inode->i_mode = mode; 143309e8cdaSErnesto A. Fernández mark_inode_dirty(inode); 144309e8cdaSErnesto A. Fernández } 145914cea93SJan Kara unlock: 1461a39ba99SAl Viro if (need_unlock) 1471a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 1482fba46a0SBob Peterson out: 1492fba46a0SBob Peterson gfs2_qa_put(ip); 1501a39ba99SAl Viro return ret; 1511a39ba99SAl Viro } 152