xref: /openbmc/linux/fs/reiserfs/xattr_acl.c (revision 1da177e4)
1 #include <linux/fs.h>
2 #include <linux/posix_acl.h>
3 #include <linux/reiserfs_fs.h>
4 #include <linux/errno.h>
5 #include <linux/pagemap.h>
6 #include <linux/xattr.h>
7 #include <linux/xattr_acl.h>
8 #include <linux/reiserfs_xattr.h>
9 #include <linux/reiserfs_acl.h>
10 #include <asm/uaccess.h>
11 
12 static int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl);
13 
14 static int
15 xattr_set_acl(struct inode *inode, int type, const void *value, size_t size)
16 {
17 	struct posix_acl *acl;
18 	int error;
19 
20 	if (!reiserfs_posixacl(inode->i_sb))
21 		return -EOPNOTSUPP;
22 	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
23 		return -EPERM;
24 
25 	if (value) {
26 		acl = posix_acl_from_xattr(value, size);
27 		if (IS_ERR(acl)) {
28 			return PTR_ERR(acl);
29 		} else if (acl) {
30 			error = posix_acl_valid(acl);
31 			if (error)
32 				goto release_and_out;
33 		}
34 	} else
35 		acl = NULL;
36 
37 	error = reiserfs_set_acl (inode, type, acl);
38 
39 release_and_out:
40 	posix_acl_release(acl);
41 	return error;
42 }
43 
44 
45 static int
46 xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
47 {
48 	struct posix_acl *acl;
49 	int error;
50 
51 	if (!reiserfs_posixacl(inode->i_sb))
52 		return -EOPNOTSUPP;
53 
54 	acl = reiserfs_get_acl (inode, type);
55 	if (IS_ERR(acl))
56 		return PTR_ERR(acl);
57 	if (acl == NULL)
58 		return -ENODATA;
59 	error = posix_acl_to_xattr(acl, buffer, size);
60 	posix_acl_release(acl);
61 
62 	return error;
63 }
64 
65 
66 /*
67  * Convert from filesystem to in-memory representation.
68  */
69 static struct posix_acl *
70 posix_acl_from_disk(const void *value, size_t size)
71 {
72 	const char *end = (char *)value + size;
73 	int n, count;
74 	struct posix_acl *acl;
75 
76 	if (!value)
77 		return NULL;
78 	if (size < sizeof(reiserfs_acl_header))
79 		 return ERR_PTR(-EINVAL);
80 	if (((reiserfs_acl_header *)value)->a_version !=
81 	    cpu_to_le32(REISERFS_ACL_VERSION))
82 		return ERR_PTR(-EINVAL);
83 	value = (char *)value + sizeof(reiserfs_acl_header);
84 	count = reiserfs_acl_count(size);
85 	if (count < 0)
86 		return ERR_PTR(-EINVAL);
87 	if (count == 0)
88 		return NULL;
89 	acl = posix_acl_alloc(count, GFP_NOFS);
90 	if (!acl)
91 		return ERR_PTR(-ENOMEM);
92 	for (n=0; n < count; n++) {
93 		reiserfs_acl_entry *entry =
94 			(reiserfs_acl_entry *)value;
95 		if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
96 			goto fail;
97 		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
98 		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
99 		switch(acl->a_entries[n].e_tag) {
100 			case ACL_USER_OBJ:
101 			case ACL_GROUP_OBJ:
102 			case ACL_MASK:
103 			case ACL_OTHER:
104 				value = (char *)value +
105 					sizeof(reiserfs_acl_entry_short);
106 				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
107 				break;
108 
109 			case ACL_USER:
110 			case ACL_GROUP:
111 				value = (char *)value + sizeof(reiserfs_acl_entry);
112 				if ((char *)value > end)
113 					goto fail;
114 				acl->a_entries[n].e_id =
115 					le32_to_cpu(entry->e_id);
116 				break;
117 
118 			default:
119 				goto fail;
120 		}
121 	}
122 	if (value != end)
123 		goto fail;
124 	return acl;
125 
126 fail:
127 	posix_acl_release(acl);
128 	return ERR_PTR(-EINVAL);
129 }
130 
131 /*
132  * Convert from in-memory to filesystem representation.
133  */
134 static void *
135 posix_acl_to_disk(const struct posix_acl *acl, size_t *size)
136 {
137 	reiserfs_acl_header *ext_acl;
138 	char *e;
139 	int n;
140 
141 	*size = reiserfs_acl_size(acl->a_count);
142 	ext_acl = (reiserfs_acl_header *)kmalloc(sizeof(reiserfs_acl_header) +
143 		acl->a_count * sizeof(reiserfs_acl_entry), GFP_NOFS);
144 	if (!ext_acl)
145 		return ERR_PTR(-ENOMEM);
146 	ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
147 	e = (char *)ext_acl + sizeof(reiserfs_acl_header);
148 	for (n=0; n < acl->a_count; n++) {
149 		reiserfs_acl_entry *entry = (reiserfs_acl_entry *)e;
150 		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
151 		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
152 		switch(acl->a_entries[n].e_tag) {
153 			case ACL_USER:
154 			case ACL_GROUP:
155 				entry->e_id =
156 					cpu_to_le32(acl->a_entries[n].e_id);
157 				e += sizeof(reiserfs_acl_entry);
158 				break;
159 
160 			case ACL_USER_OBJ:
161 			case ACL_GROUP_OBJ:
162 			case ACL_MASK:
163 			case ACL_OTHER:
164 				e += sizeof(reiserfs_acl_entry_short);
165 				break;
166 
167 			default:
168 				goto fail;
169 		}
170 	}
171 	return (char *)ext_acl;
172 
173 fail:
174 	kfree(ext_acl);
175 	return ERR_PTR(-EINVAL);
176 }
177 
178 /*
179  * Inode operation get_posix_acl().
180  *
181  * inode->i_sem: down
182  * BKL held [before 2.5.x]
183  */
184 struct posix_acl *
185 reiserfs_get_acl(struct inode *inode, int type)
186 {
187 	char *name, *value;
188 	struct posix_acl *acl, **p_acl;
189 	size_t size;
190 	int retval;
191         struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
192 
193         switch (type) {
194             case ACL_TYPE_ACCESS:
195                 name = XATTR_NAME_ACL_ACCESS;
196                 p_acl = &reiserfs_i->i_acl_access;
197                 break;
198             case ACL_TYPE_DEFAULT:
199                 name = XATTR_NAME_ACL_DEFAULT;
200                 p_acl = &reiserfs_i->i_acl_default;
201                 break;
202             default:
203                 return ERR_PTR (-EINVAL);
204         }
205 
206         if (IS_ERR (*p_acl)) {
207             if (PTR_ERR (*p_acl) == -ENODATA)
208                 return NULL;
209         } else if (*p_acl != NULL)
210             return posix_acl_dup (*p_acl);
211 
212         size = reiserfs_xattr_get (inode, name, NULL, 0);
213         if ((int)size < 0) {
214             if (size == -ENODATA || size == -ENOSYS) {
215 		*p_acl = ERR_PTR (-ENODATA);
216 		return NULL;
217             }
218             return ERR_PTR (size);
219         }
220 
221         value = kmalloc (size, GFP_NOFS);
222         if (!value)
223             return ERR_PTR (-ENOMEM);
224 
225 	retval = reiserfs_xattr_get(inode, name, value, size);
226 	if (retval == -ENODATA || retval == -ENOSYS) {
227 		/* This shouldn't actually happen as it should have
228 		   been caught above.. but just in case */
229 		acl = NULL;
230 		*p_acl = ERR_PTR (-ENODATA);
231         } else if (retval < 0) {
232 		acl = ERR_PTR(retval);
233 	} else {
234 		acl = posix_acl_from_disk(value, retval);
235 		*p_acl = posix_acl_dup (acl);
236         }
237 
238 	kfree(value);
239 	return acl;
240 }
241 
242 /*
243  * Inode operation set_posix_acl().
244  *
245  * inode->i_sem: down
246  * BKL held [before 2.5.x]
247  */
248 static int
249 reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
250 {
251         char *name;
252 	void *value = NULL;
253 	struct posix_acl **p_acl;
254 	size_t size;
255 	int error;
256         struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
257 
258 	if (S_ISLNK(inode->i_mode))
259 		return -EOPNOTSUPP;
260 
261         switch (type) {
262             case ACL_TYPE_ACCESS:
263                 name = XATTR_NAME_ACL_ACCESS;
264                 p_acl = &reiserfs_i->i_acl_access;
265                 if (acl) {
266                     mode_t mode = inode->i_mode;
267                     error = posix_acl_equiv_mode (acl, &mode);
268                     if (error < 0)
269                         return error;
270                     else {
271                         inode->i_mode = mode;
272                         if (error == 0)
273                             acl = NULL;
274                     }
275                 }
276                 break;
277             case ACL_TYPE_DEFAULT:
278                 name = XATTR_NAME_ACL_DEFAULT;
279                 p_acl = &reiserfs_i->i_acl_default;
280                 if (!S_ISDIR (inode->i_mode))
281                     return acl ? -EACCES : 0;
282                 break;
283             default:
284                 return -EINVAL;
285         }
286 
287  	if (acl) {
288             value = posix_acl_to_disk(acl, &size);
289             if (IS_ERR(value))
290                 return (int)PTR_ERR(value);
291             error = reiserfs_xattr_set(inode, name, value, size, 0);
292 	} else {
293             error = reiserfs_xattr_del (inode, name);
294             if (error == -ENODATA) {
295                 /* This may seem odd here, but it means that the ACL was set
296                  * with a value representable with mode bits. If there was
297                  * an ACL before, reiserfs_xattr_del already dirtied the inode.
298                  */
299                 mark_inode_dirty (inode);
300                 error = 0;
301             }
302         }
303 
304 	if (value)
305 		kfree(value);
306 
307         if (!error) {
308             /* Release the old one */
309             if (!IS_ERR (*p_acl) && *p_acl)
310                 posix_acl_release (*p_acl);
311 
312             if (acl == NULL)
313                 *p_acl = ERR_PTR (-ENODATA);
314             else
315                 *p_acl = posix_acl_dup (acl);
316         }
317 
318 	return error;
319 }
320 
321 /* dir->i_sem: down,
322  * inode is new and not released into the wild yet */
323 int
324 reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode)
325 {
326     struct posix_acl *acl;
327     int err = 0;
328 
329     /* ACLs only get applied to files and directories */
330     if (S_ISLNK (inode->i_mode))
331         return 0;
332 
333     /* ACLs can only be used on "new" objects, so if it's an old object
334      * there is nothing to inherit from */
335     if (get_inode_sd_version (dir) == STAT_DATA_V1)
336         goto apply_umask;
337 
338     /* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
339      * would be useless since permissions are ignored, and a pain because
340      * it introduces locking cycles */
341     if (is_reiserfs_priv_object (dir)) {
342         reiserfs_mark_inode_private (inode);
343         goto apply_umask;
344     }
345 
346     acl = reiserfs_get_acl (dir, ACL_TYPE_DEFAULT);
347     if (IS_ERR (acl)) {
348         if (PTR_ERR (acl) == -ENODATA)
349             goto apply_umask;
350         return PTR_ERR (acl);
351     }
352 
353     if (acl) {
354         struct posix_acl *acl_copy;
355         mode_t mode = inode->i_mode;
356         int need_acl;
357 
358         /* Copy the default ACL to the default ACL of a new directory */
359         if (S_ISDIR (inode->i_mode)) {
360             err = reiserfs_set_acl (inode, ACL_TYPE_DEFAULT, acl);
361             if (err)
362                 goto cleanup;
363         }
364 
365         /* Now we reconcile the new ACL and the mode,
366            potentially modifying both */
367         acl_copy = posix_acl_clone (acl, GFP_NOFS);
368         if (!acl_copy) {
369             err = -ENOMEM;
370             goto cleanup;
371         }
372 
373 
374         need_acl = posix_acl_create_masq (acl_copy, &mode);
375         if (need_acl >= 0) {
376             if (mode != inode->i_mode) {
377                 inode->i_mode = mode;
378             }
379 
380             /* If we need an ACL.. */
381             if (need_acl > 0) {
382                 err = reiserfs_set_acl (inode, ACL_TYPE_ACCESS, acl_copy);
383                 if (err)
384                     goto cleanup_copy;
385             }
386         }
387 cleanup_copy:
388         posix_acl_release (acl_copy);
389 cleanup:
390         posix_acl_release (acl);
391     } else {
392 apply_umask:
393         /* no ACL, apply umask */
394         inode->i_mode &= ~current->fs->umask;
395     }
396 
397     return err;
398 }
399 
400 /* Looks up and caches the result of the default ACL.
401  * We do this so that we don't need to carry the xattr_sem into
402  * reiserfs_new_inode if we don't need to */
403 int
404 reiserfs_cache_default_acl (struct inode *inode)
405 {
406     int ret = 0;
407     if (reiserfs_posixacl (inode->i_sb) &&
408         !is_reiserfs_priv_object (inode)) {
409         struct posix_acl *acl;
410         reiserfs_read_lock_xattr_i (inode);
411         reiserfs_read_lock_xattrs (inode->i_sb);
412         acl = reiserfs_get_acl (inode, ACL_TYPE_DEFAULT);
413         reiserfs_read_unlock_xattrs (inode->i_sb);
414         reiserfs_read_unlock_xattr_i (inode);
415         ret = acl ? 1 : 0;
416         posix_acl_release (acl);
417     }
418 
419     return ret;
420 }
421 
422 int
423 reiserfs_acl_chmod (struct inode *inode)
424 {
425         struct posix_acl *acl, *clone;
426         int error;
427 
428         if (S_ISLNK(inode->i_mode))
429                 return -EOPNOTSUPP;
430 
431 	if (get_inode_sd_version (inode) == STAT_DATA_V1 ||
432 	    !reiserfs_posixacl(inode->i_sb))
433         {
434 	    return 0;
435 	}
436 
437         reiserfs_read_lock_xattrs (inode->i_sb);
438         acl = reiserfs_get_acl(inode, ACL_TYPE_ACCESS);
439         reiserfs_read_unlock_xattrs (inode->i_sb);
440         if (!acl)
441                 return 0;
442         if (IS_ERR(acl))
443                 return PTR_ERR(acl);
444         clone = posix_acl_clone(acl, GFP_NOFS);
445         posix_acl_release(acl);
446         if (!clone)
447                 return -ENOMEM;
448         error = posix_acl_chmod_masq(clone, inode->i_mode);
449         if (!error) {
450                 int lock = !has_xattr_dir (inode);
451                 reiserfs_write_lock_xattr_i (inode);
452                 if (lock)
453                     reiserfs_write_lock_xattrs (inode->i_sb);
454                 else
455                     reiserfs_read_lock_xattrs (inode->i_sb);
456                 error = reiserfs_set_acl(inode, ACL_TYPE_ACCESS, clone);
457                 if (lock)
458                     reiserfs_write_unlock_xattrs (inode->i_sb);
459                 else
460                     reiserfs_read_unlock_xattrs (inode->i_sb);
461                 reiserfs_write_unlock_xattr_i (inode);
462         }
463         posix_acl_release(clone);
464         return error;
465 }
466 
467 static int
468 posix_acl_access_get(struct inode *inode, const char *name,
469 			  void *buffer, size_t size)
470 {
471 	if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
472 		return -EINVAL;
473 	return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
474 }
475 
476 static int
477 posix_acl_access_set(struct inode *inode, const char *name,
478 			  const void *value, size_t size, int flags)
479 {
480 	if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
481 		return -EINVAL;
482 	return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
483 }
484 
485 static int
486 posix_acl_access_del (struct inode *inode, const char *name)
487 {
488     struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
489     struct posix_acl **acl = &reiserfs_i->i_acl_access;
490     if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
491 	return -EINVAL;
492     if (!IS_ERR (*acl) && *acl) {
493         posix_acl_release (*acl);
494         *acl = ERR_PTR (-ENODATA);
495     }
496 
497     return 0;
498 }
499 
500 static int
501 posix_acl_access_list (struct inode *inode, const char *name, int namelen, char *out)
502 {
503     int len = namelen;
504     if (!reiserfs_posixacl (inode->i_sb))
505         return 0;
506     if (out)
507         memcpy (out, name, len);
508 
509     return len;
510 }
511 
512 struct reiserfs_xattr_handler posix_acl_access_handler = {
513 	.prefix = XATTR_NAME_ACL_ACCESS,
514 	.get = posix_acl_access_get,
515 	.set = posix_acl_access_set,
516 	.del = posix_acl_access_del,
517 	.list = posix_acl_access_list,
518 };
519 
520 static int
521 posix_acl_default_get (struct inode *inode, const char *name,
522 			   void *buffer, size_t size)
523 {
524 	if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
525 		return -EINVAL;
526 	return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
527 }
528 
529 static int
530 posix_acl_default_set(struct inode *inode, const char *name,
531 			   const void *value, size_t size, int flags)
532 {
533 	if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
534 		return -EINVAL;
535 	return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
536 }
537 
538 static int
539 posix_acl_default_del (struct inode *inode, const char *name)
540 {
541     struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
542     struct posix_acl **acl = &reiserfs_i->i_acl_default;
543     if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
544 	return -EINVAL;
545     if (!IS_ERR (*acl) && *acl) {
546         posix_acl_release (*acl);
547         *acl = ERR_PTR (-ENODATA);
548     }
549 
550     return 0;
551 }
552 
553 static int
554 posix_acl_default_list (struct inode *inode, const char *name, int namelen, char *out)
555 {
556     int len = namelen;
557     if (!reiserfs_posixacl (inode->i_sb))
558         return 0;
559     if (out)
560         memcpy (out, name, len);
561 
562     return len;
563 }
564 
565 struct reiserfs_xattr_handler posix_acl_default_handler = {
566 	.prefix = XATTR_NAME_ACL_DEFAULT,
567 	.get = posix_acl_default_get,
568 	.set = posix_acl_default_set,
569 	.del = posix_acl_default_del,
570 	.list = posix_acl_default_list,
571 };
572