aboutsummaryrefslogtreecommitdiffstats
path: root/fs/posix_acl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2013-12-20 08:16:37 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-01-25 23:58:16 -0500
commit5c8ebd57b6a51daf53f75b7a16c45090a98a91a4 (patch)
tree02e3d3b8f707f84effe15df3dfc0043481010390 /fs/posix_acl.c
parent9dad943ae7d4a01da6bb18e1a157ab1bfe6186cd (diff)
fs: merge xattr_acl.c into posix_acl.c
Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/posix_acl.c')
-rw-r--r--fs/posix_acl.c180
1 files changed, 173 insertions, 7 deletions
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 8bd2135b7f82..359d70b0e947 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -1,10 +1,8 @@
1/* 1/*
2 * linux/fs/posix_acl.c 2 * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
3 * 3 *
4 * Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org> 4 * Fixes from William Schumacher incorporated on 15 March 2001.
5 * 5 * (Reported by Charles Bertsch, <CBertsch@microtest.com>).
6 * Fixes from William Schumacher incorporated on 15 March 2001.
7 * (Reported by Charles Bertsch, <CBertsch@microtest.com>).
8 */ 6 */
9 7
10/* 8/*
@@ -18,9 +16,9 @@
18#include <linux/fs.h> 16#include <linux/fs.h>
19#include <linux/sched.h> 17#include <linux/sched.h>
20#include <linux/posix_acl.h> 18#include <linux/posix_acl.h>
19#include <linux/posix_acl_xattr.h>
21#include <linux/export.h> 20#include <linux/export.h>
22 21#include <linux/user_namespace.h>
23#include <linux/errno.h>
24 22
25EXPORT_SYMBOL(posix_acl_init); 23EXPORT_SYMBOL(posix_acl_init);
26EXPORT_SYMBOL(posix_acl_alloc); 24EXPORT_SYMBOL(posix_acl_alloc);
@@ -418,3 +416,171 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
418 return err; 416 return err;
419} 417}
420EXPORT_SYMBOL(posix_acl_chmod); 418EXPORT_SYMBOL(posix_acl_chmod);
419
420/*
421 * Fix up the uids and gids in posix acl extended attributes in place.
422 */
423static void posix_acl_fix_xattr_userns(
424 struct user_namespace *to, struct user_namespace *from,
425 void *value, size_t size)
426{
427 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
428 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
429 int count;
430 kuid_t uid;
431 kgid_t gid;
432
433 if (!value)
434 return;
435 if (size < sizeof(posix_acl_xattr_header))
436 return;
437 if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
438 return;
439
440 count = posix_acl_xattr_count(size);
441 if (count < 0)
442 return;
443 if (count == 0)
444 return;
445
446 for (end = entry + count; entry != end; entry++) {
447 switch(le16_to_cpu(entry->e_tag)) {
448 case ACL_USER:
449 uid = make_kuid(from, le32_to_cpu(entry->e_id));
450 entry->e_id = cpu_to_le32(from_kuid(to, uid));
451 break;
452 case ACL_GROUP:
453 gid = make_kgid(from, le32_to_cpu(entry->e_id));
454 entry->e_id = cpu_to_le32(from_kgid(to, gid));
455 break;
456 default:
457 break;
458 }
459 }
460}
461
462void posix_acl_fix_xattr_from_user(void *value, size_t size)
463{
464 struct user_namespace *user_ns = current_user_ns();
465 if (user_ns == &init_user_ns)
466 return;
467 posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
468}
469
470void posix_acl_fix_xattr_to_user(void *value, size_t size)
471{
472 struct user_namespace *user_ns = current_user_ns();
473 if (user_ns == &init_user_ns)
474 return;
475 posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
476}
477
478/*
479 * Convert from extended attribute to in-memory representation.
480 */
481struct posix_acl *
482posix_acl_from_xattr(struct user_namespace *user_ns,
483 const void *value, size_t size)
484{
485 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
486 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
487 int count;
488 struct posix_acl *acl;
489 struct posix_acl_entry *acl_e;
490
491 if (!value)
492 return NULL;
493 if (size < sizeof(posix_acl_xattr_header))
494 return ERR_PTR(-EINVAL);
495 if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
496 return ERR_PTR(-EOPNOTSUPP);
497
498 count = posix_acl_xattr_count(size);
499 if (count < 0)
500 return ERR_PTR(-EINVAL);
501 if (count == 0)
502 return NULL;
503
504 acl = posix_acl_alloc(count, GFP_NOFS);
505 if (!acl)
506 return ERR_PTR(-ENOMEM);
507 acl_e = acl->a_entries;
508
509 for (end = entry + count; entry != end; acl_e++, entry++) {
510 acl_e->e_tag = le16_to_cpu(entry->e_tag);
511 acl_e->e_perm = le16_to_cpu(entry->e_perm);
512
513 switch(acl_e->e_tag) {
514 case ACL_USER_OBJ:
515 case ACL_GROUP_OBJ:
516 case ACL_MASK:
517 case ACL_OTHER:
518 break;
519
520 case ACL_USER:
521 acl_e->e_uid =
522 make_kuid(user_ns,
523 le32_to_cpu(entry->e_id));
524 if (!uid_valid(acl_e->e_uid))
525 goto fail;
526 break;
527 case ACL_GROUP:
528 acl_e->e_gid =
529 make_kgid(user_ns,
530 le32_to_cpu(entry->e_id));
531 if (!gid_valid(acl_e->e_gid))
532 goto fail;
533 break;
534
535 default:
536 goto fail;
537 }
538 }
539 return acl;
540
541fail:
542 posix_acl_release(acl);
543 return ERR_PTR(-EINVAL);
544}
545EXPORT_SYMBOL (posix_acl_from_xattr);
546
547/*
548 * Convert from in-memory to extended attribute representation.
549 */
550int
551posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
552 void *buffer, size_t size)
553{
554 posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
555 posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
556 int real_size, n;
557
558 real_size = posix_acl_xattr_size(acl->a_count);
559 if (!buffer)
560 return real_size;
561 if (real_size > size)
562 return -ERANGE;
563
564 ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
565
566 for (n=0; n < acl->a_count; n++, ext_entry++) {
567 const struct posix_acl_entry *acl_e = &acl->a_entries[n];
568 ext_entry->e_tag = cpu_to_le16(acl_e->e_tag);
569 ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
570 switch(acl_e->e_tag) {
571 case ACL_USER:
572 ext_entry->e_id =
573 cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
574 break;
575 case ACL_GROUP:
576 ext_entry->e_id =
577 cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
578 break;
579 default:
580 ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
581 break;
582 }
583 }
584 return real_size;
585}
586EXPORT_SYMBOL (posix_acl_to_xattr);