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" 241a39ba99SAl Viro #include "rgrp.h" 25b3b94faaSDavid Teigland #include "trans.h" 265c676f6dSSteven Whitehouse #include "util.h" 27b3b94faaSDavid Teigland 28479c427dSSteven Whitehouse static const char *gfs2_acl_name(int type) 29b3b94faaSDavid Teigland { 30479c427dSSteven Whitehouse switch (type) { 31479c427dSSteven Whitehouse case ACL_TYPE_ACCESS: 3297d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_ACCESS; 33479c427dSSteven Whitehouse case ACL_TYPE_DEFAULT: 3497d79299SAndreas Gruenbacher return XATTR_POSIX_ACL_DEFAULT; 35479c427dSSteven Whitehouse } 36479c427dSSteven Whitehouse return NULL; 37479c427dSSteven Whitehouse } 38b3b94faaSDavid Teigland 391a39ba99SAl Viro static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) 40479c427dSSteven Whitehouse { 41018a01cdSSteven Whitehouse struct gfs2_inode *ip = GFS2_I(inode); 42479c427dSSteven Whitehouse struct posix_acl *acl; 43479c427dSSteven Whitehouse const char *name; 44479c427dSSteven Whitehouse char *data; 45479c427dSSteven Whitehouse int len; 4640b78a32SSteven Whitehouse 473767ac21SSteven Whitehouse if (!ip->i_eattr) 48479c427dSSteven Whitehouse return NULL; 49b3b94faaSDavid Teigland 50479c427dSSteven Whitehouse name = gfs2_acl_name(type); 51479c427dSSteven Whitehouse len = gfs2_xattr_acl_get(ip, name, &data); 521a39ba99SAl Viro if (len <= 0) 53479c427dSSteven Whitehouse return ERR_PTR(len); 545f3a4a28SEric W. Biederman acl = posix_acl_from_xattr(&init_user_ns, data, len); 5540b78a32SSteven Whitehouse kfree(data); 56479c427dSSteven Whitehouse return acl; 57b3b94faaSDavid Teigland } 58b3b94faaSDavid Teigland 591a39ba99SAl Viro struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 601a39ba99SAl Viro { 611a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 621a39ba99SAl Viro struct gfs2_holder gh; 631a39ba99SAl Viro bool need_unlock = false; 641a39ba99SAl Viro struct posix_acl *acl; 651a39ba99SAl Viro 661a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 671a39ba99SAl Viro int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 681a39ba99SAl Viro LM_FLAG_ANY, &gh); 691a39ba99SAl Viro if (ret) 701a39ba99SAl Viro return ERR_PTR(ret); 711a39ba99SAl Viro need_unlock = true; 721a39ba99SAl Viro } 731a39ba99SAl Viro acl = __gfs2_get_acl(inode, type); 741a39ba99SAl Viro if (need_unlock) 751a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 761a39ba99SAl Viro return acl; 771a39ba99SAl Viro } 781a39ba99SAl Viro 791a39ba99SAl Viro int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 80b3b94faaSDavid Teigland { 81b3b94faaSDavid Teigland int error; 82910f3d58SChengguang Xu size_t len; 83479c427dSSteven Whitehouse char *data; 84479c427dSSteven Whitehouse const char *name = gfs2_acl_name(type); 85479c427dSSteven Whitehouse 86e01580bfSChristoph Hellwig if (acl) { 87910f3d58SChengguang Xu len = posix_acl_xattr_size(acl->a_count); 88479c427dSSteven Whitehouse data = kmalloc(len, GFP_NOFS); 89479c427dSSteven Whitehouse if (data == NULL) 90479c427dSSteven Whitehouse return -ENOMEM; 915f3a4a28SEric W. Biederman error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 92479c427dSSteven Whitehouse if (error < 0) 93479c427dSSteven Whitehouse goto out; 94e01580bfSChristoph Hellwig } else { 95e01580bfSChristoph Hellwig data = NULL; 96e01580bfSChristoph Hellwig len = 0; 97e01580bfSChristoph Hellwig } 98e01580bfSChristoph Hellwig 99431547b3SChristoph Hellwig error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 100479c427dSSteven Whitehouse if (error) 101479c427dSSteven Whitehouse goto out; 102106381bfSSteven Whitehouse set_cached_acl(inode, type, acl); 1032646a1f6SSteven Whitehouse out: 104e01580bfSChristoph Hellwig kfree(data); 1052646a1f6SSteven Whitehouse return error; 1062646a1f6SSteven Whitehouse } 1071a39ba99SAl Viro 1081a39ba99SAl Viro int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 1091a39ba99SAl Viro { 1101a39ba99SAl Viro struct gfs2_inode *ip = GFS2_I(inode); 1111a39ba99SAl Viro struct gfs2_holder gh; 1121a39ba99SAl Viro bool need_unlock = false; 1131a39ba99SAl Viro int ret; 114309e8cdaSErnesto A. Fernández umode_t mode; 1151a39ba99SAl Viro 116914cea93SJan Kara if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 117914cea93SJan Kara return -E2BIG; 118914cea93SJan Kara 1191a39ba99SAl Viro ret = gfs2_rsqa_alloc(ip); 1201a39ba99SAl Viro if (ret) 1211a39ba99SAl Viro return ret; 1221a39ba99SAl Viro 1231a39ba99SAl Viro if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 1241a39ba99SAl Viro ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 1251a39ba99SAl Viro if (ret) 1261a39ba99SAl Viro return ret; 1271a39ba99SAl Viro need_unlock = true; 1281a39ba99SAl Viro } 129914cea93SJan Kara 130309e8cdaSErnesto A. Fernández mode = inode->i_mode; 131309e8cdaSErnesto A. Fernández if (type == ACL_TYPE_ACCESS && acl) { 132309e8cdaSErnesto A. Fernández ret = posix_acl_update_mode(inode, &mode, &acl); 133914cea93SJan Kara if (ret) 134914cea93SJan Kara goto unlock; 135914cea93SJan Kara } 136914cea93SJan Kara 1371a39ba99SAl Viro ret = __gfs2_set_acl(inode, acl, type); 138309e8cdaSErnesto A. Fernández if (!ret && mode != inode->i_mode) { 139c2c4be28SAndreas Gruenbacher inode->i_ctime = current_time(inode); 140309e8cdaSErnesto A. Fernández inode->i_mode = mode; 141309e8cdaSErnesto A. Fernández mark_inode_dirty(inode); 142309e8cdaSErnesto A. Fernández } 143914cea93SJan Kara unlock: 1441a39ba99SAl Viro if (need_unlock) 1451a39ba99SAl Viro gfs2_glock_dq_uninit(&gh); 1461a39ba99SAl Viro return ret; 1471a39ba99SAl Viro } 148