Commit ddca4e1730cf1b72044ae76ddf17b29d790b4dbc
1 parent
1ac7fd8190
Exists in
master
and in
20 other branches
nfs_common: Update the translation between nfsv3 acls linux posix acls
- Use kuid_t and kgit in struct nfsacl_encode_desc. - Convert from kuids and kgids when generating on the wire values. - Convert on the wire values to kuids and kgids when read. - Modify cmp_acl_entry to be type safe comparison on posix acls. Only acls with type ACL_USER and ACL_GROUP can appear more than once and as such need to compare more than their tag. - The e_id field is being removed from posix acls so don't initialize it. Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Showing 1 changed file with 26 additions and 15 deletions Side-by-side Diff
fs/nfs_common/nfsacl.c
... | ... | @@ -38,8 +38,8 @@ |
38 | 38 | unsigned int count; |
39 | 39 | struct posix_acl *acl; |
40 | 40 | int typeflag; |
41 | - uid_t uid; | |
42 | - gid_t gid; | |
41 | + kuid_t uid; | |
42 | + kgid_t gid; | |
43 | 43 | }; |
44 | 44 | |
45 | 45 | struct nfsacl_simple_acl { |
46 | 46 | |
47 | 47 | |
48 | 48 | |
... | ... | @@ -60,14 +60,16 @@ |
60 | 60 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
61 | 61 | switch(entry->e_tag) { |
62 | 62 | case ACL_USER_OBJ: |
63 | - *p++ = htonl(nfsacl_desc->uid); | |
63 | + *p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid)); | |
64 | 64 | break; |
65 | 65 | case ACL_GROUP_OBJ: |
66 | - *p++ = htonl(nfsacl_desc->gid); | |
66 | + *p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid)); | |
67 | 67 | break; |
68 | 68 | case ACL_USER: |
69 | + *p++ = htonl(from_kuid(&init_user_ns, entry->e_uid)); | |
70 | + break; | |
69 | 71 | case ACL_GROUP: |
70 | - *p++ = htonl(entry->e_id); | |
72 | + *p++ = htonl(from_kgid(&init_user_ns, entry->e_gid)); | |
71 | 73 | break; |
72 | 74 | default: /* Solaris depends on that! */ |
73 | 75 | *p++ = 0; |
... | ... | @@ -148,6 +150,7 @@ |
148 | 150 | (struct nfsacl_decode_desc *) desc; |
149 | 151 | __be32 *p = elem; |
150 | 152 | struct posix_acl_entry *entry; |
153 | + unsigned int id; | |
151 | 154 | |
152 | 155 | if (!nfsacl_desc->acl) { |
153 | 156 | if (desc->array_len > NFS_ACL_MAX_ENTRIES) |
154 | 157 | |
155 | 158 | |
156 | 159 | |
... | ... | @@ -160,14 +163,22 @@ |
160 | 163 | |
161 | 164 | entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
162 | 165 | entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; |
163 | - entry->e_id = ntohl(*p++); | |
166 | + id = ntohl(*p++); | |
164 | 167 | entry->e_perm = ntohl(*p++); |
165 | 168 | |
166 | 169 | switch(entry->e_tag) { |
167 | - case ACL_USER_OBJ: | |
168 | 170 | case ACL_USER: |
169 | - case ACL_GROUP_OBJ: | |
171 | + entry->e_uid = make_kuid(&init_user_ns, id); | |
172 | + if (!uid_valid(entry->e_uid)) | |
173 | + return -EINVAL; | |
174 | + break; | |
170 | 175 | case ACL_GROUP: |
176 | + entry->e_gid = make_kgid(&init_user_ns, id); | |
177 | + if (!gid_valid(entry->e_gid)) | |
178 | + return -EINVAL; | |
179 | + break; | |
180 | + case ACL_USER_OBJ: | |
181 | + case ACL_GROUP_OBJ: | |
171 | 182 | case ACL_OTHER: |
172 | 183 | if (entry->e_perm & ~S_IRWXO) |
173 | 184 | return -EINVAL; |
174 | 185 | |
175 | 186 | |
... | ... | @@ -190,10 +201,14 @@ |
190 | 201 | |
191 | 202 | if (a->e_tag != b->e_tag) |
192 | 203 | return a->e_tag - b->e_tag; |
193 | - else if (a->e_id > b->e_id) | |
204 | + else if ((a->e_tag == ACL_USER) && uid_gt(a->e_uid, b->e_uid)) | |
194 | 205 | return 1; |
195 | - else if (a->e_id < b->e_id) | |
206 | + else if ((a->e_tag == ACL_USER) && uid_lt(a->e_uid, b->e_uid)) | |
196 | 207 | return -1; |
208 | + else if ((a->e_tag == ACL_GROUP) && gid_gt(a->e_gid, b->e_gid)) | |
209 | + return 1; | |
210 | + else if ((a->e_tag == ACL_GROUP) && gid_lt(a->e_gid, b->e_gid)) | |
211 | + return -1; | |
197 | 212 | else |
198 | 213 | return 0; |
199 | 214 | } |
200 | 215 | |
201 | 216 | |
202 | 217 | |
... | ... | @@ -213,22 +228,18 @@ |
213 | 228 | sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry), |
214 | 229 | cmp_acl_entry, NULL); |
215 | 230 | |
216 | - /* Clear undefined identifier fields and find the ACL_GROUP_OBJ | |
217 | - and ACL_MASK entries. */ | |
231 | + /* Find the ACL_GROUP_OBJ and ACL_MASK entries. */ | |
218 | 232 | FOREACH_ACL_ENTRY(pa, acl, pe) { |
219 | 233 | switch(pa->e_tag) { |
220 | 234 | case ACL_USER_OBJ: |
221 | - pa->e_id = ACL_UNDEFINED_ID; | |
222 | 235 | break; |
223 | 236 | case ACL_GROUP_OBJ: |
224 | - pa->e_id = ACL_UNDEFINED_ID; | |
225 | 237 | group_obj = pa; |
226 | 238 | break; |
227 | 239 | case ACL_MASK: |
228 | 240 | mask = pa; |
229 | 241 | /* fall through */ |
230 | 242 | case ACL_OTHER: |
231 | - pa->e_id = ACL_UNDEFINED_ID; | |
232 | 243 | break; |
233 | 244 | } |
234 | 245 | } |