Commit ddca4e17 authored by Eric W. Biederman's avatar Eric W. Biederman

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: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 1ac7fd81
...@@ -38,8 +38,8 @@ struct nfsacl_encode_desc { ...@@ -38,8 +38,8 @@ struct nfsacl_encode_desc {
unsigned int count; unsigned int count;
struct posix_acl *acl; struct posix_acl *acl;
int typeflag; int typeflag;
uid_t uid; kuid_t uid;
gid_t gid; kgid_t gid;
}; };
struct nfsacl_simple_acl { struct nfsacl_simple_acl {
...@@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) ...@@ -60,14 +60,16 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
*p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
switch(entry->e_tag) { switch(entry->e_tag) {
case ACL_USER_OBJ: case ACL_USER_OBJ:
*p++ = htonl(nfsacl_desc->uid); *p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid));
break; break;
case ACL_GROUP_OBJ: case ACL_GROUP_OBJ:
*p++ = htonl(nfsacl_desc->gid); *p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid));
break; break;
case ACL_USER: case ACL_USER:
*p++ = htonl(from_kuid(&init_user_ns, entry->e_uid));
break;
case ACL_GROUP: case ACL_GROUP:
*p++ = htonl(entry->e_id); *p++ = htonl(from_kgid(&init_user_ns, entry->e_gid));
break; break;
default: /* Solaris depends on that! */ default: /* Solaris depends on that! */
*p++ = 0; *p++ = 0;
...@@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) ...@@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
(struct nfsacl_decode_desc *) desc; (struct nfsacl_decode_desc *) desc;
__be32 *p = elem; __be32 *p = elem;
struct posix_acl_entry *entry; struct posix_acl_entry *entry;
unsigned int id;
if (!nfsacl_desc->acl) { if (!nfsacl_desc->acl) {
if (desc->array_len > NFS_ACL_MAX_ENTRIES) if (desc->array_len > NFS_ACL_MAX_ENTRIES)
...@@ -160,14 +163,22 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem) ...@@ -160,14 +163,22 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
entry->e_id = ntohl(*p++); id = ntohl(*p++);
entry->e_perm = ntohl(*p++); entry->e_perm = ntohl(*p++);
switch(entry->e_tag) { switch(entry->e_tag) {
case ACL_USER_OBJ:
case ACL_USER: case ACL_USER:
case ACL_GROUP_OBJ: entry->e_uid = make_kuid(&init_user_ns, id);
if (!uid_valid(entry->e_uid))
return -EINVAL;
break;
case ACL_GROUP: case ACL_GROUP:
entry->e_gid = make_kgid(&init_user_ns, id);
if (!gid_valid(entry->e_gid))
return -EINVAL;
break;
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_OTHER: case ACL_OTHER:
if (entry->e_perm & ~S_IRWXO) if (entry->e_perm & ~S_IRWXO)
return -EINVAL; return -EINVAL;
...@@ -190,9 +201,13 @@ cmp_acl_entry(const void *x, const void *y) ...@@ -190,9 +201,13 @@ cmp_acl_entry(const void *x, const void *y)
if (a->e_tag != b->e_tag) if (a->e_tag != b->e_tag)
return a->e_tag - b->e_tag; return a->e_tag - b->e_tag;
else if (a->e_id > b->e_id) else if ((a->e_tag == ACL_USER) && uid_gt(a->e_uid, b->e_uid))
return 1;
else if ((a->e_tag == ACL_USER) && uid_lt(a->e_uid, b->e_uid))
return -1;
else if ((a->e_tag == ACL_GROUP) && gid_gt(a->e_gid, b->e_gid))
return 1; return 1;
else if (a->e_id < b->e_id) else if ((a->e_tag == ACL_GROUP) && gid_lt(a->e_gid, b->e_gid))
return -1; return -1;
else else
return 0; return 0;
...@@ -213,22 +228,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl) ...@@ -213,22 +228,18 @@ posix_acl_from_nfsacl(struct posix_acl *acl)
sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry), sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
cmp_acl_entry, NULL); cmp_acl_entry, NULL);
/* Clear undefined identifier fields and find the ACL_GROUP_OBJ /* Find the ACL_GROUP_OBJ and ACL_MASK entries. */
and ACL_MASK entries. */
FOREACH_ACL_ENTRY(pa, acl, pe) { FOREACH_ACL_ENTRY(pa, acl, pe) {
switch(pa->e_tag) { switch(pa->e_tag) {
case ACL_USER_OBJ: case ACL_USER_OBJ:
pa->e_id = ACL_UNDEFINED_ID;
break; break;
case ACL_GROUP_OBJ: case ACL_GROUP_OBJ:
pa->e_id = ACL_UNDEFINED_ID;
group_obj = pa; group_obj = pa;
break; break;
case ACL_MASK: case ACL_MASK:
mask = pa; mask = pa;
/* fall through */ /* fall through */
case ACL_OTHER: case ACL_OTHER:
pa->e_id = ACL_UNDEFINED_ID;
break; break;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment