aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs_common/nfsacl.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2013-02-01 17:50:52 -0500
committerEric W. Biederman <ebiederm@xmission.com>2013-02-13 09:15:14 -0500
commitddca4e1730cf1b72044ae76ddf17b29d790b4dbc (patch)
treef5659143f3b480dd7fd93ea8e0a324884fe3cf87 /fs/nfs_common/nfsacl.c
parent1ac7fd8190b79c822631ed537186fb8b2d9e9b74 (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>
Diffstat (limited to 'fs/nfs_common/nfsacl.c')
-rw-r--r--fs/nfs_common/nfsacl.c41
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
45struct nfsacl_simple_acl { 45struct 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 }