diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 1 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 26 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 5 | ||||
-rw-r--r-- | fs/ecryptfs/messaging.c | 3 | ||||
-rw-r--r-- | fs/namei.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfs4acl.c | 491 | ||||
-rw-r--r-- | fs/nfsd/nfs4callback.c | 7 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 55 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 5 |
9 files changed, 301 insertions, 295 deletions
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index b3609b7cdf..403e3bad14 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -467,6 +467,7 @@ extern struct kmem_cache *ecryptfs_header_cache_1; | |||
467 | extern struct kmem_cache *ecryptfs_header_cache_2; | 467 | extern struct kmem_cache *ecryptfs_header_cache_2; |
468 | extern struct kmem_cache *ecryptfs_xattr_cache; | 468 | extern struct kmem_cache *ecryptfs_xattr_cache; |
469 | extern struct kmem_cache *ecryptfs_lower_page_cache; | 469 | extern struct kmem_cache *ecryptfs_lower_page_cache; |
470 | extern struct kmem_cache *ecryptfs_key_record_cache; | ||
470 | 471 | ||
471 | int ecryptfs_interpose(struct dentry *hidden_dentry, | 472 | int ecryptfs_interpose(struct dentry *hidden_dentry, |
472 | struct dentry *this_dentry, struct super_block *sb, | 473 | struct dentry *this_dentry, struct super_block *sb, |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 81156e95ef..b550dea8ee 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -1638,6 +1638,8 @@ out: | |||
1638 | return rc; | 1638 | return rc; |
1639 | } | 1639 | } |
1640 | 1640 | ||
1641 | struct kmem_cache *ecryptfs_key_record_cache; | ||
1642 | |||
1641 | /** | 1643 | /** |
1642 | * ecryptfs_generate_key_packet_set | 1644 | * ecryptfs_generate_key_packet_set |
1643 | * @dest: Virtual address from which to write the key record set | 1645 | * @dest: Virtual address from which to write the key record set |
@@ -1664,50 +1666,55 @@ ecryptfs_generate_key_packet_set(char *dest_base, | |||
1664 | &ecryptfs_superblock_to_private( | 1666 | &ecryptfs_superblock_to_private( |
1665 | ecryptfs_dentry->d_sb)->mount_crypt_stat; | 1667 | ecryptfs_dentry->d_sb)->mount_crypt_stat; |
1666 | size_t written; | 1668 | size_t written; |
1667 | struct ecryptfs_key_record key_rec; | 1669 | struct ecryptfs_key_record *key_rec; |
1668 | int rc = 0; | 1670 | int rc = 0; |
1669 | 1671 | ||
1670 | (*len) = 0; | 1672 | (*len) = 0; |
1673 | key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL); | ||
1674 | if (!key_rec) { | ||
1675 | rc = -ENOMEM; | ||
1676 | goto out; | ||
1677 | } | ||
1671 | if (mount_crypt_stat->global_auth_tok) { | 1678 | if (mount_crypt_stat->global_auth_tok) { |
1672 | auth_tok = mount_crypt_stat->global_auth_tok; | 1679 | auth_tok = mount_crypt_stat->global_auth_tok; |
1673 | if (auth_tok->token_type == ECRYPTFS_PASSWORD) { | 1680 | if (auth_tok->token_type == ECRYPTFS_PASSWORD) { |
1674 | rc = write_tag_3_packet((dest_base + (*len)), | 1681 | rc = write_tag_3_packet((dest_base + (*len)), |
1675 | max, auth_tok, | 1682 | max, auth_tok, |
1676 | crypt_stat, &key_rec, | 1683 | crypt_stat, key_rec, |
1677 | &written); | 1684 | &written); |
1678 | if (rc) { | 1685 | if (rc) { |
1679 | ecryptfs_printk(KERN_WARNING, "Error " | 1686 | ecryptfs_printk(KERN_WARNING, "Error " |
1680 | "writing tag 3 packet\n"); | 1687 | "writing tag 3 packet\n"); |
1681 | goto out; | 1688 | goto out_free; |
1682 | } | 1689 | } |
1683 | (*len) += written; | 1690 | (*len) += written; |
1684 | /* Write auth tok signature packet */ | 1691 | /* Write auth tok signature packet */ |
1685 | rc = write_tag_11_packet( | 1692 | rc = write_tag_11_packet( |
1686 | (dest_base + (*len)), | 1693 | (dest_base + (*len)), |
1687 | (max - (*len)), | 1694 | (max - (*len)), |
1688 | key_rec.sig, ECRYPTFS_SIG_SIZE, &written); | 1695 | key_rec->sig, ECRYPTFS_SIG_SIZE, &written); |
1689 | if (rc) { | 1696 | if (rc) { |
1690 | ecryptfs_printk(KERN_ERR, "Error writing " | 1697 | ecryptfs_printk(KERN_ERR, "Error writing " |
1691 | "auth tok signature packet\n"); | 1698 | "auth tok signature packet\n"); |
1692 | goto out; | 1699 | goto out_free; |
1693 | } | 1700 | } |
1694 | (*len) += written; | 1701 | (*len) += written; |
1695 | } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { | 1702 | } else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { |
1696 | rc = write_tag_1_packet(dest_base + (*len), | 1703 | rc = write_tag_1_packet(dest_base + (*len), |
1697 | max, auth_tok, | 1704 | max, auth_tok, |
1698 | crypt_stat,mount_crypt_stat, | 1705 | crypt_stat,mount_crypt_stat, |
1699 | &key_rec, &written); | 1706 | key_rec, &written); |
1700 | if (rc) { | 1707 | if (rc) { |
1701 | ecryptfs_printk(KERN_WARNING, "Error " | 1708 | ecryptfs_printk(KERN_WARNING, "Error " |
1702 | "writing tag 1 packet\n"); | 1709 | "writing tag 1 packet\n"); |
1703 | goto out; | 1710 | goto out_free; |
1704 | } | 1711 | } |
1705 | (*len) += written; | 1712 | (*len) += written; |
1706 | } else { | 1713 | } else { |
1707 | ecryptfs_printk(KERN_WARNING, "Unsupported " | 1714 | ecryptfs_printk(KERN_WARNING, "Unsupported " |
1708 | "authentication token type\n"); | 1715 | "authentication token type\n"); |
1709 | rc = -EINVAL; | 1716 | rc = -EINVAL; |
1710 | goto out; | 1717 | goto out_free; |
1711 | } | 1718 | } |
1712 | } else | 1719 | } else |
1713 | BUG(); | 1720 | BUG(); |
@@ -1717,6 +1724,9 @@ ecryptfs_generate_key_packet_set(char *dest_base, | |||
1717 | ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); | 1724 | ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n"); |
1718 | rc = -EIO; | 1725 | rc = -EIO; |
1719 | } | 1726 | } |
1727 | |||
1728 | out_free: | ||
1729 | kmem_cache_free(ecryptfs_key_record_cache, key_rec); | ||
1720 | out: | 1730 | out: |
1721 | if (rc) | 1731 | if (rc) |
1722 | (*len) = 0; | 1732 | (*len) = 0; |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 26fe405a57..80044d196f 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -651,6 +651,11 @@ static struct ecryptfs_cache_info { | |||
651 | .name = "ecryptfs_lower_page_cache", | 651 | .name = "ecryptfs_lower_page_cache", |
652 | .size = PAGE_CACHE_SIZE, | 652 | .size = PAGE_CACHE_SIZE, |
653 | }, | 653 | }, |
654 | { | ||
655 | .cache = &ecryptfs_key_record_cache, | ||
656 | .name = "ecryptfs_key_record_cache", | ||
657 | .size = sizeof(struct ecryptfs_key_record), | ||
658 | }, | ||
654 | }; | 659 | }; |
655 | 660 | ||
656 | static void ecryptfs_free_kmem_caches(void) | 661 | static void ecryptfs_free_kmem_caches(void) |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 47d7e7b611..3baf253be9 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -169,7 +169,8 @@ int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid) | |||
169 | if (!new_id) { | 169 | if (!new_id) { |
170 | rc = -ENOMEM; | 170 | rc = -ENOMEM; |
171 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable " | 171 | ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable " |
172 | "to register daemon [%d] for user\n", pid, uid); | 172 | "to register daemon [%d] for user [%d]\n", |
173 | pid, uid); | ||
173 | goto unlock; | 174 | goto unlock; |
174 | } | 175 | } |
175 | if (!ecryptfs_find_daemon_id(uid, &old_id)) { | 176 | if (!ecryptfs_find_daemon_id(uid, &old_id)) { |
diff --git a/fs/namei.c b/fs/namei.c index 161e2225c7..ee60cc4d34 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2688,10 +2688,11 @@ int __page_symlink(struct inode *inode, const char *symname, int len, | |||
2688 | { | 2688 | { |
2689 | struct address_space *mapping = inode->i_mapping; | 2689 | struct address_space *mapping = inode->i_mapping; |
2690 | struct page *page; | 2690 | struct page *page; |
2691 | int err = -ENOMEM; | 2691 | int err; |
2692 | char *kaddr; | 2692 | char *kaddr; |
2693 | 2693 | ||
2694 | retry: | 2694 | retry: |
2695 | err = -ENOMEM; | ||
2695 | page = find_or_create_page(mapping, 0, gfp_mask); | 2696 | page = find_or_create_page(mapping, 0, gfp_mask); |
2696 | if (!page) | 2697 | if (!page) |
2697 | goto fail; | 2698 | goto fail; |
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 5d94555cdc..832673b145 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c | |||
@@ -61,9 +61,11 @@ | |||
61 | 61 | ||
62 | /* flags used to simulate posix default ACLs */ | 62 | /* flags used to simulate posix default ACLs */ |
63 | #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ | 63 | #define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \ |
64 | | NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE) | 64 | | NFS4_ACE_DIRECTORY_INHERIT_ACE) |
65 | 65 | ||
66 | #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS | NFS4_ACE_IDENTIFIER_GROUP) | 66 | #define NFS4_SUPPORTED_FLAGS (NFS4_INHERITANCE_FLAGS \ |
67 | | NFS4_ACE_INHERIT_ONLY_ACE \ | ||
68 | | NFS4_ACE_IDENTIFIER_GROUP) | ||
67 | 69 | ||
68 | #define MASK_EQUAL(mask1, mask2) \ | 70 | #define MASK_EQUAL(mask1, mask2) \ |
69 | ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) ) | 71 | ( ((mask1) & NFS4_ACE_MASK_ALL) == ((mask2) & NFS4_ACE_MASK_ALL) ) |
@@ -87,12 +89,19 @@ mask_from_posix(unsigned short perm, unsigned int flags) | |||
87 | } | 89 | } |
88 | 90 | ||
89 | static u32 | 91 | static u32 |
90 | deny_mask(u32 allow_mask, unsigned int flags) | 92 | deny_mask_from_posix(unsigned short perm, u32 flags) |
91 | { | 93 | { |
92 | u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP; | 94 | u32 mask = 0; |
93 | if (!(flags & NFS4_ACL_DIR)) | 95 | |
94 | ret &= ~NFS4_ACE_DELETE_CHILD; | 96 | if (perm & ACL_READ) |
95 | return ret; | 97 | mask |= NFS4_READ_MODE; |
98 | if (perm & ACL_WRITE) | ||
99 | mask |= NFS4_WRITE_MODE; | ||
100 | if ((perm & ACL_WRITE) && (flags & NFS4_ACL_DIR)) | ||
101 | mask |= NFS4_ACE_DELETE_CHILD; | ||
102 | if (perm & ACL_EXECUTE) | ||
103 | mask |= NFS4_EXECUTE_MODE; | ||
104 | return mask; | ||
96 | } | 105 | } |
97 | 106 | ||
98 | /* XXX: modify functions to return NFS errors; they're only ever | 107 | /* XXX: modify functions to return NFS errors; they're only ever |
@@ -126,108 +135,151 @@ struct ace_container { | |||
126 | }; | 135 | }; |
127 | 136 | ||
128 | static short ace2type(struct nfs4_ace *); | 137 | static short ace2type(struct nfs4_ace *); |
129 | static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); | 138 | static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, |
130 | static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int); | 139 | unsigned int); |
131 | int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); | 140 | void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); |
132 | static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *); | ||
133 | 141 | ||
134 | struct nfs4_acl * | 142 | struct nfs4_acl * |
135 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, | 143 | nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, |
136 | unsigned int flags) | 144 | unsigned int flags) |
137 | { | 145 | { |
138 | struct nfs4_acl *acl; | 146 | struct nfs4_acl *acl; |
139 | int error = -EINVAL; | 147 | int size = 0; |
140 | 148 | ||
141 | if ((pacl != NULL && | 149 | if (pacl) { |
142 | (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) || | 150 | if (posix_acl_valid(pacl) < 0) |
143 | (dpacl != NULL && | 151 | return ERR_PTR(-EINVAL); |
144 | (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0))) | 152 | size += 2*pacl->a_count; |
145 | goto out_err; | ||
146 | |||
147 | acl = nfs4_acl_new(); | ||
148 | if (acl == NULL) { | ||
149 | error = -ENOMEM; | ||
150 | goto out_err; | ||
151 | } | 153 | } |
152 | 154 | if (dpacl) { | |
153 | if (pacl != NULL) { | 155 | if (posix_acl_valid(dpacl) < 0) |
154 | error = _posix_to_nfsv4_one(pacl, acl, | 156 | return ERR_PTR(-EINVAL); |
155 | flags & ~NFS4_ACL_TYPE_DEFAULT); | 157 | size += 2*dpacl->a_count; |
156 | if (error < 0) | ||
157 | goto out_acl; | ||
158 | } | 158 | } |
159 | 159 | ||
160 | if (dpacl != NULL) { | 160 | /* Allocate for worst case: one (deny, allow) pair each: */ |
161 | error = _posix_to_nfsv4_one(dpacl, acl, | 161 | acl = nfs4_acl_new(size); |
162 | flags | NFS4_ACL_TYPE_DEFAULT); | 162 | if (acl == NULL) |
163 | if (error < 0) | 163 | return ERR_PTR(-ENOMEM); |
164 | goto out_acl; | ||
165 | } | ||
166 | 164 | ||
167 | return acl; | 165 | if (pacl) |
166 | _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT); | ||
168 | 167 | ||
169 | out_acl: | 168 | if (dpacl) |
170 | nfs4_acl_free(acl); | 169 | _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT); |
171 | out_err: | ||
172 | acl = ERR_PTR(error); | ||
173 | 170 | ||
174 | return acl; | 171 | return acl; |
175 | } | 172 | } |
176 | 173 | ||
177 | static int | 174 | struct posix_acl_summary { |
178 | nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, | 175 | unsigned short owner; |
179 | uid_t owner, unsigned int flags) | 176 | unsigned short users; |
177 | unsigned short group; | ||
178 | unsigned short groups; | ||
179 | unsigned short other; | ||
180 | unsigned short mask; | ||
181 | }; | ||
182 | |||
183 | static void | ||
184 | summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas) | ||
180 | { | 185 | { |
181 | int error; | 186 | struct posix_acl_entry *pa, *pe; |
182 | 187 | pas->users = 0; | |
183 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 188 | pas->groups = 0; |
184 | eflag, mask, whotype, owner); | 189 | pas->mask = 07; |
185 | if (error < 0) | 190 | |
186 | return error; | 191 | pe = acl->a_entries + acl->a_count; |
187 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 192 | |
188 | eflag, deny_mask(mask, flags), whotype, owner); | 193 | FOREACH_ACL_ENTRY(pa, acl, pe) { |
189 | return error; | 194 | switch (pa->e_tag) { |
195 | case ACL_USER_OBJ: | ||
196 | pas->owner = pa->e_perm; | ||
197 | break; | ||
198 | case ACL_GROUP_OBJ: | ||
199 | pas->group = pa->e_perm; | ||
200 | break; | ||
201 | case ACL_USER: | ||
202 | pas->users |= pa->e_perm; | ||
203 | break; | ||
204 | case ACL_GROUP: | ||
205 | pas->groups |= pa->e_perm; | ||
206 | break; | ||
207 | case ACL_OTHER: | ||
208 | pas->other = pa->e_perm; | ||
209 | break; | ||
210 | case ACL_MASK: | ||
211 | pas->mask = pa->e_perm; | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | /* We'll only care about effective permissions: */ | ||
216 | pas->users &= pas->mask; | ||
217 | pas->group &= pas->mask; | ||
218 | pas->groups &= pas->mask; | ||
190 | } | 219 | } |
191 | 220 | ||
192 | /* We assume the acl has been verified with posix_acl_valid. */ | 221 | /* We assume the acl has been verified with posix_acl_valid. */ |
193 | static int | 222 | static void |
194 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | 223 | _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, |
195 | unsigned int flags) | 224 | unsigned int flags) |
196 | { | 225 | { |
197 | struct posix_acl_entry *pa, *pe, *group_owner_entry; | 226 | struct posix_acl_entry *pa, *group_owner_entry; |
198 | int error = -EINVAL; | 227 | struct nfs4_ace *ace; |
199 | u32 mask, mask_mask; | 228 | struct posix_acl_summary pas; |
229 | unsigned short deny; | ||
200 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? | 230 | int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? |
201 | NFS4_INHERITANCE_FLAGS : 0); | 231 | NFS4_INHERITANCE_FLAGS : 0); |
202 | 232 | ||
203 | BUG_ON(pacl->a_count < 3); | 233 | BUG_ON(pacl->a_count < 3); |
204 | pe = pacl->a_entries + pacl->a_count; | 234 | summarize_posix_acl(pacl, &pas); |
205 | pa = pe - 2; /* if mask entry exists, it's second from the last. */ | ||
206 | if (pa->e_tag == ACL_MASK) | ||
207 | mask_mask = deny_mask(mask_from_posix(pa->e_perm, flags), flags); | ||
208 | else | ||
209 | mask_mask = 0; | ||
210 | 235 | ||
211 | pa = pacl->a_entries; | 236 | pa = pacl->a_entries; |
212 | BUG_ON(pa->e_tag != ACL_USER_OBJ); | 237 | ace = acl->aces + acl->naces; |
213 | mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); | ||
214 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags); | ||
215 | if (error < 0) | ||
216 | goto out; | ||
217 | pa++; | ||
218 | 238 | ||
219 | while (pa->e_tag == ACL_USER) { | 239 | /* We could deny everything not granted by the owner: */ |
220 | mask = mask_from_posix(pa->e_perm, flags); | 240 | deny = ~pas.owner; |
221 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 241 | /* |
222 | eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); | 242 | * but it is equivalent (and simpler) to deny only what is not |
223 | if (error < 0) | 243 | * granted by later entries: |
224 | goto out; | 244 | */ |
245 | deny &= pas.users | pas.group | pas.groups | pas.other; | ||
246 | if (deny) { | ||
247 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; | ||
248 | ace->flag = eflag; | ||
249 | ace->access_mask = deny_mask_from_posix(deny, flags); | ||
250 | ace->whotype = NFS4_ACL_WHO_OWNER; | ||
251 | ace++; | ||
252 | acl->naces++; | ||
253 | } | ||
225 | 254 | ||
255 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; | ||
256 | ace->flag = eflag; | ||
257 | ace->access_mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); | ||
258 | ace->whotype = NFS4_ACL_WHO_OWNER; | ||
259 | ace++; | ||
260 | acl->naces++; | ||
261 | pa++; | ||
226 | 262 | ||
227 | error = nfs4_acl_add_pair(acl, eflag, mask, | 263 | while (pa->e_tag == ACL_USER) { |
228 | NFS4_ACL_WHO_NAMED, pa->e_id, flags); | 264 | deny = ~(pa->e_perm & pas.mask); |
229 | if (error < 0) | 265 | deny &= pas.groups | pas.group | pas.other; |
230 | goto out; | 266 | if (deny) { |
267 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; | ||
268 | ace->flag = eflag; | ||
269 | ace->access_mask = deny_mask_from_posix(deny, flags); | ||
270 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
271 | ace->who = pa->e_id; | ||
272 | ace++; | ||
273 | acl->naces++; | ||
274 | } | ||
275 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; | ||
276 | ace->flag = eflag; | ||
277 | ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, | ||
278 | flags); | ||
279 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
280 | ace->who = pa->e_id; | ||
281 | ace++; | ||
282 | acl->naces++; | ||
231 | pa++; | 283 | pa++; |
232 | } | 284 | } |
233 | 285 | ||
@@ -236,67 +288,65 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, | |||
236 | 288 | ||
237 | /* allow ACEs */ | 289 | /* allow ACEs */ |
238 | 290 | ||
239 | if (pacl->a_count > 3) { | ||
240 | BUG_ON(pa->e_tag != ACL_GROUP_OBJ); | ||
241 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | ||
242 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | ||
243 | NFS4_ACL_WHO_GROUP, 0); | ||
244 | if (error < 0) | ||
245 | goto out; | ||
246 | } | ||
247 | group_owner_entry = pa; | 291 | group_owner_entry = pa; |
248 | mask = mask_from_posix(pa->e_perm, flags); | 292 | |
249 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 293 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
250 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | 294 | ace->flag = eflag; |
251 | NFS4_ACL_WHO_GROUP, 0); | 295 | ace->access_mask = mask_from_posix(pas.group, flags); |
252 | if (error < 0) | 296 | ace->whotype = NFS4_ACL_WHO_GROUP; |
253 | goto out; | 297 | ace++; |
298 | acl->naces++; | ||
254 | pa++; | 299 | pa++; |
255 | 300 | ||
256 | while (pa->e_tag == ACL_GROUP) { | 301 | while (pa->e_tag == ACL_GROUP) { |
257 | mask = mask_from_posix(pa->e_perm, flags); | 302 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
258 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 303 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
259 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, | 304 | ace->access_mask = mask_from_posix(pa->e_perm & pas.mask, |
260 | NFS4_ACL_WHO_NAMED, pa->e_id); | 305 | flags); |
261 | if (error < 0) | 306 | ace->whotype = NFS4_ACL_WHO_NAMED; |
262 | goto out; | 307 | ace->who = pa->e_id; |
263 | 308 | ace++; | |
264 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, | 309 | acl->naces++; |
265 | NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, | ||
266 | NFS4_ACL_WHO_NAMED, pa->e_id); | ||
267 | if (error < 0) | ||
268 | goto out; | ||
269 | pa++; | 310 | pa++; |
270 | } | 311 | } |
271 | 312 | ||
272 | /* deny ACEs */ | 313 | /* deny ACEs */ |
273 | 314 | ||
274 | pa = group_owner_entry; | 315 | pa = group_owner_entry; |
275 | mask = mask_from_posix(pa->e_perm, flags); | 316 | |
276 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 317 | deny = ~pas.group & pas.other; |
277 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 318 | if (deny) { |
278 | deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); | 319 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; |
279 | if (error < 0) | 320 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
280 | goto out; | 321 | ace->access_mask = deny_mask_from_posix(deny, flags); |
322 | ace->whotype = NFS4_ACL_WHO_GROUP; | ||
323 | ace++; | ||
324 | acl->naces++; | ||
325 | } | ||
281 | pa++; | 326 | pa++; |
327 | |||
282 | while (pa->e_tag == ACL_GROUP) { | 328 | while (pa->e_tag == ACL_GROUP) { |
283 | mask = mask_from_posix(pa->e_perm, flags); | 329 | deny = ~(pa->e_perm & pas.mask); |
284 | error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, | 330 | deny &= pas.other; |
285 | NFS4_ACE_IDENTIFIER_GROUP | eflag, | 331 | if (deny) { |
286 | deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); | 332 | ace->type = NFS4_ACE_ACCESS_DENIED_ACE_TYPE; |
287 | if (error < 0) | 333 | ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP; |
288 | goto out; | 334 | ace->access_mask = mask_from_posix(deny, flags); |
335 | ace->whotype = NFS4_ACL_WHO_NAMED; | ||
336 | ace->who = pa->e_id; | ||
337 | ace++; | ||
338 | acl->naces++; | ||
339 | } | ||
289 | pa++; | 340 | pa++; |
290 | } | 341 | } |
291 | 342 | ||
292 | if (pa->e_tag == ACL_MASK) | 343 | if (pa->e_tag == ACL_MASK) |
293 | pa++; | 344 | pa++; |
294 | BUG_ON(pa->e_tag != ACL_OTHER); | 345 | ace->type = NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE; |
295 | mask = mask_from_posix(pa->e_perm, flags); | 346 | ace->flag = eflag; |
296 | error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); | 347 | ace->access_mask = mask_from_posix(pa->e_perm, flags); |
297 | 348 | ace->whotype = NFS4_ACL_WHO_EVERYONE; | |
298 | out: | 349 | acl->naces++; |
299 | return error; | ||
300 | } | 350 | } |
301 | 351 | ||
302 | static void | 352 | static void |
@@ -342,46 +392,6 @@ sort_pacl(struct posix_acl *pacl) | |||
342 | return; | 392 | return; |
343 | } | 393 | } |
344 | 394 | ||
345 | int | ||
346 | nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, | ||
347 | struct posix_acl **dpacl, unsigned int flags) | ||
348 | { | ||
349 | struct nfs4_acl *dacl; | ||
350 | int error = -ENOMEM; | ||
351 | |||
352 | *pacl = NULL; | ||
353 | *dpacl = NULL; | ||
354 | |||
355 | dacl = nfs4_acl_new(); | ||
356 | if (dacl == NULL) | ||
357 | goto out; | ||
358 | |||
359 | error = nfs4_acl_split(acl, dacl); | ||
360 | if (error) | ||
361 | goto out_acl; | ||
362 | |||
363 | *pacl = _nfsv4_to_posix_one(acl, flags); | ||
364 | if (IS_ERR(*pacl)) { | ||
365 | error = PTR_ERR(*pacl); | ||
366 | *pacl = NULL; | ||
367 | goto out_acl; | ||
368 | } | ||
369 | |||
370 | *dpacl = _nfsv4_to_posix_one(dacl, flags); | ||
371 | if (IS_ERR(*dpacl)) { | ||
372 | error = PTR_ERR(*dpacl); | ||
373 | *dpacl = NULL; | ||
374 | } | ||
375 | out_acl: | ||
376 | if (error) { | ||
377 | posix_acl_release(*pacl); | ||
378 | *pacl = NULL; | ||
379 | } | ||
380 | nfs4_acl_free(dacl); | ||
381 | out: | ||
382 | return error; | ||
383 | } | ||
384 | |||
385 | /* | 395 | /* |
386 | * While processing the NFSv4 ACE, this maintains bitmasks representing | 396 | * While processing the NFSv4 ACE, this maintains bitmasks representing |
387 | * which permission bits have been allowed and which denied to a given | 397 | * which permission bits have been allowed and which denied to a given |
@@ -406,6 +416,7 @@ struct posix_ace_state_array { | |||
406 | * calculated so far: */ | 416 | * calculated so far: */ |
407 | 417 | ||
408 | struct posix_acl_state { | 418 | struct posix_acl_state { |
419 | int empty; | ||
409 | struct posix_ace_state owner; | 420 | struct posix_ace_state owner; |
410 | struct posix_ace_state group; | 421 | struct posix_ace_state group; |
411 | struct posix_ace_state other; | 422 | struct posix_ace_state other; |
@@ -421,6 +432,7 @@ init_state(struct posix_acl_state *state, int cnt) | |||
421 | int alloc; | 432 | int alloc; |
422 | 433 | ||
423 | memset(state, 0, sizeof(struct posix_acl_state)); | 434 | memset(state, 0, sizeof(struct posix_acl_state)); |
435 | state->empty = 1; | ||
424 | /* | 436 | /* |
425 | * In the worst case, each individual acl could be for a distinct | 437 | * In the worst case, each individual acl could be for a distinct |
426 | * named user or group, but we don't no which, so we allocate | 438 | * named user or group, but we don't no which, so we allocate |
@@ -488,6 +500,20 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) | |||
488 | int nace; | 500 | int nace; |
489 | int i, error = 0; | 501 | int i, error = 0; |
490 | 502 | ||
503 | /* | ||
504 | * ACLs with no ACEs are treated differently in the inheritable | ||
505 | * and effective cases: when there are no inheritable ACEs, we | ||
506 | * set a zero-length default posix acl: | ||
507 | */ | ||
508 | if (state->empty && (flags & NFS4_ACL_TYPE_DEFAULT)) { | ||
509 | pacl = posix_acl_alloc(0, GFP_KERNEL); | ||
510 | return pacl ? pacl : ERR_PTR(-ENOMEM); | ||
511 | } | ||
512 | /* | ||
513 | * When there are no effective ACEs, the following will end | ||
514 | * up setting a 3-element effective posix ACL with all | ||
515 | * permissions zero. | ||
516 | */ | ||
491 | nace = 4 + state->users->n + state->groups->n; | 517 | nace = 4 + state->users->n + state->groups->n; |
492 | pacl = posix_acl_alloc(nace, GFP_KERNEL); | 518 | pacl = posix_acl_alloc(nace, GFP_KERNEL); |
493 | if (!pacl) | 519 | if (!pacl) |
@@ -603,6 +629,8 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
603 | u32 mask = ace->access_mask; | 629 | u32 mask = ace->access_mask; |
604 | int i; | 630 | int i; |
605 | 631 | ||
632 | state->empty = 0; | ||
633 | |||
606 | switch (ace2type(ace)) { | 634 | switch (ace2type(ace)) { |
607 | case ACL_USER_OBJ: | 635 | case ACL_USER_OBJ: |
608 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { | 636 | if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) { |
@@ -666,75 +694,62 @@ static void process_one_v4_ace(struct posix_acl_state *state, | |||
666 | } | 694 | } |
667 | } | 695 | } |
668 | 696 | ||
669 | static struct posix_acl * | 697 | int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl, |
670 | _nfsv4_to_posix_one(struct nfs4_acl *n4acl, unsigned int flags) | 698 | struct posix_acl **dpacl, unsigned int flags) |
671 | { | 699 | { |
672 | struct posix_acl_state state; | 700 | struct posix_acl_state effective_acl_state, default_acl_state; |
673 | struct posix_acl *pacl; | ||
674 | struct nfs4_ace *ace; | 701 | struct nfs4_ace *ace; |
675 | int ret; | 702 | int ret; |
676 | 703 | ||
677 | ret = init_state(&state, n4acl->naces); | 704 | ret = init_state(&effective_acl_state, acl->naces); |
678 | if (ret) | 705 | if (ret) |
679 | return ERR_PTR(ret); | 706 | return ret; |
680 | 707 | ret = init_state(&default_acl_state, acl->naces); | |
681 | list_for_each_entry(ace, &n4acl->ace_head, l_ace) | 708 | if (ret) |
682 | process_one_v4_ace(&state, ace); | 709 | goto out_estate; |
683 | 710 | ret = -EINVAL; | |
684 | pacl = posix_state_to_acl(&state, flags); | 711 | for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { |
685 | |||
686 | free_state(&state); | ||
687 | |||
688 | if (!IS_ERR(pacl)) | ||
689 | sort_pacl(pacl); | ||
690 | return pacl; | ||
691 | } | ||
692 | |||
693 | static int | ||
694 | nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl) | ||
695 | { | ||
696 | struct list_head *h, *n; | ||
697 | struct nfs4_ace *ace; | ||
698 | int error = 0; | ||
699 | |||
700 | list_for_each_safe(h, n, &acl->ace_head) { | ||
701 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
702 | |||
703 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && | 712 | if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && |
704 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) | 713 | ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) |
705 | return -EINVAL; | 714 | goto out_dstate; |
706 | |||
707 | if (ace->flag & ~NFS4_SUPPORTED_FLAGS) | 715 | if (ace->flag & ~NFS4_SUPPORTED_FLAGS) |
708 | return -EINVAL; | 716 | goto out_dstate; |
709 | 717 | if ((ace->flag & NFS4_INHERITANCE_FLAGS) == 0) { | |
710 | switch (ace->flag & NFS4_INHERITANCE_FLAGS) { | 718 | process_one_v4_ace(&effective_acl_state, ace); |
711 | case 0: | ||
712 | /* Leave this ace in the effective acl: */ | ||
713 | continue; | 719 | continue; |
714 | case NFS4_INHERITANCE_FLAGS: | ||
715 | /* Add this ace to the default acl and remove it | ||
716 | * from the effective acl: */ | ||
717 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, | ||
718 | ace->access_mask, ace->whotype, ace->who); | ||
719 | if (error) | ||
720 | return error; | ||
721 | list_del(h); | ||
722 | kfree(ace); | ||
723 | acl->naces--; | ||
724 | break; | ||
725 | case NFS4_INHERITANCE_FLAGS & ~NFS4_ACE_INHERIT_ONLY_ACE: | ||
726 | /* Add this ace to the default, but leave it in | ||
727 | * the effective acl as well: */ | ||
728 | error = nfs4_acl_add_ace(dacl, ace->type, ace->flag, | ||
729 | ace->access_mask, ace->whotype, ace->who); | ||
730 | if (error) | ||
731 | return error; | ||
732 | break; | ||
733 | default: | ||
734 | return -EINVAL; | ||
735 | } | 720 | } |
721 | if (!(flags & NFS4_ACL_DIR)) | ||
722 | goto out_dstate; | ||
723 | /* | ||
724 | * Note that when only one of FILE_INHERIT or DIRECTORY_INHERIT | ||
725 | * is set, we're effectively turning on the other. That's OK, | ||
726 | * according to rfc 3530. | ||
727 | */ | ||
728 | process_one_v4_ace(&default_acl_state, ace); | ||
729 | |||
730 | if (!(ace->flag & NFS4_ACE_INHERIT_ONLY_ACE)) | ||
731 | process_one_v4_ace(&effective_acl_state, ace); | ||
736 | } | 732 | } |
737 | return 0; | 733 | *pacl = posix_state_to_acl(&effective_acl_state, flags); |
734 | if (IS_ERR(*pacl)) { | ||
735 | ret = PTR_ERR(*pacl); | ||
736 | goto out_dstate; | ||
737 | } | ||
738 | *dpacl = posix_state_to_acl(&default_acl_state, | ||
739 | flags | NFS4_ACL_TYPE_DEFAULT); | ||
740 | if (IS_ERR(*dpacl)) { | ||
741 | ret = PTR_ERR(*dpacl); | ||
742 | posix_acl_release(*pacl); | ||
743 | goto out_dstate; | ||
744 | } | ||
745 | sort_pacl(*pacl); | ||
746 | sort_pacl(*dpacl); | ||
747 | ret = 0; | ||
748 | out_dstate: | ||
749 | free_state(&default_acl_state); | ||
750 | out_estate: | ||
751 | free_state(&effective_acl_state); | ||
752 | return ret; | ||
738 | } | 753 | } |
739 | 754 | ||
740 | static short | 755 | static short |
@@ -759,48 +774,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4); | |||
759 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); | 774 | EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); |
760 | 775 | ||
761 | struct nfs4_acl * | 776 | struct nfs4_acl * |
762 | nfs4_acl_new(void) | 777 | nfs4_acl_new(int n) |
763 | { | 778 | { |
764 | struct nfs4_acl *acl; | 779 | struct nfs4_acl *acl; |
765 | 780 | ||
766 | if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) | 781 | acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL); |
782 | if (acl == NULL) | ||
767 | return NULL; | 783 | return NULL; |
768 | |||
769 | acl->naces = 0; | 784 | acl->naces = 0; |
770 | INIT_LIST_HEAD(&acl->ace_head); | ||
771 | |||
772 | return acl; | 785 | return acl; |
773 | } | 786 | } |
774 | 787 | ||
775 | void | 788 | void |
776 | nfs4_acl_free(struct nfs4_acl *acl) | ||
777 | { | ||
778 | struct list_head *h; | ||
779 | struct nfs4_ace *ace; | ||
780 | |||
781 | if (!acl) | ||
782 | return; | ||
783 | |||
784 | while (!list_empty(&acl->ace_head)) { | ||
785 | h = acl->ace_head.next; | ||
786 | list_del(h); | ||
787 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
788 | kfree(ace); | ||
789 | } | ||
790 | |||
791 | kfree(acl); | ||
792 | |||
793 | return; | ||
794 | } | ||
795 | |||
796 | int | ||
797 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | 789 | nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, |
798 | int whotype, uid_t who) | 790 | int whotype, uid_t who) |
799 | { | 791 | { |
800 | struct nfs4_ace *ace; | 792 | struct nfs4_ace *ace = acl->aces + acl->naces; |
801 | |||
802 | if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL) | ||
803 | return -ENOMEM; | ||
804 | 793 | ||
805 | ace->type = type; | 794 | ace->type = type; |
806 | ace->flag = flag; | 795 | ace->flag = flag; |
@@ -808,10 +797,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, | |||
808 | ace->whotype = whotype; | 797 | ace->whotype = whotype; |
809 | ace->who = who; | 798 | ace->who = who; |
810 | 799 | ||
811 | list_add_tail(&ace->l_ace, &acl->ace_head); | ||
812 | acl->naces++; | 800 | acl->naces++; |
813 | |||
814 | return 0; | ||
815 | } | 801 | } |
816 | 802 | ||
817 | static struct { | 803 | static struct { |
@@ -865,7 +851,6 @@ nfs4_acl_write_who(int who, char *p) | |||
865 | } | 851 | } |
866 | 852 | ||
867 | EXPORT_SYMBOL(nfs4_acl_new); | 853 | EXPORT_SYMBOL(nfs4_acl_new); |
868 | EXPORT_SYMBOL(nfs4_acl_free); | ||
869 | EXPORT_SYMBOL(nfs4_acl_add_ace); | 854 | EXPORT_SYMBOL(nfs4_acl_add_ace); |
870 | EXPORT_SYMBOL(nfs4_acl_get_whotype); | 855 | EXPORT_SYMBOL(nfs4_acl_get_whotype); |
871 | EXPORT_SYMBOL(nfs4_acl_write_who); | 856 | EXPORT_SYMBOL(nfs4_acl_write_who); |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index f57655a7a2..fb14d68eac 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -387,7 +387,6 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
387 | .address = (struct sockaddr *)&addr, | 387 | .address = (struct sockaddr *)&addr, |
388 | .addrsize = sizeof(addr), | 388 | .addrsize = sizeof(addr), |
389 | .timeout = &timeparms, | 389 | .timeout = &timeparms, |
390 | .servername = clp->cl_name.data, | ||
391 | .program = program, | 390 | .program = program, |
392 | .version = nfs_cb_version[1]->number, | 391 | .version = nfs_cb_version[1]->number, |
393 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ | 392 | .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ |
@@ -397,6 +396,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
397 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], | 396 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], |
398 | .rpc_argp = clp, | 397 | .rpc_argp = clp, |
399 | }; | 398 | }; |
399 | char clientname[16]; | ||
400 | int status; | 400 | int status; |
401 | 401 | ||
402 | if (atomic_read(&cb->cb_set)) | 402 | if (atomic_read(&cb->cb_set)) |
@@ -419,6 +419,11 @@ nfsd4_probe_callback(struct nfs4_client *clp) | |||
419 | memset(program->stats, 0, sizeof(cb->cb_stat)); | 419 | memset(program->stats, 0, sizeof(cb->cb_stat)); |
420 | program->stats->program = program; | 420 | program->stats->program = program; |
421 | 421 | ||
422 | /* Just here to make some printk's more useful: */ | ||
423 | snprintf(clientname, sizeof(clientname), | ||
424 | "%u.%u.%u.%u", NIPQUAD(addr.sin_addr)); | ||
425 | args.servername = clientname; | ||
426 | |||
422 | /* Create RPC client */ | 427 | /* Create RPC client */ |
423 | cb->cb_client = rpc_create(&args); | 428 | cb->cb_client = rpc_create(&args); |
424 | if (IS_ERR(cb->cb_client)) { | 429 | if (IS_ERR(cb->cb_client)) { |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 0efba557fb..5d090f11f2 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -199,24 +199,22 @@ defer_free(struct nfsd4_compoundargs *argp, | |||
199 | 199 | ||
200 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) | 200 | static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) |
201 | { | 201 | { |
202 | void *new = NULL; | ||
203 | if (p == argp->tmp) { | 202 | if (p == argp->tmp) { |
204 | new = kmalloc(nbytes, GFP_KERNEL); | 203 | p = kmalloc(nbytes, GFP_KERNEL); |
205 | if (!new) return NULL; | 204 | if (!p) |
206 | p = new; | 205 | return NULL; |
207 | memcpy(p, argp->tmp, nbytes); | 206 | memcpy(p, argp->tmp, nbytes); |
208 | } else { | 207 | } else { |
209 | BUG_ON(p != argp->tmpp); | 208 | BUG_ON(p != argp->tmpp); |
210 | argp->tmpp = NULL; | 209 | argp->tmpp = NULL; |
211 | } | 210 | } |
212 | if (defer_free(argp, kfree, p)) { | 211 | if (defer_free(argp, kfree, p)) { |
213 | kfree(new); | 212 | kfree(p); |
214 | return NULL; | 213 | return NULL; |
215 | } else | 214 | } else |
216 | return (char *)p; | 215 | return (char *)p; |
217 | } | 216 | } |
218 | 217 | ||
219 | |||
220 | static __be32 | 218 | static __be32 |
221 | nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) | 219 | nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) |
222 | { | 220 | { |
@@ -255,7 +253,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
255 | return status; | 253 | return status; |
256 | 254 | ||
257 | /* | 255 | /* |
258 | * According to spec, unsupported attributes return ERR_NOTSUPP; | 256 | * According to spec, unsupported attributes return ERR_ATTRNOTSUPP; |
259 | * read-only attributes return ERR_INVAL. | 257 | * read-only attributes return ERR_INVAL. |
260 | */ | 258 | */ |
261 | if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) | 259 | if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) |
@@ -273,42 +271,42 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
273 | iattr->ia_valid |= ATTR_SIZE; | 271 | iattr->ia_valid |= ATTR_SIZE; |
274 | } | 272 | } |
275 | if (bmval[0] & FATTR4_WORD0_ACL) { | 273 | if (bmval[0] & FATTR4_WORD0_ACL) { |
276 | int nace, i; | 274 | int nace; |
277 | struct nfs4_ace ace; | 275 | struct nfs4_ace *ace; |
278 | 276 | ||
279 | READ_BUF(4); len += 4; | 277 | READ_BUF(4); len += 4; |
280 | READ32(nace); | 278 | READ32(nace); |
281 | 279 | ||
282 | *acl = nfs4_acl_new(); | 280 | if (nace > NFS4_ACL_MAX) |
281 | return nfserr_resource; | ||
282 | |||
283 | *acl = nfs4_acl_new(nace); | ||
283 | if (*acl == NULL) { | 284 | if (*acl == NULL) { |
284 | host_err = -ENOMEM; | 285 | host_err = -ENOMEM; |
285 | goto out_nfserr; | 286 | goto out_nfserr; |
286 | } | 287 | } |
287 | defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl); | 288 | defer_free(argp, kfree, *acl); |
288 | 289 | ||
289 | for (i = 0; i < nace; i++) { | 290 | (*acl)->naces = nace; |
291 | for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { | ||
290 | READ_BUF(16); len += 16; | 292 | READ_BUF(16); len += 16; |
291 | READ32(ace.type); | 293 | READ32(ace->type); |
292 | READ32(ace.flag); | 294 | READ32(ace->flag); |
293 | READ32(ace.access_mask); | 295 | READ32(ace->access_mask); |
294 | READ32(dummy32); | 296 | READ32(dummy32); |
295 | READ_BUF(dummy32); | 297 | READ_BUF(dummy32); |
296 | len += XDR_QUADLEN(dummy32) << 2; | 298 | len += XDR_QUADLEN(dummy32) << 2; |
297 | READMEM(buf, dummy32); | 299 | READMEM(buf, dummy32); |
298 | ace.whotype = nfs4_acl_get_whotype(buf, dummy32); | 300 | ace->whotype = nfs4_acl_get_whotype(buf, dummy32); |
299 | host_err = 0; | 301 | host_err = 0; |
300 | if (ace.whotype != NFS4_ACL_WHO_NAMED) | 302 | if (ace->whotype != NFS4_ACL_WHO_NAMED) |
301 | ace.who = 0; | 303 | ace->who = 0; |
302 | else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP) | 304 | else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) |
303 | host_err = nfsd_map_name_to_gid(argp->rqstp, | 305 | host_err = nfsd_map_name_to_gid(argp->rqstp, |
304 | buf, dummy32, &ace.who); | 306 | buf, dummy32, &ace->who); |
305 | else | 307 | else |
306 | host_err = nfsd_map_name_to_uid(argp->rqstp, | 308 | host_err = nfsd_map_name_to_uid(argp->rqstp, |
307 | buf, dummy32, &ace.who); | 309 | buf, dummy32, &ace->who); |
308 | if (host_err) | ||
309 | goto out_nfserr; | ||
310 | host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag, | ||
311 | ace.access_mask, ace.whotype, ace.who); | ||
312 | if (host_err) | 310 | if (host_err) |
313 | goto out_nfserr; | 311 | goto out_nfserr; |
314 | } | 312 | } |
@@ -1596,7 +1594,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1596 | } | 1594 | } |
1597 | if (bmval0 & FATTR4_WORD0_ACL) { | 1595 | if (bmval0 & FATTR4_WORD0_ACL) { |
1598 | struct nfs4_ace *ace; | 1596 | struct nfs4_ace *ace; |
1599 | struct list_head *h; | ||
1600 | 1597 | ||
1601 | if (acl == NULL) { | 1598 | if (acl == NULL) { |
1602 | if ((buflen -= 4) < 0) | 1599 | if ((buflen -= 4) < 0) |
@@ -1609,9 +1606,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1609 | goto out_resource; | 1606 | goto out_resource; |
1610 | WRITE32(acl->naces); | 1607 | WRITE32(acl->naces); |
1611 | 1608 | ||
1612 | list_for_each(h, &acl->ace_head) { | 1609 | for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { |
1613 | ace = list_entry(h, struct nfs4_ace, l_ace); | ||
1614 | |||
1615 | if ((buflen -= 4*3) < 0) | 1610 | if ((buflen -= 4*3) < 0) |
1616 | goto out_resource; | 1611 | goto out_resource; |
1617 | WRITE32(ace->type); | 1612 | WRITE32(ace->type); |
@@ -1821,7 +1816,7 @@ out_acl: | |||
1821 | status = nfs_ok; | 1816 | status = nfs_ok; |
1822 | 1817 | ||
1823 | out: | 1818 | out: |
1824 | nfs4_acl_free(acl); | 1819 | kfree(acl); |
1825 | if (fhp == &tempfh) | 1820 | if (fhp == &tempfh) |
1826 | fh_put(&tempfh); | 1821 | fh_put(&tempfh); |
1827 | return status; | 1822 | return status; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8283236c6a..7e6aa245b5 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -466,7 +466,10 @@ out: | |||
466 | posix_acl_release(dpacl); | 466 | posix_acl_release(dpacl); |
467 | return (error); | 467 | return (error); |
468 | out_nfserr: | 468 | out_nfserr: |
469 | error = nfserrno(host_error); | 469 | if (host_error == -EOPNOTSUPP) |
470 | error = nfserr_attrnotsupp; | ||
471 | else | ||
472 | error = nfserrno(host_error); | ||
470 | goto out; | 473 | goto out; |
471 | } | 474 | } |
472 | 475 | ||