]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/cifs/cifsacl.c
Merge remote-tracking branch 'signal/for-next'
[karo-tx-linux.git] / fs / cifs / cifsacl.c
1 /*
2  *   fs/cifs/cifsacl.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2007,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for mapping CIFS/NTFS ACLs
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24 #include <linux/fs.h>
25 #include <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/keyctl.h>
28 #include <linux/key-type.h>
29 #include <linux/moduleparam.h>
30 #include <keys/user-type.h>
31 #include "cifspdu.h"
32 #include "cifsglob.h"
33 #include "cifsacl.h"
34 #include "cifsproto.h"
35 #include "cifs_debug.h"
36
37 /* security id for everyone/world system group */
38 static const struct cifs_sid sid_everyone = {
39         1, 1, {0, 0, 0, 0, 0, 1}, {0} };
40 /* security id for Authenticated Users system group */
41 static const struct cifs_sid sid_authusers = {
42         1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
43 /* group users */
44 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
45
46 static const struct cred *root_cred;
47
48 static unsigned int cifs_idmap_cache_timeout = 600;
49 module_param(cifs_idmap_cache_timeout, uint, 0644);
50 MODULE_PARM_DESC(cifs_idmap_cache_timeout, "Number of seconds that ID mappings "
51                         "stay in cache. (default=600)");
52
53 static int
54 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
55 {
56         char *payload;
57
58         /*
59          * If the payload is less than or equal to the size of a pointer, then
60          * an allocation here is wasteful. Just copy the data directly to the
61          * payload.value union member instead.
62          *
63          * With this however, you must check the datalen before trying to
64          * dereference payload.data!
65          */
66         if (prep->datalen <= sizeof(void *)) {
67                 key->payload.value = 0;
68                 memcpy(&key->payload.value, prep->data, prep->datalen);
69                 key->datalen = prep->datalen;
70                 return 0;
71         }
72         payload = kmalloc(prep->datalen, GFP_KERNEL);
73         if (!payload)
74                 return -ENOMEM;
75
76         memcpy(payload, prep->data, prep->datalen);
77         key->payload.data = payload;
78         key->datalen = prep->datalen;
79         return 0;
80 }
81
82 static inline void
83 cifs_idmap_key_destroy(struct key *key)
84 {
85         if (key->datalen > sizeof(void *))
86                 kfree(key->payload.data);
87 }
88
89 static struct key_type cifs_idmap_key_type = {
90         .name        = "cifs.idmap",
91         .instantiate = cifs_idmap_key_instantiate,
92         .destroy     = cifs_idmap_key_destroy,
93         .describe    = user_describe,
94         .match       = user_match,
95 };
96
97 static char *
98 sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
99 {
100         int i, len;
101         unsigned int saval;
102         char *sidstr, *strptr;
103
104         /* 3 bytes for prefix */
105         sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
106                          (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
107                          GFP_KERNEL);
108         if (!sidstr)
109                 return sidstr;
110
111         strptr = sidstr;
112         len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
113                         sidptr->revision);
114         strptr += len;
115
116         for (i = 0; i < NUM_AUTHS; ++i) {
117                 if (sidptr->authority[i]) {
118                         len = sprintf(strptr, "-%hhu", sidptr->authority[i]);
119                         strptr += len;
120                 }
121         }
122
123         for (i = 0; i < sidptr->num_subauth; ++i) {
124                 saval = le32_to_cpu(sidptr->sub_auth[i]);
125                 len = sprintf(strptr, "-%u", saval);
126                 strptr += len;
127         }
128
129         return sidstr;
130 }
131
132 /*
133  * if the two SIDs (roughly equivalent to a UUID for a user or group) are
134  * the same returns zero, if they do not match returns non-zero.
135  */
136 static int
137 compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
138 {
139         int i;
140         int num_subauth, num_sat, num_saw;
141
142         if ((!ctsid) || (!cwsid))
143                 return 1;
144
145         /* compare the revision */
146         if (ctsid->revision != cwsid->revision) {
147                 if (ctsid->revision > cwsid->revision)
148                         return 1;
149                 else
150                         return -1;
151         }
152
153         /* compare all of the six auth values */
154         for (i = 0; i < NUM_AUTHS; ++i) {
155                 if (ctsid->authority[i] != cwsid->authority[i]) {
156                         if (ctsid->authority[i] > cwsid->authority[i])
157                                 return 1;
158                         else
159                                 return -1;
160                 }
161         }
162
163         /* compare all of the subauth values if any */
164         num_sat = ctsid->num_subauth;
165         num_saw = cwsid->num_subauth;
166         num_subauth = num_sat < num_saw ? num_sat : num_saw;
167         if (num_subauth) {
168                 for (i = 0; i < num_subauth; ++i) {
169                         if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
170                                 if (le32_to_cpu(ctsid->sub_auth[i]) >
171                                         le32_to_cpu(cwsid->sub_auth[i]))
172                                         return 1;
173                                 else
174                                         return -1;
175                         }
176                 }
177         }
178
179         return 0; /* sids compare/match */
180 }
181
182 static void
183 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
184 {
185         int i;
186
187         dst->revision = src->revision;
188         dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
189         for (i = 0; i < NUM_AUTHS; ++i)
190                 dst->authority[i] = src->authority[i];
191         for (i = 0; i < dst->num_subauth; ++i)
192                 dst->sub_auth[i] = src->sub_auth[i];
193 }
194
195 static int
196 id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
197 {
198         int rc;
199         struct key *sidkey;
200         struct cifs_sid *ksid;
201         unsigned int ksid_size;
202         char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
203         const struct cred *saved_cred;
204
205         rc = snprintf(desc, sizeof(desc), "%ci:%u",
206                         sidtype == SIDOWNER ? 'o' : 'g', cid);
207         if (rc >= sizeof(desc))
208                 return -EINVAL;
209
210         rc = 0;
211         saved_cred = override_creds(root_cred);
212         sidkey = request_key(&cifs_idmap_key_type, desc, "");
213         if (IS_ERR(sidkey)) {
214                 rc = -EINVAL;
215                 cFYI(1, "%s: Can't map %cid %u to a SID", __func__,
216                         sidtype == SIDOWNER ? 'u' : 'g', cid);
217                 goto out_revert_creds;
218         } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
219                 rc = -EIO;
220                 cFYI(1, "%s: Downcall contained malformed key "
221                         "(datalen=%hu)", __func__, sidkey->datalen);
222                 goto invalidate_key;
223         }
224
225         ksid = (struct cifs_sid *)sidkey->payload.data;
226         ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
227         if (ksid_size > sidkey->datalen) {
228                 rc = -EIO;
229                 cFYI(1, "%s: Downcall contained malformed key (datalen=%hu, "
230                         "ksid_size=%u)", __func__, sidkey->datalen, ksid_size);
231                 goto invalidate_key;
232         }
233         cifs_copy_sid(ssid, ksid);
234         key_set_timeout(sidkey, cifs_idmap_cache_timeout);
235 out_key_put:
236         key_put(sidkey);
237 out_revert_creds:
238         revert_creds(saved_cred);
239         return rc;
240
241 invalidate_key:
242         key_invalidate(sidkey);
243         goto out_key_put;
244 }
245
246 static int
247 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
248                 struct cifs_fattr *fattr, uint sidtype)
249 {
250         int rc;
251         struct key *sidkey;
252         char *sidstr;
253         const struct cred *saved_cred;
254         uid_t fuid = cifs_sb->mnt_uid;
255         gid_t fgid = cifs_sb->mnt_gid;
256
257         /*
258          * If we have too many subauthorities, then something is really wrong.
259          * Just return an error.
260          */
261         if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
262                 cFYI(1, "%s: %u subauthorities is too many!", __func__,
263                         psid->num_subauth);
264                 return -EIO;
265         }
266
267         sidstr = sid_to_key_str(psid, sidtype);
268         if (!sidstr)
269                 return -ENOMEM;
270
271         saved_cred = override_creds(root_cred);
272         sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
273         if (IS_ERR(sidkey)) {
274                 rc = -EINVAL;
275                 cFYI(1, "%s: Can't map SID %s to a %cid", __func__, sidstr,
276                         sidtype == SIDOWNER ? 'u' : 'g');
277                 goto out_revert_creds;
278         }
279
280         /*
281          * FIXME: Here we assume that uid_t and gid_t are same size. It's
282          * probably a safe assumption but might be better to check based on
283          * sidtype.
284          */
285         if (sidkey->datalen != sizeof(uid_t)) {
286                 rc = -EIO;
287                 cFYI(1, "%s: Downcall contained malformed key "
288                         "(datalen=%hu)", __func__, sidkey->datalen);
289                 key_invalidate(sidkey);
290                 goto out_key_put;
291         }
292
293         if (sidtype == SIDOWNER)
294                 fuid = (uid_t)sidkey->payload.value;
295         else
296                 fgid = (gid_t)sidkey->payload.value;
297
298         key_set_timeout(sidkey, cifs_idmap_cache_timeout);
299 out_key_put:
300         key_put(sidkey);
301 out_revert_creds:
302         revert_creds(saved_cred);
303         kfree(sidstr);
304
305         /*
306          * Note that we return 0 here unconditionally. If the mapping
307          * fails then we just fall back to using the mnt_uid/mnt_gid.
308          */
309         if (sidtype == SIDOWNER)
310                 fattr->cf_uid = fuid;
311         else
312                 fattr->cf_gid = fgid;
313         return 0;
314 }
315
316 int
317 init_cifs_idmap(void)
318 {
319         struct cred *cred;
320         struct key *keyring;
321         int ret;
322
323         cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
324
325         /* create an override credential set with a special thread keyring in
326          * which requests are cached
327          *
328          * this is used to prevent malicious redirections from being installed
329          * with add_key().
330          */
331         cred = prepare_kernel_cred(NULL);
332         if (!cred)
333                 return -ENOMEM;
334
335         keyring = keyring_alloc(".cifs_idmap", 0, 0, cred,
336                                 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
337                                 KEY_USR_VIEW | KEY_USR_READ,
338                                 KEY_ALLOC_NOT_IN_QUOTA, NULL);
339         if (IS_ERR(keyring)) {
340                 ret = PTR_ERR(keyring);
341                 goto failed_put_cred;
342         }
343
344         ret = register_key_type(&cifs_idmap_key_type);
345         if (ret < 0)
346                 goto failed_put_key;
347
348         /* instruct request_key() to use this special keyring as a cache for
349          * the results it looks up */
350         set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
351         cred->thread_keyring = keyring;
352         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
353         root_cred = cred;
354
355         cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
356         return 0;
357
358 failed_put_key:
359         key_put(keyring);
360 failed_put_cred:
361         put_cred(cred);
362         return ret;
363 }
364
365 void
366 exit_cifs_idmap(void)
367 {
368         key_revoke(root_cred->thread_keyring);
369         unregister_key_type(&cifs_idmap_key_type);
370         put_cred(root_cred);
371         cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
372 }
373
374 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
375 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
376                                 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
377 {
378         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
379         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
380
381         /* copy security descriptor control portion */
382         pnntsd->revision = pntsd->revision;
383         pnntsd->type = pntsd->type;
384         pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
385         pnntsd->sacloffset = 0;
386         pnntsd->osidoffset = cpu_to_le32(sidsoffset);
387         pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
388
389         /* copy owner sid */
390         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
391                                 le32_to_cpu(pntsd->osidoffset));
392         nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
393         cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
394
395         /* copy group sid */
396         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
397                                 le32_to_cpu(pntsd->gsidoffset));
398         ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
399                                         sizeof(struct cifs_sid));
400         cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
401
402         return;
403 }
404
405
406 /*
407    change posix mode to reflect permissions
408    pmode is the existing mode (we only want to overwrite part of this
409    bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
410 */
411 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
412                                  umode_t *pbits_to_set)
413 {
414         __u32 flags = le32_to_cpu(ace_flags);
415         /* the order of ACEs is important.  The canonical order is to begin with
416            DENY entries followed by ALLOW, otherwise an allow entry could be
417            encountered first, making the subsequent deny entry like "dead code"
418            which would be superflous since Windows stops when a match is made
419            for the operation you are trying to perform for your user */
420
421         /* For deny ACEs we change the mask so that subsequent allow access
422            control entries do not turn on the bits we are denying */
423         if (type == ACCESS_DENIED) {
424                 if (flags & GENERIC_ALL)
425                         *pbits_to_set &= ~S_IRWXUGO;
426
427                 if ((flags & GENERIC_WRITE) ||
428                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
429                         *pbits_to_set &= ~S_IWUGO;
430                 if ((flags & GENERIC_READ) ||
431                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
432                         *pbits_to_set &= ~S_IRUGO;
433                 if ((flags & GENERIC_EXECUTE) ||
434                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
435                         *pbits_to_set &= ~S_IXUGO;
436                 return;
437         } else if (type != ACCESS_ALLOWED) {
438                 cERROR(1, "unknown access control type %d", type);
439                 return;
440         }
441         /* else ACCESS_ALLOWED type */
442
443         if (flags & GENERIC_ALL) {
444                 *pmode |= (S_IRWXUGO & (*pbits_to_set));
445                 cFYI(DBG2, "all perms");
446                 return;
447         }
448         if ((flags & GENERIC_WRITE) ||
449                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
450                 *pmode |= (S_IWUGO & (*pbits_to_set));
451         if ((flags & GENERIC_READ) ||
452                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
453                 *pmode |= (S_IRUGO & (*pbits_to_set));
454         if ((flags & GENERIC_EXECUTE) ||
455                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
456                 *pmode |= (S_IXUGO & (*pbits_to_set));
457
458         cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
459         return;
460 }
461
462 /*
463    Generate access flags to reflect permissions mode is the existing mode.
464    This function is called for every ACE in the DACL whose SID matches
465    with either owner or group or everyone.
466 */
467
468 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
469                                 __u32 *pace_flags)
470 {
471         /* reset access mask */
472         *pace_flags = 0x0;
473
474         /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
475         mode &= bits_to_use;
476
477         /* check for R/W/X UGO since we do not know whose flags
478            is this but we have cleared all the bits sans RWX for
479            either user or group or other as per bits_to_use */
480         if (mode & S_IRUGO)
481                 *pace_flags |= SET_FILE_READ_RIGHTS;
482         if (mode & S_IWUGO)
483                 *pace_flags |= SET_FILE_WRITE_RIGHTS;
484         if (mode & S_IXUGO)
485                 *pace_flags |= SET_FILE_EXEC_RIGHTS;
486
487         cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
488         return;
489 }
490
491 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
492                         const struct cifs_sid *psid, __u64 nmode, umode_t bits)
493 {
494         int i;
495         __u16 size = 0;
496         __u32 access_req = 0;
497
498         pntace->type = ACCESS_ALLOWED;
499         pntace->flags = 0x0;
500         mode_to_access_flags(nmode, bits, &access_req);
501         if (!access_req)
502                 access_req = SET_MINIMUM_RIGHTS;
503         pntace->access_req = cpu_to_le32(access_req);
504
505         pntace->sid.revision = psid->revision;
506         pntace->sid.num_subauth = psid->num_subauth;
507         for (i = 0; i < NUM_AUTHS; i++)
508                 pntace->sid.authority[i] = psid->authority[i];
509         for (i = 0; i < psid->num_subauth; i++)
510                 pntace->sid.sub_auth[i] = psid->sub_auth[i];
511
512         size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
513         pntace->size = cpu_to_le16(size);
514
515         return size;
516 }
517
518
519 #ifdef CONFIG_CIFS_DEBUG2
520 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
521 {
522         int num_subauth;
523
524         /* validate that we do not go past end of acl */
525
526         if (le16_to_cpu(pace->size) < 16) {
527                 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
528                 return;
529         }
530
531         if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
532                 cERROR(1, "ACL too small to parse ACE");
533                 return;
534         }
535
536         num_subauth = pace->sid.num_subauth;
537         if (num_subauth) {
538                 int i;
539                 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
540                         pace->sid.revision, pace->sid.num_subauth, pace->type,
541                         pace->flags, le16_to_cpu(pace->size));
542                 for (i = 0; i < num_subauth; ++i) {
543                         cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
544                                 le32_to_cpu(pace->sid.sub_auth[i]));
545                 }
546
547                 /* BB add length check to make sure that we do not have huge
548                         num auths and therefore go off the end */
549         }
550
551         return;
552 }
553 #endif
554
555
556 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
557                        struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
558                        struct cifs_fattr *fattr)
559 {
560         int i;
561         int num_aces = 0;
562         int acl_size;
563         char *acl_base;
564         struct cifs_ace **ppace;
565
566         /* BB need to add parm so we can store the SID BB */
567
568         if (!pdacl) {
569                 /* no DACL in the security descriptor, set
570                    all the permissions for user/group/other */
571                 fattr->cf_mode |= S_IRWXUGO;
572                 return;
573         }
574
575         /* validate that we do not go past end of acl */
576         if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
577                 cERROR(1, "ACL too small to parse DACL");
578                 return;
579         }
580
581         cFYI(DBG2, "DACL revision %d size %d num aces %d",
582                 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
583                 le32_to_cpu(pdacl->num_aces));
584
585         /* reset rwx permissions for user/group/other.
586            Also, if num_aces is 0 i.e. DACL has no ACEs,
587            user/group/other have no permissions */
588         fattr->cf_mode &= ~(S_IRWXUGO);
589
590         acl_base = (char *)pdacl;
591         acl_size = sizeof(struct cifs_acl);
592
593         num_aces = le32_to_cpu(pdacl->num_aces);
594         if (num_aces > 0) {
595                 umode_t user_mask = S_IRWXU;
596                 umode_t group_mask = S_IRWXG;
597                 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
598
599                 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
600                         return;
601                 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
602                                 GFP_KERNEL);
603                 if (!ppace) {
604                         cERROR(1, "DACL memory allocation error");
605                         return;
606                 }
607
608                 for (i = 0; i < num_aces; ++i) {
609                         ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
610 #ifdef CONFIG_CIFS_DEBUG2
611                         dump_ace(ppace[i], end_of_acl);
612 #endif
613                         if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
614                                 access_flags_to_mode(ppace[i]->access_req,
615                                                      ppace[i]->type,
616                                                      &fattr->cf_mode,
617                                                      &user_mask);
618                         if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
619                                 access_flags_to_mode(ppace[i]->access_req,
620                                                      ppace[i]->type,
621                                                      &fattr->cf_mode,
622                                                      &group_mask);
623                         if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
624                                 access_flags_to_mode(ppace[i]->access_req,
625                                                      ppace[i]->type,
626                                                      &fattr->cf_mode,
627                                                      &other_mask);
628                         if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
629                                 access_flags_to_mode(ppace[i]->access_req,
630                                                      ppace[i]->type,
631                                                      &fattr->cf_mode,
632                                                      &other_mask);
633
634
635 /*                      memcpy((void *)(&(cifscred->aces[i])),
636                                 (void *)ppace[i],
637                                 sizeof(struct cifs_ace)); */
638
639                         acl_base = (char *)ppace[i];
640                         acl_size = le16_to_cpu(ppace[i]->size);
641                 }
642
643                 kfree(ppace);
644         }
645
646         return;
647 }
648
649
650 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
651                         struct cifs_sid *pgrpsid, __u64 nmode)
652 {
653         u16 size = 0;
654         struct cifs_acl *pnndacl;
655
656         pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
657
658         size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
659                                         pownersid, nmode, S_IRWXU);
660         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
661                                         pgrpsid, nmode, S_IRWXG);
662         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
663                                          &sid_everyone, nmode, S_IRWXO);
664
665         pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
666         pndacl->num_aces = cpu_to_le32(3);
667
668         return 0;
669 }
670
671
672 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
673 {
674         /* BB need to add parm so we can store the SID BB */
675
676         /* validate that we do not go past end of ACL - sid must be at least 8
677            bytes long (assuming no sub-auths - e.g. the null SID */
678         if (end_of_acl < (char *)psid + 8) {
679                 cERROR(1, "ACL too small to parse SID %p", psid);
680                 return -EINVAL;
681         }
682
683 #ifdef CONFIG_CIFS_DEBUG2
684         if (psid->num_subauth) {
685                 int i;
686                 cFYI(1, "SID revision %d num_auth %d",
687                         psid->revision, psid->num_subauth);
688
689                 for (i = 0; i < psid->num_subauth; i++) {
690                         cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
691                                 le32_to_cpu(psid->sub_auth[i]));
692                 }
693
694                 /* BB add length check to make sure that we do not have huge
695                         num auths and therefore go off the end */
696                 cFYI(1, "RID 0x%x",
697                         le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
698         }
699 #endif
700
701         return 0;
702 }
703
704
705 /* Convert CIFS ACL to POSIX form */
706 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
707                 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
708 {
709         int rc = 0;
710         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
711         struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
712         char *end_of_acl = ((char *)pntsd) + acl_len;
713         __u32 dacloffset;
714
715         if (pntsd == NULL)
716                 return -EIO;
717
718         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
719                                 le32_to_cpu(pntsd->osidoffset));
720         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
721                                 le32_to_cpu(pntsd->gsidoffset));
722         dacloffset = le32_to_cpu(pntsd->dacloffset);
723         dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
724         cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
725                  "sacloffset 0x%x dacloffset 0x%x",
726                  pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
727                  le32_to_cpu(pntsd->gsidoffset),
728                  le32_to_cpu(pntsd->sacloffset), dacloffset);
729 /*      cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
730         rc = parse_sid(owner_sid_ptr, end_of_acl);
731         if (rc) {
732                 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
733                 return rc;
734         }
735         rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
736         if (rc) {
737                 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
738                 return rc;
739         }
740
741         rc = parse_sid(group_sid_ptr, end_of_acl);
742         if (rc) {
743                 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
744                 return rc;
745         }
746         rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
747         if (rc) {
748                 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
749                 return rc;
750         }
751
752         if (dacloffset)
753                 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
754                            group_sid_ptr, fattr);
755         else
756                 cFYI(1, "no ACL"); /* BB grant all or default perms? */
757
758         return rc;
759 }
760
761 /* Convert permission bits from mode to equivalent CIFS ACL */
762 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
763         __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
764 {
765         int rc = 0;
766         __u32 dacloffset;
767         __u32 ndacloffset;
768         __u32 sidsoffset;
769         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
770         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
771         struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
772         struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
773
774         if (nmode != NO_CHANGE_64) { /* chmod */
775                 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
776                                 le32_to_cpu(pntsd->osidoffset));
777                 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
778                                 le32_to_cpu(pntsd->gsidoffset));
779                 dacloffset = le32_to_cpu(pntsd->dacloffset);
780                 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
781                 ndacloffset = sizeof(struct cifs_ntsd);
782                 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
783                 ndacl_ptr->revision = dacl_ptr->revision;
784                 ndacl_ptr->size = 0;
785                 ndacl_ptr->num_aces = 0;
786
787                 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
788                                         nmode);
789                 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
790                 /* copy sec desc control portion & owner and group sids */
791                 copy_sec_desc(pntsd, pnntsd, sidsoffset);
792                 *aclflag = CIFS_ACL_DACL;
793         } else {
794                 memcpy(pnntsd, pntsd, secdesclen);
795                 if (uid != NO_CHANGE_32) { /* chown */
796                         owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
797                                         le32_to_cpu(pnntsd->osidoffset));
798                         nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
799                                                                 GFP_KERNEL);
800                         if (!nowner_sid_ptr)
801                                 return -ENOMEM;
802                         rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
803                         if (rc) {
804                                 cFYI(1, "%s: Mapping error %d for owner id %d",
805                                                 __func__, rc, uid);
806                                 kfree(nowner_sid_ptr);
807                                 return rc;
808                         }
809                         cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
810                         kfree(nowner_sid_ptr);
811                         *aclflag = CIFS_ACL_OWNER;
812                 }
813                 if (gid != NO_CHANGE_32) { /* chgrp */
814                         group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
815                                         le32_to_cpu(pnntsd->gsidoffset));
816                         ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
817                                                                 GFP_KERNEL);
818                         if (!ngroup_sid_ptr)
819                                 return -ENOMEM;
820                         rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
821                         if (rc) {
822                                 cFYI(1, "%s: Mapping error %d for group id %d",
823                                                 __func__, rc, gid);
824                                 kfree(ngroup_sid_ptr);
825                                 return rc;
826                         }
827                         cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
828                         kfree(ngroup_sid_ptr);
829                         *aclflag = CIFS_ACL_GROUP;
830                 }
831         }
832
833         return rc;
834 }
835
836 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
837                 __u16 fid, u32 *pacllen)
838 {
839         struct cifs_ntsd *pntsd = NULL;
840         unsigned int xid;
841         int rc;
842         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
843
844         if (IS_ERR(tlink))
845                 return ERR_CAST(tlink);
846
847         xid = get_xid();
848         rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
849         free_xid(xid);
850
851         cifs_put_tlink(tlink);
852
853         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
854         if (rc)
855                 return ERR_PTR(rc);
856         return pntsd;
857 }
858
859 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
860                 const char *path, u32 *pacllen)
861 {
862         struct cifs_ntsd *pntsd = NULL;
863         int oplock = 0;
864         unsigned int xid;
865         int rc, create_options = 0;
866         __u16 fid;
867         struct cifs_tcon *tcon;
868         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
869
870         if (IS_ERR(tlink))
871                 return ERR_CAST(tlink);
872
873         tcon = tlink_tcon(tlink);
874         xid = get_xid();
875
876         if (backup_cred(cifs_sb))
877                 create_options |= CREATE_OPEN_BACKUP_INTENT;
878
879         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
880                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
881                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
882         if (!rc) {
883                 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
884                 CIFSSMBClose(xid, tcon, fid);
885         }
886
887         cifs_put_tlink(tlink);
888         free_xid(xid);
889
890         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
891         if (rc)
892                 return ERR_PTR(rc);
893         return pntsd;
894 }
895
896 /* Retrieve an ACL from the server */
897 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
898                                       struct inode *inode, const char *path,
899                                       u32 *pacllen)
900 {
901         struct cifs_ntsd *pntsd = NULL;
902         struct cifsFileInfo *open_file = NULL;
903
904         if (inode)
905                 open_file = find_readable_file(CIFS_I(inode), true);
906         if (!open_file)
907                 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
908
909         pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
910         cifsFileInfo_put(open_file);
911         return pntsd;
912 }
913
914  /* Set an ACL on the server */
915 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
916                         struct inode *inode, const char *path, int aclflag)
917 {
918         int oplock = 0;
919         unsigned int xid;
920         int rc, access_flags, create_options = 0;
921         __u16 fid;
922         struct cifs_tcon *tcon;
923         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
924         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
925
926         if (IS_ERR(tlink))
927                 return PTR_ERR(tlink);
928
929         tcon = tlink_tcon(tlink);
930         xid = get_xid();
931
932         if (backup_cred(cifs_sb))
933                 create_options |= CREATE_OPEN_BACKUP_INTENT;
934
935         if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
936                 access_flags = WRITE_OWNER;
937         else
938                 access_flags = WRITE_DAC;
939
940         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
941                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
942                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
943         if (rc) {
944                 cERROR(1, "Unable to open file to set ACL");
945                 goto out;
946         }
947
948         rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
949         cFYI(DBG2, "SetCIFSACL rc = %d", rc);
950
951         CIFSSMBClose(xid, tcon, fid);
952 out:
953         free_xid(xid);
954         cifs_put_tlink(tlink);
955         return rc;
956 }
957
958 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
959 int
960 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
961                   struct inode *inode, const char *path, const __u16 *pfid)
962 {
963         struct cifs_ntsd *pntsd = NULL;
964         u32 acllen = 0;
965         int rc = 0;
966
967         cFYI(DBG2, "converting ACL to mode for %s", path);
968
969         if (pfid)
970                 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
971         else
972                 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
973
974         /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
975         if (IS_ERR(pntsd)) {
976                 rc = PTR_ERR(pntsd);
977                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
978         } else {
979                 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
980                 kfree(pntsd);
981                 if (rc)
982                         cERROR(1, "parse sec desc failed rc = %d", rc);
983         }
984
985         return rc;
986 }
987
988 /* Convert mode bits to an ACL so we can update the ACL on the server */
989 int
990 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
991                         uid_t uid, gid_t gid)
992 {
993         int rc = 0;
994         int aclflag = CIFS_ACL_DACL; /* default flag to set */
995         __u32 secdesclen = 0;
996         struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
997         struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
998
999         cFYI(DBG2, "set ACL from mode for %s", path);
1000
1001         /* Get the security descriptor */
1002         pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1003         if (IS_ERR(pntsd)) {
1004                 rc = PTR_ERR(pntsd);
1005                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1006                 goto out;
1007         }
1008
1009         /*
1010          * Add three ACEs for owner, group, everyone getting rid of other ACEs
1011          * as chmod disables ACEs and set the security descriptor. Allocate
1012          * memory for the smb header, set security descriptor request security
1013          * descriptor parameters, and secuirty descriptor itself
1014          */
1015         secdesclen = max_t(u32, secdesclen, DEFSECDESCLEN);
1016         pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1017         if (!pnntsd) {
1018                 cERROR(1, "Unable to allocate security descriptor");
1019                 kfree(pntsd);
1020                 return -ENOMEM;
1021         }
1022
1023         rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1024                                 &aclflag);
1025
1026         cFYI(DBG2, "build_sec_desc rc: %d", rc);
1027
1028         if (!rc) {
1029                 /* Set the security descriptor */
1030                 rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
1031                 cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1032         }
1033
1034         kfree(pnntsd);
1035         kfree(pntsd);
1036 out:
1037         return rc;
1038 }