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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc5 180 lines 4.4 kB view raw
1/* 2 * linux/fs/xattr_acl.c 3 * 4 * Almost all from linux/fs/ext2/acl.c: 5 * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org> 6 */ 7 8#include <linux/export.h> 9#include <linux/fs.h> 10#include <linux/posix_acl_xattr.h> 11#include <linux/gfp.h> 12#include <linux/user_namespace.h> 13 14/* 15 * Fix up the uids and gids in posix acl extended attributes in place. 16 */ 17static void posix_acl_fix_xattr_userns( 18 struct user_namespace *to, struct user_namespace *from, 19 void *value, size_t size) 20{ 21 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; 22 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; 23 int count; 24 kuid_t uid; 25 kgid_t gid; 26 27 if (!value) 28 return; 29 if (size < sizeof(posix_acl_xattr_header)) 30 return; 31 if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 32 return; 33 34 count = posix_acl_xattr_count(size); 35 if (count < 0) 36 return; 37 if (count == 0) 38 return; 39 40 for (end = entry + count; entry != end; entry++) { 41 switch(le16_to_cpu(entry->e_tag)) { 42 case ACL_USER: 43 uid = make_kuid(from, le32_to_cpu(entry->e_id)); 44 entry->e_id = cpu_to_le32(from_kuid(to, uid)); 45 break; 46 case ACL_GROUP: 47 gid = make_kgid(from, le32_to_cpu(entry->e_id)); 48 entry->e_id = cpu_to_le32(from_kgid(to, gid)); 49 break; 50 default: 51 break; 52 } 53 } 54} 55 56void posix_acl_fix_xattr_from_user(void *value, size_t size) 57{ 58 struct user_namespace *user_ns = current_user_ns(); 59 if (user_ns == &init_user_ns) 60 return; 61 posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size); 62} 63 64void posix_acl_fix_xattr_to_user(void *value, size_t size) 65{ 66 struct user_namespace *user_ns = current_user_ns(); 67 if (user_ns == &init_user_ns) 68 return; 69 posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size); 70} 71 72/* 73 * Convert from extended attribute to in-memory representation. 74 */ 75struct posix_acl * 76posix_acl_from_xattr(struct user_namespace *user_ns, 77 const void *value, size_t size) 78{ 79 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; 80 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; 81 int count; 82 struct posix_acl *acl; 83 struct posix_acl_entry *acl_e; 84 85 if (!value) 86 return NULL; 87 if (size < sizeof(posix_acl_xattr_header)) 88 return ERR_PTR(-EINVAL); 89 if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 90 return ERR_PTR(-EOPNOTSUPP); 91 92 count = posix_acl_xattr_count(size); 93 if (count < 0) 94 return ERR_PTR(-EINVAL); 95 if (count == 0) 96 return NULL; 97 98 acl = posix_acl_alloc(count, GFP_NOFS); 99 if (!acl) 100 return ERR_PTR(-ENOMEM); 101 acl_e = acl->a_entries; 102 103 for (end = entry + count; entry != end; acl_e++, entry++) { 104 acl_e->e_tag = le16_to_cpu(entry->e_tag); 105 acl_e->e_perm = le16_to_cpu(entry->e_perm); 106 107 switch(acl_e->e_tag) { 108 case ACL_USER_OBJ: 109 case ACL_GROUP_OBJ: 110 case ACL_MASK: 111 case ACL_OTHER: 112 break; 113 114 case ACL_USER: 115 acl_e->e_uid = 116 make_kuid(user_ns, 117 le32_to_cpu(entry->e_id)); 118 if (!uid_valid(acl_e->e_uid)) 119 goto fail; 120 break; 121 case ACL_GROUP: 122 acl_e->e_gid = 123 make_kgid(user_ns, 124 le32_to_cpu(entry->e_id)); 125 if (!gid_valid(acl_e->e_gid)) 126 goto fail; 127 break; 128 129 default: 130 goto fail; 131 } 132 } 133 return acl; 134 135fail: 136 posix_acl_release(acl); 137 return ERR_PTR(-EINVAL); 138} 139EXPORT_SYMBOL (posix_acl_from_xattr); 140 141/* 142 * Convert from in-memory to extended attribute representation. 143 */ 144int 145posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl, 146 void *buffer, size_t size) 147{ 148 posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer; 149 posix_acl_xattr_entry *ext_entry = ext_acl->a_entries; 150 int real_size, n; 151 152 real_size = posix_acl_xattr_size(acl->a_count); 153 if (!buffer) 154 return real_size; 155 if (real_size > size) 156 return -ERANGE; 157 158 ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); 159 160 for (n=0; n < acl->a_count; n++, ext_entry++) { 161 const struct posix_acl_entry *acl_e = &acl->a_entries[n]; 162 ext_entry->e_tag = cpu_to_le16(acl_e->e_tag); 163 ext_entry->e_perm = cpu_to_le16(acl_e->e_perm); 164 switch(acl_e->e_tag) { 165 case ACL_USER: 166 ext_entry->e_id = 167 cpu_to_le32(from_kuid(user_ns, acl_e->e_uid)); 168 break; 169 case ACL_GROUP: 170 ext_entry->e_id = 171 cpu_to_le32(from_kgid(user_ns, acl_e->e_gid)); 172 break; 173 default: 174 ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); 175 break; 176 } 177 } 178 return real_size; 179} 180EXPORT_SYMBOL (posix_acl_to_xattr);