aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr_acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xattr_acl.c')
-rw-r--r--fs/xattr_acl.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c
index 69d06b07b169..11efd830b5f5 100644
--- a/fs/xattr_acl.c
+++ b/fs/xattr_acl.c
@@ -9,13 +9,72 @@
9#include <linux/fs.h> 9#include <linux/fs.h>
10#include <linux/posix_acl_xattr.h> 10#include <linux/posix_acl_xattr.h>
11#include <linux/gfp.h> 11#include <linux/gfp.h>
12#include <linux/user_namespace.h>
12 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_kuid(to, uid));
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}
13 71
14/* 72/*
15 * Convert from extended attribute to in-memory representation. 73 * Convert from extended attribute to in-memory representation.
16 */ 74 */
17struct posix_acl * 75struct posix_acl *
18posix_acl_from_xattr(const void *value, size_t size) 76posix_acl_from_xattr(struct user_namespace *user_ns,
77 const void *value, size_t size)
19{ 78{
20 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; 79 posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
21 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; 80 posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
@@ -50,12 +109,21 @@ posix_acl_from_xattr(const void *value, size_t size)
50 case ACL_GROUP_OBJ: 109 case ACL_GROUP_OBJ:
51 case ACL_MASK: 110 case ACL_MASK:
52 case ACL_OTHER: 111 case ACL_OTHER:
53 acl_e->e_id = ACL_UNDEFINED_ID;
54 break; 112 break;
55 113
56 case ACL_USER: 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;
57 case ACL_GROUP: 121 case ACL_GROUP:
58 acl_e->e_id = le32_to_cpu(entry->e_id); 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;
59 break; 127 break;
60 128
61 default: 129 default:
@@ -74,7 +142,8 @@ EXPORT_SYMBOL (posix_acl_from_xattr);
74 * Convert from in-memory to extended attribute representation. 142 * Convert from in-memory to extended attribute representation.
75 */ 143 */
76int 144int
77posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) 145posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
146 void *buffer, size_t size)
78{ 147{
79 posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer; 148 posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
80 posix_acl_xattr_entry *ext_entry = ext_acl->a_entries; 149 posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
@@ -89,9 +158,22 @@ posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size)
89 ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); 158 ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
90 159
91 for (n=0; n < acl->a_count; n++, ext_entry++) { 160 for (n=0; n < acl->a_count; n++, ext_entry++) {
92 ext_entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); 161 const struct posix_acl_entry *acl_e = &acl->a_entries[n];
93 ext_entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); 162 ext_entry->e_tag = cpu_to_le16(acl_e->e_tag);
94 ext_entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); 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 }
95 } 177 }
96 return real_size; 178 return real_size;
97} 179}