1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. 4 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. 5 */ 6 7 #include <linux/sched.h> 8 #include <linux/slab.h> 9 #include <linux/spinlock.h> 10 #include <linux/completion.h> 11 #include <linux/buffer_head.h> 12 #include <linux/xattr.h> 13 #include <linux/posix_acl.h> 14 #include <linux/posix_acl_xattr.h> 15 #include <linux/gfs2_ondisk.h> 16 17 #include "gfs2.h" 18 #include "incore.h" 19 #include "acl.h" 20 #include "xattr.h" 21 #include "glock.h" 22 #include "inode.h" 23 #include "meta_io.h" 24 #include "rgrp.h" 25 #include "trans.h" 26 #include "util.h" 27 28 static const char *gfs2_acl_name(int type) 29 { 30 switch (type) { 31 case ACL_TYPE_ACCESS: 32 return XATTR_POSIX_ACL_ACCESS; 33 case ACL_TYPE_DEFAULT: 34 return XATTR_POSIX_ACL_DEFAULT; 35 } 36 return NULL; 37 } 38 39 static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) 40 { 41 struct gfs2_inode *ip = GFS2_I(inode); 42 struct posix_acl *acl; 43 const char *name; 44 char *data; 45 int len; 46 47 if (!ip->i_eattr) 48 return NULL; 49 50 name = gfs2_acl_name(type); 51 len = gfs2_xattr_acl_get(ip, name, &data); 52 if (len <= 0) 53 return ERR_PTR(len); 54 acl = posix_acl_from_xattr(&init_user_ns, data, len); 55 kfree(data); 56 return acl; 57 } 58 59 struct posix_acl *gfs2_get_acl(struct inode *inode, int type) 60 { 61 struct gfs2_inode *ip = GFS2_I(inode); 62 struct gfs2_holder gh; 63 bool need_unlock = false; 64 struct posix_acl *acl; 65 66 if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 67 int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 68 LM_FLAG_ANY, &gh); 69 if (ret) 70 return ERR_PTR(ret); 71 need_unlock = true; 72 } 73 acl = __gfs2_get_acl(inode, type); 74 if (need_unlock) 75 gfs2_glock_dq_uninit(&gh); 76 return acl; 77 } 78 79 int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 80 { 81 int error; 82 size_t len; 83 char *data; 84 const char *name = gfs2_acl_name(type); 85 86 if (acl) { 87 len = posix_acl_xattr_size(acl->a_count); 88 data = kmalloc(len, GFP_NOFS); 89 if (data == NULL) 90 return -ENOMEM; 91 error = posix_acl_to_xattr(&init_user_ns, acl, data, len); 92 if (error < 0) 93 goto out; 94 } else { 95 data = NULL; 96 len = 0; 97 } 98 99 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS); 100 if (error) 101 goto out; 102 set_cached_acl(inode, type, acl); 103 out: 104 kfree(data); 105 return error; 106 } 107 108 int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) 109 { 110 struct gfs2_inode *ip = GFS2_I(inode); 111 struct gfs2_holder gh; 112 bool need_unlock = false; 113 int ret; 114 umode_t mode; 115 116 if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode))) 117 return -E2BIG; 118 119 ret = gfs2_rsqa_alloc(ip); 120 if (ret) 121 return ret; 122 123 if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { 124 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); 125 if (ret) 126 return ret; 127 need_unlock = true; 128 } 129 130 mode = inode->i_mode; 131 if (type == ACL_TYPE_ACCESS && acl) { 132 ret = posix_acl_update_mode(inode, &mode, &acl); 133 if (ret) 134 goto unlock; 135 } 136 137 ret = __gfs2_set_acl(inode, acl, type); 138 if (!ret && mode != inode->i_mode) { 139 inode->i_ctime = current_time(inode); 140 inode->i_mode = mode; 141 mark_inode_dirty(inode); 142 } 143 unlock: 144 if (need_unlock) 145 gfs2_glock_dq_uninit(&gh); 146 return ret; 147 } 148