From 5a10b5bdf6cd205cd4b142b5b456229cf9e8ae80 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Fri, 8 Jul 2016 15:57:51 -0500 Subject: [PATCH] UBUNTU: SAUCE: (namespace) posix_acl: Export posix_acl_fix_xattr_userns() to modules BugLink: http://bugs.launchpad.net/bugs/1634964 Fuse will make use of this function to provide backwards- compatible acl support when proper posix acl support is added. Add a check to return immediately if the to and from namespaces are the same, and remove equivalent checks from its callers. Also return an error code to indicate to callers whether or not the conversion of the id between the user namespaces was successful. For a valid xattr the id will continue to be changed regardless to maintain the current behaviour for existing callers, so they do not require updates to handle failed conversions. Signed-off-by: Seth Forshee Acked-by: Tim Gardner Signed-off-by: Luis Henriques --- fs/posix_acl.c | 42 ++++++++++++++++++++------------- include/linux/posix_acl_xattr.h | 9 +++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 93a8b46465c7..87328aeb4c1b 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -626,58 +626,68 @@ EXPORT_SYMBOL(posix_acl_update_mode); /* * Fix up the uids and gids in posix acl extended attributes in place. */ -static void posix_acl_fix_xattr_userns( +int posix_acl_fix_xattr_userns( struct user_namespace *to, struct user_namespace *from, void *value, size_t size) { posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; int count; - kuid_t uid; - kgid_t gid; + kuid_t kuid; + kgid_t kgid; + uid_t uid; + gid_t gid; + int ret = 0; + if (to == from) + return 0; if (!value) - return; + return 0; if (size < sizeof(posix_acl_xattr_header)) - return; + return -EINVAL; if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) - return; + return -EINVAL; count = posix_acl_xattr_count(size); if (count < 0) - return; + return -EINVAL; if (count == 0) - return; + return 0; for (end = entry + count; entry != end; entry++) { switch(le16_to_cpu(entry->e_tag)) { case ACL_USER: - uid = make_kuid(from, le32_to_cpu(entry->e_id)); - entry->e_id = cpu_to_le32(from_kuid(to, uid)); + kuid = make_kuid(from, le32_to_cpu(entry->e_id)); + uid = from_kuid(to, kuid); + entry->e_id = cpu_to_le32(uid); + if (uid == (uid_t)-1) + ret = -EOVERFLOW; break; case ACL_GROUP: - gid = make_kgid(from, le32_to_cpu(entry->e_id)); - entry->e_id = cpu_to_le32(from_kgid(to, gid)); + kgid = make_kgid(from, le32_to_cpu(entry->e_id)); + gid = from_kgid(to, kgid); + entry->e_id = cpu_to_le32(gid); + if (gid == (gid_t)-1) + ret = -EOVERFLOW; break; default: break; } } + + return ret; } +EXPORT_SYMBOL(posix_acl_fix_xattr_userns); void posix_acl_fix_xattr_from_user(void *value, size_t size) { struct user_namespace *user_ns = current_user_ns(); - if (user_ns == &init_user_ns) - return; posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size); } void posix_acl_fix_xattr_to_user(void *value, size_t size) { struct user_namespace *user_ns = current_user_ns(); - if (user_ns == &init_user_ns) - return; posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size); } diff --git a/include/linux/posix_acl_xattr.h b/include/linux/posix_acl_xattr.h index 6f14ee295822..f2547dd58cb9 100644 --- a/include/linux/posix_acl_xattr.h +++ b/include/linux/posix_acl_xattr.h @@ -53,9 +53,18 @@ posix_acl_xattr_count(size_t size) } #ifdef CONFIG_FS_POSIX_ACL +int posix_acl_fix_xattr_userns(struct user_namespace *to, + struct user_namespace *from, + void *value, size_t size); void posix_acl_fix_xattr_from_user(void *value, size_t size); void posix_acl_fix_xattr_to_user(void *value, size_t size); #else +static inline int posix_acl_fix_xattr_userns(struct user_namespace *to, + struct user_namespace *from, + void *value, size_t size) +{ + return 0; +} static inline void posix_acl_fix_xattr_from_user(void *value, size_t size) { } -- 2.39.5