xref: /openbmc/linux/fs/gfs2/acl.c (revision 4800cd83)
1 /*
2  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4  *
5  * This copyrighted material is made available to anyone wishing to use,
6  * modify, copy, or redistribute it subject to the terms and conditions
7  * of the GNU General Public License version 2.
8  */
9 
10 #include <linux/sched.h>
11 #include <linux/slab.h>
12 #include <linux/spinlock.h>
13 #include <linux/completion.h>
14 #include <linux/buffer_head.h>
15 #include <linux/xattr.h>
16 #include <linux/posix_acl.h>
17 #include <linux/posix_acl_xattr.h>
18 #include <linux/gfs2_ondisk.h>
19 
20 #include "gfs2.h"
21 #include "incore.h"
22 #include "acl.h"
23 #include "xattr.h"
24 #include "glock.h"
25 #include "inode.h"
26 #include "meta_io.h"
27 #include "trans.h"
28 #include "util.h"
29 
30 static const char *gfs2_acl_name(int type)
31 {
32 	switch (type) {
33 	case ACL_TYPE_ACCESS:
34 		return GFS2_POSIX_ACL_ACCESS;
35 	case ACL_TYPE_DEFAULT:
36 		return GFS2_POSIX_ACL_DEFAULT;
37 	}
38 	return NULL;
39 }
40 
41 static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
42 {
43 	struct posix_acl *acl;
44 	const char *name;
45 	char *data;
46 	int len;
47 
48 	if (!ip->i_eattr)
49 		return NULL;
50 
51 	acl = get_cached_acl(&ip->i_inode, type);
52 	if (acl != ACL_NOT_CACHED)
53 		return acl;
54 
55 	name = gfs2_acl_name(type);
56 	if (name == NULL)
57 		return ERR_PTR(-EINVAL);
58 
59 	len = gfs2_xattr_acl_get(ip, name, &data);
60 	if (len < 0)
61 		return ERR_PTR(len);
62 	if (len == 0)
63 		return NULL;
64 
65 	acl = posix_acl_from_xattr(data, len);
66 	kfree(data);
67 	return acl;
68 }
69 
70 /**
71  * gfs2_check_acl - Check an ACL to see if we're allowed to do something
72  * @inode: the file we want to do something to
73  * @mask: what we want to do
74  *
75  * Returns: errno
76  */
77 
78 int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
79 {
80 	struct posix_acl *acl;
81 	int error;
82 
83 	if (flags & IPERM_FLAG_RCU)
84 		return -ECHILD;
85 
86 	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
87 	if (IS_ERR(acl))
88 		return PTR_ERR(acl);
89 
90 	if (acl) {
91 		error = posix_acl_permission(inode, acl, mask);
92 		posix_acl_release(acl);
93 		return error;
94 	}
95 
96 	return -EAGAIN;
97 }
98 
99 static int gfs2_set_mode(struct inode *inode, mode_t mode)
100 {
101 	int error = 0;
102 
103 	if (mode != inode->i_mode) {
104 		struct iattr iattr;
105 
106 		iattr.ia_valid = ATTR_MODE;
107 		iattr.ia_mode = mode;
108 
109 		error = gfs2_setattr_simple(GFS2_I(inode), &iattr);
110 	}
111 
112 	return error;
113 }
114 
115 static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
116 {
117 	int error;
118 	int len;
119 	char *data;
120 	const char *name = gfs2_acl_name(type);
121 
122 	BUG_ON(name == NULL);
123 	len = posix_acl_to_xattr(acl, NULL, 0);
124 	if (len == 0)
125 		return 0;
126 	data = kmalloc(len, GFP_NOFS);
127 	if (data == NULL)
128 		return -ENOMEM;
129 	error = posix_acl_to_xattr(acl, data, len);
130 	if (error < 0)
131 		goto out;
132 	error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
133 	if (!error)
134 		set_cached_acl(inode, type, acl);
135 out:
136 	kfree(data);
137 	return error;
138 }
139 
140 int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
141 {
142 	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
143 	struct posix_acl *acl, *clone;
144 	mode_t mode = inode->i_mode;
145 	int error = 0;
146 
147 	if (!sdp->sd_args.ar_posix_acl)
148 		return 0;
149 	if (S_ISLNK(inode->i_mode))
150 		return 0;
151 
152 	acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT);
153 	if (IS_ERR(acl))
154 		return PTR_ERR(acl);
155 	if (!acl) {
156 		mode &= ~current_umask();
157 		if (mode != inode->i_mode)
158 			error = gfs2_set_mode(inode, mode);
159 		return error;
160 	}
161 
162 	if (S_ISDIR(inode->i_mode)) {
163 		error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
164 		if (error)
165 			goto out;
166 	}
167 
168 	clone = posix_acl_clone(acl, GFP_NOFS);
169 	error = -ENOMEM;
170 	if (!clone)
171 		goto out;
172 	posix_acl_release(acl);
173 	acl = clone;
174 
175 	error = posix_acl_create_masq(acl, &mode);
176 	if (error < 0)
177 		goto out;
178 	if (error == 0)
179 		goto munge;
180 
181 	error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
182 	if (error)
183 		goto out;
184 munge:
185 	error = gfs2_set_mode(inode, mode);
186 out:
187 	posix_acl_release(acl);
188 	return error;
189 }
190 
191 int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
192 {
193 	struct posix_acl *acl, *clone;
194 	char *data;
195 	unsigned int len;
196 	int error;
197 
198 	acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
199 	if (IS_ERR(acl))
200 		return PTR_ERR(acl);
201 	if (!acl)
202 		return gfs2_setattr_simple(ip, attr);
203 
204 	clone = posix_acl_clone(acl, GFP_NOFS);
205 	error = -ENOMEM;
206 	if (!clone)
207 		goto out;
208 	posix_acl_release(acl);
209 	acl = clone;
210 
211 	error = posix_acl_chmod_masq(acl, attr->ia_mode);
212 	if (!error) {
213 		len = posix_acl_to_xattr(acl, NULL, 0);
214 		data = kmalloc(len, GFP_NOFS);
215 		error = -ENOMEM;
216 		if (data == NULL)
217 			goto out;
218 		posix_acl_to_xattr(acl, data, len);
219 		error = gfs2_xattr_acl_chmod(ip, attr, data);
220 		kfree(data);
221 		set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
222 	}
223 
224 out:
225 	posix_acl_release(acl);
226 	return error;
227 }
228 
229 static int gfs2_acl_type(const char *name)
230 {
231 	if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
232 		return ACL_TYPE_ACCESS;
233 	if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
234 		return ACL_TYPE_DEFAULT;
235 	return -EINVAL;
236 }
237 
238 static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
239 				 void *buffer, size_t size, int xtype)
240 {
241 	struct inode *inode = dentry->d_inode;
242 	struct gfs2_sbd *sdp = GFS2_SB(inode);
243 	struct posix_acl *acl;
244 	int type;
245 	int error;
246 
247 	if (!sdp->sd_args.ar_posix_acl)
248 		return -EOPNOTSUPP;
249 
250 	type = gfs2_acl_type(name);
251 	if (type < 0)
252 		return type;
253 
254 	acl = gfs2_acl_get(GFS2_I(inode), type);
255 	if (IS_ERR(acl))
256 		return PTR_ERR(acl);
257 	if (acl == NULL)
258 		return -ENODATA;
259 
260 	error = posix_acl_to_xattr(acl, buffer, size);
261 	posix_acl_release(acl);
262 
263 	return error;
264 }
265 
266 static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
267 				 const void *value, size_t size, int flags,
268 				 int xtype)
269 {
270 	struct inode *inode = dentry->d_inode;
271 	struct gfs2_sbd *sdp = GFS2_SB(inode);
272 	struct posix_acl *acl = NULL;
273 	int error = 0, type;
274 
275 	if (!sdp->sd_args.ar_posix_acl)
276 		return -EOPNOTSUPP;
277 
278 	type = gfs2_acl_type(name);
279 	if (type < 0)
280 		return type;
281 	if (flags & XATTR_CREATE)
282 		return -EINVAL;
283 	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
284 		return value ? -EACCES : 0;
285 	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
286 		return -EPERM;
287 	if (S_ISLNK(inode->i_mode))
288 		return -EOPNOTSUPP;
289 
290 	if (!value)
291 		goto set_acl;
292 
293 	acl = posix_acl_from_xattr(value, size);
294 	if (!acl) {
295 		/*
296 		 * acl_set_file(3) may request that we set default ACLs with
297 		 * zero length -- defend (gracefully) against that here.
298 		 */
299 		goto out;
300 	}
301 	if (IS_ERR(acl)) {
302 		error = PTR_ERR(acl);
303 		goto out;
304 	}
305 
306 	error = posix_acl_valid(acl);
307 	if (error)
308 		goto out_release;
309 
310 	error = -EINVAL;
311 	if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
312 		goto out_release;
313 
314 	if (type == ACL_TYPE_ACCESS) {
315 		mode_t mode = inode->i_mode;
316 		error = posix_acl_equiv_mode(acl, &mode);
317 
318 		if (error <= 0) {
319 			posix_acl_release(acl);
320 			acl = NULL;
321 
322 			if (error < 0)
323 				return error;
324 		}
325 
326 		error = gfs2_set_mode(inode, mode);
327 		if (error)
328 			goto out_release;
329 	}
330 
331 set_acl:
332 	error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
333 	if (!error) {
334 		if (acl)
335 			set_cached_acl(inode, type, acl);
336 		else
337 			forget_cached_acl(inode, type);
338 	}
339 out_release:
340 	posix_acl_release(acl);
341 out:
342 	return error;
343 }
344 
345 const struct xattr_handler gfs2_xattr_system_handler = {
346 	.prefix = XATTR_SYSTEM_PREFIX,
347 	.flags  = GFS2_EATYPE_SYS,
348 	.get    = gfs2_xattr_system_get,
349 	.set    = gfs2_xattr_system_set,
350 };
351 
352