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>
This commit is contained in:
parent
1ac7fd8190
commit
ddca4e1730
1 changed files with 26 additions and 15 deletions
|
@ -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)
|
||||||
*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)
|
||||||
(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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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;
|
return 1;
|
||||||
else if (a->e_id < b->e_id)
|
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;
|
||||||
|
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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue