Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: add generic xattr_acl handlers

With the ->set_acl inode operation we can implement the Posix ACL
xattr handlers in generic code instead of duplicating them all
over the tree.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Christoph Hellwig and committed by
Al Viro
2aeccbe9 893d46e4

+105
+102
fs/posix_acl.c
··· 17 17 #include <linux/sched.h> 18 18 #include <linux/posix_acl.h> 19 19 #include <linux/posix_acl_xattr.h> 20 + #include <linux/xattr.h> 20 21 #include <linux/export.h> 21 22 #include <linux/user_namespace.h> 22 23 ··· 612 611 return real_size; 613 612 } 614 613 EXPORT_SYMBOL (posix_acl_to_xattr); 614 + 615 + static int 616 + posix_acl_xattr_get(struct dentry *dentry, const char *name, 617 + void *value, size_t size, int type) 618 + { 619 + struct posix_acl *acl; 620 + int error; 621 + 622 + if (!IS_POSIXACL(dentry->d_inode)) 623 + return -EOPNOTSUPP; 624 + if (S_ISLNK(dentry->d_inode->i_mode)) 625 + return -EOPNOTSUPP; 626 + 627 + acl = get_acl(dentry->d_inode, type); 628 + if (IS_ERR(acl)) 629 + return PTR_ERR(acl); 630 + if (acl == NULL) 631 + return -ENODATA; 632 + 633 + error = posix_acl_to_xattr(&init_user_ns, acl, value, size); 634 + posix_acl_release(acl); 635 + 636 + return error; 637 + } 638 + 639 + static int 640 + posix_acl_xattr_set(struct dentry *dentry, const char *name, 641 + const void *value, size_t size, int flags, int type) 642 + { 643 + struct inode *inode = dentry->d_inode; 644 + struct posix_acl *acl = NULL; 645 + int ret; 646 + 647 + if (!IS_POSIXACL(inode)) 648 + return -EOPNOTSUPP; 649 + if (!inode->i_op->set_acl) 650 + return -EOPNOTSUPP; 651 + 652 + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) 653 + return value ? -EACCES : 0; 654 + if (!inode_owner_or_capable(inode)) 655 + return -EPERM; 656 + 657 + if (value) { 658 + acl = posix_acl_from_xattr(&init_user_ns, value, size); 659 + if (IS_ERR(acl)) 660 + return PTR_ERR(acl); 661 + 662 + if (acl) { 663 + ret = posix_acl_valid(acl); 664 + if (ret) 665 + goto out; 666 + } 667 + } 668 + 669 + ret = inode->i_op->set_acl(inode, acl, type); 670 + out: 671 + posix_acl_release(acl); 672 + return ret; 673 + } 674 + 675 + static size_t 676 + posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size, 677 + const char *name, size_t name_len, int type) 678 + { 679 + const char *xname; 680 + size_t size; 681 + 682 + if (!IS_POSIXACL(dentry->d_inode)) 683 + return -EOPNOTSUPP; 684 + if (S_ISLNK(dentry->d_inode->i_mode)) 685 + return -EOPNOTSUPP; 686 + 687 + if (type == ACL_TYPE_ACCESS) 688 + xname = POSIX_ACL_XATTR_ACCESS; 689 + else 690 + xname = POSIX_ACL_XATTR_DEFAULT; 691 + 692 + size = strlen(xname) + 1; 693 + if (list && size <= list_size) 694 + memcpy(list, xname, size); 695 + return size; 696 + } 697 + 698 + const struct xattr_handler posix_acl_access_xattr_handler = { 699 + .prefix = POSIX_ACL_XATTR_ACCESS, 700 + .flags = ACL_TYPE_ACCESS, 701 + .list = posix_acl_xattr_list, 702 + .get = posix_acl_xattr_get, 703 + .set = posix_acl_xattr_set, 704 + }; 705 + EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); 706 + 707 + const struct xattr_handler posix_acl_default_xattr_handler = { 708 + .prefix = POSIX_ACL_XATTR_DEFAULT, 709 + .flags = ACL_TYPE_DEFAULT, 710 + .list = posix_acl_xattr_list, 711 + .get = posix_acl_xattr_get, 712 + .set = posix_acl_xattr_set, 713 + }; 714 + EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
+3
include/linux/posix_acl_xattr.h
··· 69 69 int posix_acl_to_xattr(struct user_namespace *user_ns, 70 70 const struct posix_acl *acl, void *buffer, size_t size); 71 71 72 + extern const struct xattr_handler posix_acl_access_xattr_handler; 73 + extern const struct xattr_handler posix_acl_default_xattr_handler; 74 + 72 75 #endif /* _POSIX_ACL_XATTR_H */