diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2013-02-01 14:50:52 -0800 | 
|---|---|---|
| committer | Eric W. Biederman <ebiederm@xmission.com> | 2013-02-13 06:15:14 -0800 | 
| commit | ddca4e1730cf1b72044ae76ddf17b29d790b4dbc (patch) | |
| tree | f5659143f3b480dd7fd93ea8e0a324884fe3cf87 | |
| parent | 1ac7fd8190b79c822631ed537186fb8b2d9e9b74 (diff) | |
| download | olio-linux-3.10-ddca4e1730cf1b72044ae76ddf17b29d790b4dbc.tar.xz olio-linux-3.10-ddca4e1730cf1b72044ae76ddf17b29d790b4dbc.zip  | |
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 6940439bd60..ed628f71274 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -38,8 +38,8 @@ struct nfsacl_encode_desc {  	unsigned int count;  	struct posix_acl *acl;  	int typeflag; -	uid_t uid; -	gid_t gid; +	kuid_t uid; +	kgid_t gid;  };  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);  	switch(entry->e_tag) {  		case ACL_USER_OBJ: -			*p++ = htonl(nfsacl_desc->uid); +			*p++ = htonl(from_kuid(&init_user_ns, nfsacl_desc->uid));  			break;  		case ACL_GROUP_OBJ: -			*p++ = htonl(nfsacl_desc->gid); +			*p++ = htonl(from_kgid(&init_user_ns, nfsacl_desc->gid));  			break;  		case ACL_USER: +			*p++ = htonl(from_kuid(&init_user_ns, entry->e_uid)); +			break;  		case ACL_GROUP: -			*p++ = htonl(entry->e_id); +			*p++ = htonl(from_kgid(&init_user_ns, entry->e_gid));  			break;  		default:  /* Solaris depends on that! */  			*p++ = 0; @@ -148,6 +150,7 @@ xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)  		(struct nfsacl_decode_desc *) desc;  	__be32 *p = elem;  	struct posix_acl_entry *entry; +	unsigned int id;  	if (!nfsacl_desc->acl) {  		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->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT; -	entry->e_id = ntohl(*p++); +	id = ntohl(*p++);  	entry->e_perm = ntohl(*p++);  	switch(entry->e_tag) { -		case ACL_USER_OBJ:  		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: +			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:  			if (entry->e_perm & ~S_IRWXO)  				return -EINVAL; @@ -190,9 +201,13 @@ cmp_acl_entry(const void *x, const void *y)  	if (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; -	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;  	else  		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),  	     cmp_acl_entry, NULL); -	/* Clear undefined identifier fields and find the ACL_GROUP_OBJ -	   and ACL_MASK entries. */ +	/* Find the ACL_GROUP_OBJ and ACL_MASK entries. */  	FOREACH_ACL_ENTRY(pa, acl, pe) {  		switch(pa->e_tag) {  			case ACL_USER_OBJ: -				pa->e_id = ACL_UNDEFINED_ID;  				break;  			case ACL_GROUP_OBJ: -				pa->e_id = ACL_UNDEFINED_ID;  				group_obj = pa;  				break;  			case ACL_MASK:  				mask = pa;  				/* fall through */  			case ACL_OTHER: -				pa->e_id = ACL_UNDEFINED_ID;  				break;  		}  	}  |