xref: /openbmc/linux/fs/xfs/xfs_acl.c (revision 82b5d164)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2008, Christoph Hellwig
4  * All Rights Reserved.
5  */
6 #include "xfs.h"
7 #include "xfs_shared.h"
8 #include "xfs_format.h"
9 #include "xfs_log_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_inode.h"
13 #include "xfs_attr.h"
14 #include "xfs_trace.h"
15 #include <linux/posix_acl_xattr.h>
16 
17 
18 /*
19  * Locking scheme:
20  *  - all ACL updates are protected by inode->i_mutex, which is taken before
21  *    calling into this file.
22  */
23 
24 STATIC struct posix_acl *
25 xfs_acl_from_disk(
26 	const struct xfs_acl	*aclp,
27 	int			len,
28 	int			max_entries)
29 {
30 	struct posix_acl_entry *acl_e;
31 	struct posix_acl *acl;
32 	const struct xfs_acl_entry *ace;
33 	unsigned int count, i;
34 
35 	if (len < sizeof(*aclp))
36 		return ERR_PTR(-EFSCORRUPTED);
37 	count = be32_to_cpu(aclp->acl_cnt);
38 	if (count > max_entries || XFS_ACL_SIZE(count) != len)
39 		return ERR_PTR(-EFSCORRUPTED);
40 
41 	acl = posix_acl_alloc(count, GFP_KERNEL);
42 	if (!acl)
43 		return ERR_PTR(-ENOMEM);
44 
45 	for (i = 0; i < count; i++) {
46 		acl_e = &acl->a_entries[i];
47 		ace = &aclp->acl_entry[i];
48 
49 		/*
50 		 * The tag is 32 bits on disk and 16 bits in core.
51 		 *
52 		 * Because every access to it goes through the core
53 		 * format first this is not a problem.
54 		 */
55 		acl_e->e_tag = be32_to_cpu(ace->ae_tag);
56 		acl_e->e_perm = be16_to_cpu(ace->ae_perm);
57 
58 		switch (acl_e->e_tag) {
59 		case ACL_USER:
60 			acl_e->e_uid = xfs_uid_to_kuid(be32_to_cpu(ace->ae_id));
61 			break;
62 		case ACL_GROUP:
63 			acl_e->e_gid = xfs_gid_to_kgid(be32_to_cpu(ace->ae_id));
64 			break;
65 		case ACL_USER_OBJ:
66 		case ACL_GROUP_OBJ:
67 		case ACL_MASK:
68 		case ACL_OTHER:
69 			break;
70 		default:
71 			goto fail;
72 		}
73 	}
74 	return acl;
75 
76 fail:
77 	posix_acl_release(acl);
78 	return ERR_PTR(-EINVAL);
79 }
80 
81 STATIC void
82 xfs_acl_to_disk(struct xfs_acl *aclp, const struct posix_acl *acl)
83 {
84 	const struct posix_acl_entry *acl_e;
85 	struct xfs_acl_entry *ace;
86 	int i;
87 
88 	aclp->acl_cnt = cpu_to_be32(acl->a_count);
89 	for (i = 0; i < acl->a_count; i++) {
90 		ace = &aclp->acl_entry[i];
91 		acl_e = &acl->a_entries[i];
92 
93 		ace->ae_tag = cpu_to_be32(acl_e->e_tag);
94 		switch (acl_e->e_tag) {
95 		case ACL_USER:
96 			ace->ae_id = cpu_to_be32(xfs_kuid_to_uid(acl_e->e_uid));
97 			break;
98 		case ACL_GROUP:
99 			ace->ae_id = cpu_to_be32(xfs_kgid_to_gid(acl_e->e_gid));
100 			break;
101 		default:
102 			ace->ae_id = cpu_to_be32(ACL_UNDEFINED_ID);
103 			break;
104 		}
105 
106 		ace->ae_perm = cpu_to_be16(acl_e->e_perm);
107 	}
108 }
109 
110 struct posix_acl *
111 xfs_get_acl(struct inode *inode, int type)
112 {
113 	struct xfs_inode *ip = XFS_I(inode);
114 	struct posix_acl *acl = NULL;
115 	struct xfs_acl *xfs_acl = NULL;
116 	unsigned char *ea_name;
117 	int error;
118 	int len;
119 
120 	trace_xfs_get_acl(ip);
121 
122 	switch (type) {
123 	case ACL_TYPE_ACCESS:
124 		ea_name = SGI_ACL_FILE;
125 		break;
126 	case ACL_TYPE_DEFAULT:
127 		ea_name = SGI_ACL_DEFAULT;
128 		break;
129 	default:
130 		BUG();
131 	}
132 
133 	/*
134 	 * If we have a cached ACLs value just return it, not need to
135 	 * go out to the disk.
136 	 */
137 	len = XFS_ACL_MAX_SIZE(ip->i_mount);
138 	error = xfs_attr_get(ip, ea_name, (unsigned char **)&xfs_acl, &len,
139 				ATTR_ALLOC | ATTR_ROOT);
140 	if (error) {
141 		/*
142 		 * If the attribute doesn't exist make sure we have a negative
143 		 * cache entry, for any other error assume it is transient.
144 		 */
145 		if (error != -ENOATTR)
146 			acl = ERR_PTR(error);
147 	} else  {
148 		acl = xfs_acl_from_disk(xfs_acl, len,
149 					XFS_ACL_MAX_ENTRIES(ip->i_mount));
150 		kmem_free(xfs_acl);
151 	}
152 	return acl;
153 }
154 
155 int
156 __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
157 {
158 	struct xfs_inode *ip = XFS_I(inode);
159 	unsigned char *ea_name;
160 	int error;
161 
162 	switch (type) {
163 	case ACL_TYPE_ACCESS:
164 		ea_name = SGI_ACL_FILE;
165 		break;
166 	case ACL_TYPE_DEFAULT:
167 		if (!S_ISDIR(inode->i_mode))
168 			return acl ? -EACCES : 0;
169 		ea_name = SGI_ACL_DEFAULT;
170 		break;
171 	default:
172 		return -EINVAL;
173 	}
174 
175 	if (acl) {
176 		struct xfs_acl *xfs_acl;
177 		int len = XFS_ACL_MAX_SIZE(ip->i_mount);
178 
179 		xfs_acl = kmem_zalloc_large(len, 0);
180 		if (!xfs_acl)
181 			return -ENOMEM;
182 
183 		xfs_acl_to_disk(xfs_acl, acl);
184 
185 		/* subtract away the unused acl entries */
186 		len -= sizeof(struct xfs_acl_entry) *
187 			 (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);
188 
189 		error = xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
190 				len, ATTR_ROOT);
191 
192 		kmem_free(xfs_acl);
193 	} else {
194 		/*
195 		 * A NULL ACL argument means we want to remove the ACL.
196 		 */
197 		error = xfs_attr_remove(ip, ea_name, ATTR_ROOT);
198 
199 		/*
200 		 * If the attribute didn't exist to start with that's fine.
201 		 */
202 		if (error == -ENOATTR)
203 			error = 0;
204 	}
205 
206 	if (!error)
207 		set_cached_acl(inode, type, acl);
208 	return error;
209 }
210 
211 static int
212 xfs_set_mode(struct inode *inode, umode_t mode)
213 {
214 	int error = 0;
215 
216 	if (mode != inode->i_mode) {
217 		struct iattr iattr;
218 
219 		iattr.ia_valid = ATTR_MODE | ATTR_CTIME;
220 		iattr.ia_mode = mode;
221 		iattr.ia_ctime = current_time(inode);
222 
223 		error = xfs_setattr_nonsize(XFS_I(inode), &iattr, XFS_ATTR_NOACL);
224 	}
225 
226 	return error;
227 }
228 
229 int
230 xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
231 {
232 	umode_t mode;
233 	bool set_mode = false;
234 	int error = 0;
235 
236 	if (!acl)
237 		goto set_acl;
238 
239 	error = -E2BIG;
240 	if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb)))
241 		return error;
242 
243 	if (type == ACL_TYPE_ACCESS) {
244 		error = posix_acl_update_mode(inode, &mode, &acl);
245 		if (error)
246 			return error;
247 		set_mode = true;
248 	}
249 
250  set_acl:
251 	error =  __xfs_set_acl(inode, acl, type);
252 	if (error)
253 		return error;
254 
255 	/*
256 	 * We set the mode after successfully updating the ACL xattr because the
257 	 * xattr update can fail at ENOSPC and we don't want to change the mode
258 	 * if the ACL update hasn't been applied.
259 	 */
260 	if (set_mode)
261 		error = xfs_set_mode(inode, mode);
262 
263 	return error;
264 }
265