diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2013-02-01 17:50:52 -0500 |
|---|---|---|
| committer | Eric W. Biederman <ebiederm@xmission.com> | 2013-02-13 09:15:14 -0500 |
| commit | ddca4e1730cf1b72044ae76ddf17b29d790b4dbc (patch) | |
| tree | f5659143f3b480dd7fd93ea8e0a324884fe3cf87 | |
| parent | 1ac7fd8190b79c822631ed537186fb8b2d9e9b74 (diff) | |
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>
| -rw-r--r-- | fs/nfs_common/nfsacl.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 6940439bd609..ed628f71274c 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
| @@ -38,8 +38,8 @@ struct nfsacl_encode_desc { | |||
| 38 | unsigned int count; | 38 | unsigned int count; |
| 39 | struct posix_acl *acl; | 39 | struct posix_acl *acl; |
| 40 | int typeflag; | 40 | int typeflag; |
| 41 | uid_t uid; | 41 | kuid_t uid; |
| 42 | gid_t gid; | 42 | kgid_t gid; |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | struct nfsacl_simple_acl { | 45 | struct nfsacl_simple_acl { |
| @@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
| 60 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); | 60 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
| 61 | switch(entry->e_tag) { | 61 | switch(entry->e_tag) { |
| 62 | case ACL_USER_OBJ: | 62 | case ACL_USER_OBJ: |
| 63 | *p++ = htonl(nfsacl_desc->uid); | 63 | *p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid)); |
| 64 | break; | 64 | break; |
| 65 | case ACL_GROUP_OBJ: | 65 | case ACL_GROUP_OBJ: |
| 66 | *p++ = htonl(nfsacl_desc->gid); | 66 | *p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid)); |
| 67 | break; | 67 | break; |
| 68 | case ACL_USER: | 68 | case ACL_USER: |
| 69 | *p++ = htonl(from_kuid(&init_user_ns, entry->e_uid)); | ||
| 70 | break; | ||
| 69 | case ACL_GROUP: | 71 | case ACL_GROUP: |
| 70 | *p++ = htonl(entry->e_id); | 72 | *p++ = htonl(from_kgid(&init_user_ns, entry->e_gid)); |
| 71 | break; | 73 | break; |
| 72 | default: /* Solaris depends on that! */ | 74 | default: /* Solaris depends on that! */ |
| 73 | *p++ = 0; | 75 | *p++ = 0; |
| @@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) | |||
| 148 | (struct nfsacl_decode_desc *) desc; | 150 | (struct nfsacl_decode_desc *) desc; |
| 149 | __be32 *p = elem; | 151 | __be32 *p = elem; |
| 150 | struct posix_acl_entry *entry; | 152 | struct posix_acl_entry *entry; |
| 153 | unsigned int id; | ||
| 151 | 154 | ||
| 152 | if (!nfsacl_desc->acl) { | 155 | if (!nfsacl_desc->acl) { |
| 153 | if (desc->array_len > NFS_ACL_MAX_ENTRIES) | 156 | if (desc->array_len > NFS_ACL_MAX_ENTRIES) |
| @@ -160,14 +163,22 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) | |||
| 160 | 163 | ||
| 161 | entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; | 164 | entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
| 162 | entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; | 165 | entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; |
| 163 | entry->e_id = ntohl(*p++); | 166 | id = ntohl(*p++); |
| 164 | entry->e_perm = ntohl(*p++); | 167 | entry->e_perm = ntohl(*p++); |
| 165 | 168 | ||
| 166 | switch(entry->e_tag) { | 169 | switch(entry->e_tag) { |
| 167 | case ACL_USER_OBJ: | ||
| 168 | case ACL_USER: | 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 | case ACL_GROUP: | 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 | case ACL_OTHER: | 182 | case ACL_OTHER: |
| 172 | if (entry->e_perm & ~S_IRWXO) | 183 | if (entry->e_perm & ~S_IRWXO) |
| 173 | return -EINVAL; | 184 | return -EINVAL; |
| @@ -190,9 +201,13 @@ cmp_acl_entry(const void *x, const void *y) | |||
| 190 | 201 | ||
| 191 | if (a->e_tag != b->e_tag) | 202 | if (a->e_tag != b->e_tag) |
| 192 | return a->e_tag - b->e_tag; | 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)) |
| 205 | return 1; | ||
| 206 | else if ((a->e_tag == ACL_USER) && uid_lt(a->e_uid, b->e_uid)) | ||
| 207 | return -1; | ||
| 208 | else if ((a->e_tag == ACL_GROUP) && gid_gt(a->e_gid, b->e_gid)) | ||
| 194 | return 1; | 209 | return 1; |
| 195 | else if (a->e_id < b->e_id) | 210 | else if ((a->e_tag == ACL_GROUP) && gid_lt(a->e_gid, b->e_gid)) |
| 196 | return -1; | 211 | return -1; |
| 197 | else | 212 | else |
| 198 | return 0; | 213 | return 0; |
| @@ -213,22 +228,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl) | |||
| 213 | sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry), | 228 | sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry), |
| 214 | cmp_acl_entry, NULL); | 229 | cmp_acl_entry, NULL); |
| 215 | 230 | ||
| 216 | /* Clear undefined identifier fields and find the ACL_GROUP_OBJ | 231 | /* Find the ACL_GROUP_OBJ and ACL_MASK entries. */ |
| 217 | and ACL_MASK entries. */ | ||
| 218 | FOREACH_ACL_ENTRY(pa, acl, pe) { | 232 | FOREACH_ACL_ENTRY(pa, acl, pe) { |
| 219 | switch(pa->e_tag) { | 233 | switch(pa->e_tag) { |
| 220 | case ACL_USER_OBJ: | 234 | case ACL_USER_OBJ: |
| 221 | pa->e_id = ACL_UNDEFINED_ID; | ||
| 222 | break; | 235 | break; |
| 223 | case ACL_GROUP_OBJ: | 236 | case ACL_GROUP_OBJ: |
| 224 | pa->e_id = ACL_UNDEFINED_ID; | ||
| 225 | group_obj = pa; | 237 | group_obj = pa; |
| 226 | break; | 238 | break; |
| 227 | case ACL_MASK: | 239 | case ACL_MASK: |
| 228 | mask = pa; | 240 | mask = pa; |
| 229 | /* fall through */ | 241 | /* fall through */ |
| 230 | case ACL_OTHER: | 242 | case ACL_OTHER: |
| 231 | pa->e_id = ACL_UNDEFINED_ID; | ||
| 232 | break; | 243 | break; |
| 233 | } | 244 | } |
| 234 | } | 245 | } |
