]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/cifs/cifsacl.c
Merge branches 'no-rebases', 'arch-avr32', 'arch-blackfin', 'arch-cris', 'arch-h8300...
[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 <keys/user-type.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsacl.h"
33 #include "cifsproto.h"
34 #include "cifs_debug.h"
35
36 /* security id for everyone/world system group */
37 static const struct cifs_sid sid_everyone = {
38         1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39 /* security id for Authenticated Users system group */
40 static const struct cifs_sid sid_authusers = {
41         1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
42 /* group users */
43 static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
44
45 const struct cred *root_cred;
46
47 static void
48 shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
49                         int *nr_del)
50 {
51         struct rb_node *node;
52         struct rb_node *tmp;
53         struct cifs_sid_id *psidid;
54
55         node = rb_first(root);
56         while (node) {
57                 tmp = node;
58                 node = rb_next(tmp);
59                 psidid = rb_entry(tmp, struct cifs_sid_id, rbnode);
60                 if (nr_to_scan == 0 || *nr_del == nr_to_scan)
61                         ++(*nr_rem);
62                 else {
63                         if (time_after(jiffies, psidid->time + SID_MAP_EXPIRE)
64                                                 && psidid->refcount == 0) {
65                                 rb_erase(tmp, root);
66                                 ++(*nr_del);
67                         } else
68                                 ++(*nr_rem);
69                 }
70         }
71 }
72
73 /*
74  * Run idmap cache shrinker.
75  */
76 static int
77 cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc)
78 {
79         int nr_to_scan = sc->nr_to_scan;
80         int nr_del = 0;
81         int nr_rem = 0;
82         struct rb_root *root;
83
84         root = &uidtree;
85         spin_lock(&siduidlock);
86         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
87         spin_unlock(&siduidlock);
88
89         root = &gidtree;
90         spin_lock(&sidgidlock);
91         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
92         spin_unlock(&sidgidlock);
93
94         root = &siduidtree;
95         spin_lock(&uidsidlock);
96         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
97         spin_unlock(&uidsidlock);
98
99         root = &sidgidtree;
100         spin_lock(&gidsidlock);
101         shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del);
102         spin_unlock(&gidsidlock);
103
104         return nr_rem;
105 }
106
107 static void
108 sid_rb_insert(struct rb_root *root, unsigned long cid,
109                 struct cifs_sid_id **psidid, char *typestr)
110 {
111         char *strptr;
112         struct rb_node *node = root->rb_node;
113         struct rb_node *parent = NULL;
114         struct rb_node **linkto = &(root->rb_node);
115         struct cifs_sid_id *lsidid;
116
117         while (node) {
118                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
119                 parent = node;
120                 if (cid > lsidid->id) {
121                         linkto = &(node->rb_left);
122                         node = node->rb_left;
123                 }
124                 if (cid < lsidid->id) {
125                         linkto = &(node->rb_right);
126                         node = node->rb_right;
127                 }
128         }
129
130         (*psidid)->id = cid;
131         (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
132         (*psidid)->refcount = 0;
133
134         sprintf((*psidid)->sidstr, "%s", typestr);
135         strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
136         sprintf(strptr, "%ld", cid);
137
138         clear_bit(SID_ID_PENDING, &(*psidid)->state);
139         clear_bit(SID_ID_MAPPED, &(*psidid)->state);
140
141         rb_link_node(&(*psidid)->rbnode, parent, linkto);
142         rb_insert_color(&(*psidid)->rbnode, root);
143 }
144
145 static struct cifs_sid_id *
146 sid_rb_search(struct rb_root *root, unsigned long cid)
147 {
148         struct rb_node *node = root->rb_node;
149         struct cifs_sid_id *lsidid;
150
151         while (node) {
152                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
153                 if (cid > lsidid->id)
154                         node = node->rb_left;
155                 else if (cid < lsidid->id)
156                         node = node->rb_right;
157                 else /* node found */
158                         return lsidid;
159         }
160
161         return NULL;
162 }
163
164 static struct shrinker cifs_shrinker = {
165         .shrink = cifs_idmap_shrinker,
166         .seeks = DEFAULT_SEEKS,
167 };
168
169 static int
170 cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
171 {
172         char *payload;
173
174         payload = kmalloc(prep->datalen, GFP_KERNEL);
175         if (!payload)
176                 return -ENOMEM;
177
178         memcpy(payload, prep->data, prep->datalen);
179         key->payload.data = payload;
180         key->datalen = prep->datalen;
181         return 0;
182 }
183
184 static inline void
185 cifs_idmap_key_destroy(struct key *key)
186 {
187         kfree(key->payload.data);
188 }
189
190 struct key_type cifs_idmap_key_type = {
191         .name        = "cifs.idmap",
192         .instantiate = cifs_idmap_key_instantiate,
193         .destroy     = cifs_idmap_key_destroy,
194         .describe    = user_describe,
195         .match       = user_match,
196 };
197
198 static void
199 sid_to_str(struct cifs_sid *sidptr, char *sidstr)
200 {
201         int i;
202         unsigned long saval;
203         char *strptr;
204
205         strptr = sidstr;
206
207         sprintf(strptr, "%s", "S");
208         strptr = sidstr + strlen(sidstr);
209
210         sprintf(strptr, "-%d", sidptr->revision);
211         strptr = sidstr + strlen(sidstr);
212
213         for (i = 0; i < 6; ++i) {
214                 if (sidptr->authority[i]) {
215                         sprintf(strptr, "-%d", sidptr->authority[i]);
216                         strptr = sidstr + strlen(sidstr);
217                 }
218         }
219
220         for (i = 0; i < sidptr->num_subauth; ++i) {
221                 saval = le32_to_cpu(sidptr->sub_auth[i]);
222                 sprintf(strptr, "-%ld", saval);
223                 strptr = sidstr + strlen(sidstr);
224         }
225 }
226
227 static void
228 cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
229 {
230         memcpy(dst, src, sizeof(*dst));
231         dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
232 }
233
234 static void
235 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
236                 struct cifs_sid_id **psidid, char *typestr)
237 {
238         int rc;
239         char *strptr;
240         struct rb_node *node = root->rb_node;
241         struct rb_node *parent = NULL;
242         struct rb_node **linkto = &(root->rb_node);
243         struct cifs_sid_id *lsidid;
244
245         while (node) {
246                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
247                 parent = node;
248                 rc = compare_sids(sidptr, &((lsidid)->sid));
249                 if (rc > 0) {
250                         linkto = &(node->rb_left);
251                         node = node->rb_left;
252                 } else if (rc < 0) {
253                         linkto = &(node->rb_right);
254                         node = node->rb_right;
255                 }
256         }
257
258         cifs_copy_sid(&(*psidid)->sid, sidptr);
259         (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
260         (*psidid)->refcount = 0;
261
262         sprintf((*psidid)->sidstr, "%s", typestr);
263         strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
264         sid_to_str(&(*psidid)->sid, strptr);
265
266         clear_bit(SID_ID_PENDING, &(*psidid)->state);
267         clear_bit(SID_ID_MAPPED, &(*psidid)->state);
268
269         rb_link_node(&(*psidid)->rbnode, parent, linkto);
270         rb_insert_color(&(*psidid)->rbnode, root);
271 }
272
273 static struct cifs_sid_id *
274 id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
275 {
276         int rc;
277         struct rb_node *node = root->rb_node;
278         struct cifs_sid_id *lsidid;
279
280         while (node) {
281                 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
282                 rc = compare_sids(sidptr, &((lsidid)->sid));
283                 if (rc > 0) {
284                         node = node->rb_left;
285                 } else if (rc < 0) {
286                         node = node->rb_right;
287                 } else /* node found */
288                         return lsidid;
289         }
290
291         return NULL;
292 }
293
294 static int
295 sidid_pending_wait(void *unused)
296 {
297         schedule();
298         return signal_pending(current) ? -ERESTARTSYS : 0;
299 }
300
301 static int
302 id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
303 {
304         int rc = 0;
305         struct key *sidkey;
306         const struct cred *saved_cred;
307         struct cifs_sid *lsid;
308         struct cifs_sid_id *psidid, *npsidid;
309         struct rb_root *cidtree;
310         spinlock_t *cidlock;
311
312         if (sidtype == SIDOWNER) {
313                 cidlock = &siduidlock;
314                 cidtree = &uidtree;
315         } else if (sidtype == SIDGROUP) {
316                 cidlock = &sidgidlock;
317                 cidtree = &gidtree;
318         } else
319                 return -EINVAL;
320
321         spin_lock(cidlock);
322         psidid = sid_rb_search(cidtree, cid);
323
324         if (!psidid) { /* node does not exist, allocate one & attempt adding */
325                 spin_unlock(cidlock);
326                 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
327                 if (!npsidid)
328                         return -ENOMEM;
329
330                 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
331                 if (!npsidid->sidstr) {
332                         kfree(npsidid);
333                         return -ENOMEM;
334                 }
335
336                 spin_lock(cidlock);
337                 psidid = sid_rb_search(cidtree, cid);
338                 if (psidid) { /* node happened to get inserted meanwhile */
339                         ++psidid->refcount;
340                         spin_unlock(cidlock);
341                         kfree(npsidid->sidstr);
342                         kfree(npsidid);
343                 } else {
344                         psidid = npsidid;
345                         sid_rb_insert(cidtree, cid, &psidid,
346                                         sidtype == SIDOWNER ? "oi:" : "gi:");
347                         ++psidid->refcount;
348                         spin_unlock(cidlock);
349                 }
350         } else {
351                 ++psidid->refcount;
352                 spin_unlock(cidlock);
353         }
354
355         /*
356          * If we are here, it is safe to access psidid and its fields
357          * since a reference was taken earlier while holding the spinlock.
358          * A reference on the node is put without holding the spinlock
359          * and it is OK to do so in this case, shrinker will not erase
360          * this node until all references are put and we do not access
361          * any fields of the node after a reference is put .
362          */
363         if (test_bit(SID_ID_MAPPED, &psidid->state)) {
364                 cifs_copy_sid(ssid, &psidid->sid);
365                 psidid->time = jiffies; /* update ts for accessing */
366                 goto id_sid_out;
367         }
368
369         if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) {
370                 rc = -EINVAL;
371                 goto id_sid_out;
372         }
373
374         if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
375                 saved_cred = override_creds(root_cred);
376                 sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
377                 if (IS_ERR(sidkey)) {
378                         rc = -EINVAL;
379                         cFYI(1, "%s: Can't map and id to a SID", __func__);
380                 } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
381                         rc = -EIO;
382                         cFYI(1, "%s: Downcall contained malformed key "
383                                 "(datalen=%hu)", __func__, sidkey->datalen);
384                 } else {
385                         lsid = (struct cifs_sid *)sidkey->payload.data;
386                         cifs_copy_sid(&psidid->sid, lsid);
387                         cifs_copy_sid(ssid, &psidid->sid);
388                         set_bit(SID_ID_MAPPED, &psidid->state);
389                         key_put(sidkey);
390                         kfree(psidid->sidstr);
391                 }
392                 psidid->time = jiffies; /* update ts for accessing */
393                 revert_creds(saved_cred);
394                 clear_bit(SID_ID_PENDING, &psidid->state);
395                 wake_up_bit(&psidid->state, SID_ID_PENDING);
396         } else {
397                 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
398                                 sidid_pending_wait, TASK_INTERRUPTIBLE);
399                 if (rc) {
400                         cFYI(1, "%s: sidid_pending_wait interrupted %d",
401                                         __func__, rc);
402                         --psidid->refcount;
403                         return rc;
404                 }
405                 if (test_bit(SID_ID_MAPPED, &psidid->state))
406                         cifs_copy_sid(ssid, &psidid->sid);
407                 else
408                         rc = -EINVAL;
409         }
410 id_sid_out:
411         --psidid->refcount;
412         return rc;
413 }
414
415 static int
416 sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
417                 struct cifs_fattr *fattr, uint sidtype)
418 {
419         int rc;
420         unsigned long cid;
421         struct key *idkey;
422         const struct cred *saved_cred;
423         struct cifs_sid_id *psidid, *npsidid;
424         struct rb_root *cidtree;
425         spinlock_t *cidlock;
426
427         if (sidtype == SIDOWNER) {
428                 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
429                 cidlock = &siduidlock;
430                 cidtree = &uidtree;
431         } else if (sidtype == SIDGROUP) {
432                 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
433                 cidlock = &sidgidlock;
434                 cidtree = &gidtree;
435         } else
436                 return -ENOENT;
437
438         spin_lock(cidlock);
439         psidid = id_rb_search(cidtree, psid);
440
441         if (!psidid) { /* node does not exist, allocate one & attempt adding */
442                 spin_unlock(cidlock);
443                 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
444                 if (!npsidid)
445                         return -ENOMEM;
446
447                 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
448                 if (!npsidid->sidstr) {
449                         kfree(npsidid);
450                         return -ENOMEM;
451                 }
452
453                 spin_lock(cidlock);
454                 psidid = id_rb_search(cidtree, psid);
455                 if (psidid) { /* node happened to get inserted meanwhile */
456                         ++psidid->refcount;
457                         spin_unlock(cidlock);
458                         kfree(npsidid->sidstr);
459                         kfree(npsidid);
460                 } else {
461                         psidid = npsidid;
462                         id_rb_insert(cidtree, psid, &psidid,
463                                         sidtype == SIDOWNER ? "os:" : "gs:");
464                         ++psidid->refcount;
465                         spin_unlock(cidlock);
466                 }
467         } else {
468                 ++psidid->refcount;
469                 spin_unlock(cidlock);
470         }
471
472         /*
473          * If we are here, it is safe to access psidid and its fields
474          * since a reference was taken earlier while holding the spinlock.
475          * A reference on the node is put without holding the spinlock
476          * and it is OK to do so in this case, shrinker will not erase
477          * this node until all references are put and we do not access
478          * any fields of the node after a reference is put .
479          */
480         if (test_bit(SID_ID_MAPPED, &psidid->state)) {
481                 cid = psidid->id;
482                 psidid->time = jiffies; /* update ts for accessing */
483                 goto sid_to_id_out;
484         }
485
486         if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
487                 goto sid_to_id_out;
488
489         if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
490                 saved_cred = override_creds(root_cred);
491                 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
492                 if (IS_ERR(idkey))
493                         cFYI(1, "%s: Can't map SID to an id", __func__);
494                 else {
495                         cid = *(unsigned long *)idkey->payload.value;
496                         psidid->id = cid;
497                         set_bit(SID_ID_MAPPED, &psidid->state);
498                         key_put(idkey);
499                         kfree(psidid->sidstr);
500                 }
501                 revert_creds(saved_cred);
502                 psidid->time = jiffies; /* update ts for accessing */
503                 clear_bit(SID_ID_PENDING, &psidid->state);
504                 wake_up_bit(&psidid->state, SID_ID_PENDING);
505         } else {
506                 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
507                                 sidid_pending_wait, TASK_INTERRUPTIBLE);
508                 if (rc) {
509                         cFYI(1, "%s: sidid_pending_wait interrupted %d",
510                                         __func__, rc);
511                         --psidid->refcount; /* decremented without spinlock */
512                         return rc;
513                 }
514                 if (test_bit(SID_ID_MAPPED, &psidid->state))
515                         cid = psidid->id;
516         }
517
518 sid_to_id_out:
519         --psidid->refcount; /* decremented without spinlock */
520         if (sidtype == SIDOWNER)
521                 fattr->cf_uid = cid;
522         else
523                 fattr->cf_gid = cid;
524
525         return 0;
526 }
527
528 int
529 init_cifs_idmap(void)
530 {
531         struct cred *cred;
532         struct key *keyring;
533         int ret;
534
535         cFYI(1, "Registering the %s key type", cifs_idmap_key_type.name);
536
537         /* create an override credential set with a special thread keyring in
538          * which requests are cached
539          *
540          * this is used to prevent malicious redirections from being installed
541          * with add_key().
542          */
543         cred = prepare_kernel_cred(NULL);
544         if (!cred)
545                 return -ENOMEM;
546
547         keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
548                             (KEY_POS_ALL & ~KEY_POS_SETATTR) |
549                             KEY_USR_VIEW | KEY_USR_READ,
550                             KEY_ALLOC_NOT_IN_QUOTA);
551         if (IS_ERR(keyring)) {
552                 ret = PTR_ERR(keyring);
553                 goto failed_put_cred;
554         }
555
556         ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
557         if (ret < 0)
558                 goto failed_put_key;
559
560         ret = register_key_type(&cifs_idmap_key_type);
561         if (ret < 0)
562                 goto failed_put_key;
563
564         /* instruct request_key() to use this special keyring as a cache for
565          * the results it looks up */
566         set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
567         cred->thread_keyring = keyring;
568         cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
569         root_cred = cred;
570
571         spin_lock_init(&siduidlock);
572         uidtree = RB_ROOT;
573         spin_lock_init(&sidgidlock);
574         gidtree = RB_ROOT;
575
576         spin_lock_init(&uidsidlock);
577         siduidtree = RB_ROOT;
578         spin_lock_init(&gidsidlock);
579         sidgidtree = RB_ROOT;
580         register_shrinker(&cifs_shrinker);
581
582         cFYI(1, "cifs idmap keyring: %d", key_serial(keyring));
583         return 0;
584
585 failed_put_key:
586         key_put(keyring);
587 failed_put_cred:
588         put_cred(cred);
589         return ret;
590 }
591
592 void
593 exit_cifs_idmap(void)
594 {
595         key_revoke(root_cred->thread_keyring);
596         unregister_key_type(&cifs_idmap_key_type);
597         put_cred(root_cred);
598         unregister_shrinker(&cifs_shrinker);
599         cFYI(1, "Unregistered %s key type", cifs_idmap_key_type.name);
600 }
601
602 void
603 cifs_destroy_idmaptrees(void)
604 {
605         struct rb_root *root;
606         struct rb_node *node;
607
608         root = &uidtree;
609         spin_lock(&siduidlock);
610         while ((node = rb_first(root)))
611                 rb_erase(node, root);
612         spin_unlock(&siduidlock);
613
614         root = &gidtree;
615         spin_lock(&sidgidlock);
616         while ((node = rb_first(root)))
617                 rb_erase(node, root);
618         spin_unlock(&sidgidlock);
619
620         root = &siduidtree;
621         spin_lock(&uidsidlock);
622         while ((node = rb_first(root)))
623                 rb_erase(node, root);
624         spin_unlock(&uidsidlock);
625
626         root = &sidgidtree;
627         spin_lock(&gidsidlock);
628         while ((node = rb_first(root)))
629                 rb_erase(node, root);
630         spin_unlock(&gidsidlock);
631 }
632
633 /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
634    the same returns 1, if they do not match returns 0 */
635 int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
636 {
637         int i;
638         int num_subauth, num_sat, num_saw;
639
640         if ((!ctsid) || (!cwsid))
641                 return 1;
642
643         /* compare the revision */
644         if (ctsid->revision != cwsid->revision) {
645                 if (ctsid->revision > cwsid->revision)
646                         return 1;
647                 else
648                         return -1;
649         }
650
651         /* compare all of the six auth values */
652         for (i = 0; i < 6; ++i) {
653                 if (ctsid->authority[i] != cwsid->authority[i]) {
654                         if (ctsid->authority[i] > cwsid->authority[i])
655                                 return 1;
656                         else
657                                 return -1;
658                 }
659         }
660
661         /* compare all of the subauth values if any */
662         num_sat = ctsid->num_subauth;
663         num_saw = cwsid->num_subauth;
664         num_subauth = num_sat < num_saw ? num_sat : num_saw;
665         if (num_subauth) {
666                 for (i = 0; i < num_subauth; ++i) {
667                         if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
668                                 if (le32_to_cpu(ctsid->sub_auth[i]) >
669                                         le32_to_cpu(cwsid->sub_auth[i]))
670                                         return 1;
671                                 else
672                                         return -1;
673                         }
674                 }
675         }
676
677         return 0; /* sids compare/match */
678 }
679
680
681 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
682 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
683                                 struct cifs_ntsd *pnntsd, __u32 sidsoffset)
684 {
685         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
686         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
687
688         /* copy security descriptor control portion */
689         pnntsd->revision = pntsd->revision;
690         pnntsd->type = pntsd->type;
691         pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
692         pnntsd->sacloffset = 0;
693         pnntsd->osidoffset = cpu_to_le32(sidsoffset);
694         pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
695
696         /* copy owner sid */
697         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
698                                 le32_to_cpu(pntsd->osidoffset));
699         nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
700         cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
701
702         /* copy group sid */
703         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
704                                 le32_to_cpu(pntsd->gsidoffset));
705         ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
706                                         sizeof(struct cifs_sid));
707         cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
708
709         return;
710 }
711
712
713 /*
714    change posix mode to reflect permissions
715    pmode is the existing mode (we only want to overwrite part of this
716    bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
717 */
718 static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
719                                  umode_t *pbits_to_set)
720 {
721         __u32 flags = le32_to_cpu(ace_flags);
722         /* the order of ACEs is important.  The canonical order is to begin with
723            DENY entries followed by ALLOW, otherwise an allow entry could be
724            encountered first, making the subsequent deny entry like "dead code"
725            which would be superflous since Windows stops when a match is made
726            for the operation you are trying to perform for your user */
727
728         /* For deny ACEs we change the mask so that subsequent allow access
729            control entries do not turn on the bits we are denying */
730         if (type == ACCESS_DENIED) {
731                 if (flags & GENERIC_ALL)
732                         *pbits_to_set &= ~S_IRWXUGO;
733
734                 if ((flags & GENERIC_WRITE) ||
735                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
736                         *pbits_to_set &= ~S_IWUGO;
737                 if ((flags & GENERIC_READ) ||
738                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
739                         *pbits_to_set &= ~S_IRUGO;
740                 if ((flags & GENERIC_EXECUTE) ||
741                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
742                         *pbits_to_set &= ~S_IXUGO;
743                 return;
744         } else if (type != ACCESS_ALLOWED) {
745                 cERROR(1, "unknown access control type %d", type);
746                 return;
747         }
748         /* else ACCESS_ALLOWED type */
749
750         if (flags & GENERIC_ALL) {
751                 *pmode |= (S_IRWXUGO & (*pbits_to_set));
752                 cFYI(DBG2, "all perms");
753                 return;
754         }
755         if ((flags & GENERIC_WRITE) ||
756                         ((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
757                 *pmode |= (S_IWUGO & (*pbits_to_set));
758         if ((flags & GENERIC_READ) ||
759                         ((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
760                 *pmode |= (S_IRUGO & (*pbits_to_set));
761         if ((flags & GENERIC_EXECUTE) ||
762                         ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
763                 *pmode |= (S_IXUGO & (*pbits_to_set));
764
765         cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode);
766         return;
767 }
768
769 /*
770    Generate access flags to reflect permissions mode is the existing mode.
771    This function is called for every ACE in the DACL whose SID matches
772    with either owner or group or everyone.
773 */
774
775 static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
776                                 __u32 *pace_flags)
777 {
778         /* reset access mask */
779         *pace_flags = 0x0;
780
781         /* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
782         mode &= bits_to_use;
783
784         /* check for R/W/X UGO since we do not know whose flags
785            is this but we have cleared all the bits sans RWX for
786            either user or group or other as per bits_to_use */
787         if (mode & S_IRUGO)
788                 *pace_flags |= SET_FILE_READ_RIGHTS;
789         if (mode & S_IWUGO)
790                 *pace_flags |= SET_FILE_WRITE_RIGHTS;
791         if (mode & S_IXUGO)
792                 *pace_flags |= SET_FILE_EXEC_RIGHTS;
793
794         cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags);
795         return;
796 }
797
798 static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
799                         const struct cifs_sid *psid, __u64 nmode, umode_t bits)
800 {
801         int i;
802         __u16 size = 0;
803         __u32 access_req = 0;
804
805         pntace->type = ACCESS_ALLOWED;
806         pntace->flags = 0x0;
807         mode_to_access_flags(nmode, bits, &access_req);
808         if (!access_req)
809                 access_req = SET_MINIMUM_RIGHTS;
810         pntace->access_req = cpu_to_le32(access_req);
811
812         pntace->sid.revision = psid->revision;
813         pntace->sid.num_subauth = psid->num_subauth;
814         for (i = 0; i < 6; i++)
815                 pntace->sid.authority[i] = psid->authority[i];
816         for (i = 0; i < psid->num_subauth; i++)
817                 pntace->sid.sub_auth[i] = psid->sub_auth[i];
818
819         size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
820         pntace->size = cpu_to_le16(size);
821
822         return size;
823 }
824
825
826 #ifdef CONFIG_CIFS_DEBUG2
827 static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
828 {
829         int num_subauth;
830
831         /* validate that we do not go past end of acl */
832
833         if (le16_to_cpu(pace->size) < 16) {
834                 cERROR(1, "ACE too small %d", le16_to_cpu(pace->size));
835                 return;
836         }
837
838         if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
839                 cERROR(1, "ACL too small to parse ACE");
840                 return;
841         }
842
843         num_subauth = pace->sid.num_subauth;
844         if (num_subauth) {
845                 int i;
846                 cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d",
847                         pace->sid.revision, pace->sid.num_subauth, pace->type,
848                         pace->flags, le16_to_cpu(pace->size));
849                 for (i = 0; i < num_subauth; ++i) {
850                         cFYI(1, "ACE sub_auth[%d]: 0x%x", i,
851                                 le32_to_cpu(pace->sid.sub_auth[i]));
852                 }
853
854                 /* BB add length check to make sure that we do not have huge
855                         num auths and therefore go off the end */
856         }
857
858         return;
859 }
860 #endif
861
862
863 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
864                        struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
865                        struct cifs_fattr *fattr)
866 {
867         int i;
868         int num_aces = 0;
869         int acl_size;
870         char *acl_base;
871         struct cifs_ace **ppace;
872
873         /* BB need to add parm so we can store the SID BB */
874
875         if (!pdacl) {
876                 /* no DACL in the security descriptor, set
877                    all the permissions for user/group/other */
878                 fattr->cf_mode |= S_IRWXUGO;
879                 return;
880         }
881
882         /* validate that we do not go past end of acl */
883         if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
884                 cERROR(1, "ACL too small to parse DACL");
885                 return;
886         }
887
888         cFYI(DBG2, "DACL revision %d size %d num aces %d",
889                 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
890                 le32_to_cpu(pdacl->num_aces));
891
892         /* reset rwx permissions for user/group/other.
893            Also, if num_aces is 0 i.e. DACL has no ACEs,
894            user/group/other have no permissions */
895         fattr->cf_mode &= ~(S_IRWXUGO);
896
897         acl_base = (char *)pdacl;
898         acl_size = sizeof(struct cifs_acl);
899
900         num_aces = le32_to_cpu(pdacl->num_aces);
901         if (num_aces > 0) {
902                 umode_t user_mask = S_IRWXU;
903                 umode_t group_mask = S_IRWXG;
904                 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
905
906                 if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
907                         return;
908                 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
909                                 GFP_KERNEL);
910                 if (!ppace) {
911                         cERROR(1, "DACL memory allocation error");
912                         return;
913                 }
914
915                 for (i = 0; i < num_aces; ++i) {
916                         ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
917 #ifdef CONFIG_CIFS_DEBUG2
918                         dump_ace(ppace[i], end_of_acl);
919 #endif
920                         if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
921                                 access_flags_to_mode(ppace[i]->access_req,
922                                                      ppace[i]->type,
923                                                      &fattr->cf_mode,
924                                                      &user_mask);
925                         if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
926                                 access_flags_to_mode(ppace[i]->access_req,
927                                                      ppace[i]->type,
928                                                      &fattr->cf_mode,
929                                                      &group_mask);
930                         if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
931                                 access_flags_to_mode(ppace[i]->access_req,
932                                                      ppace[i]->type,
933                                                      &fattr->cf_mode,
934                                                      &other_mask);
935                         if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
936                                 access_flags_to_mode(ppace[i]->access_req,
937                                                      ppace[i]->type,
938                                                      &fattr->cf_mode,
939                                                      &other_mask);
940
941
942 /*                      memcpy((void *)(&(cifscred->aces[i])),
943                                 (void *)ppace[i],
944                                 sizeof(struct cifs_ace)); */
945
946                         acl_base = (char *)ppace[i];
947                         acl_size = le16_to_cpu(ppace[i]->size);
948                 }
949
950                 kfree(ppace);
951         }
952
953         return;
954 }
955
956
957 static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
958                         struct cifs_sid *pgrpsid, __u64 nmode)
959 {
960         u16 size = 0;
961         struct cifs_acl *pnndacl;
962
963         pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
964
965         size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
966                                         pownersid, nmode, S_IRWXU);
967         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
968                                         pgrpsid, nmode, S_IRWXG);
969         size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
970                                          &sid_everyone, nmode, S_IRWXO);
971
972         pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
973         pndacl->num_aces = cpu_to_le32(3);
974
975         return 0;
976 }
977
978
979 static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
980 {
981         /* BB need to add parm so we can store the SID BB */
982
983         /* validate that we do not go past end of ACL - sid must be at least 8
984            bytes long (assuming no sub-auths - e.g. the null SID */
985         if (end_of_acl < (char *)psid + 8) {
986                 cERROR(1, "ACL too small to parse SID %p", psid);
987                 return -EINVAL;
988         }
989
990         if (psid->num_subauth) {
991 #ifdef CONFIG_CIFS_DEBUG2
992                 int i;
993                 cFYI(1, "SID revision %d num_auth %d",
994                         psid->revision, psid->num_subauth);
995
996                 for (i = 0; i < psid->num_subauth; i++) {
997                         cFYI(1, "SID sub_auth[%d]: 0x%x ", i,
998                                 le32_to_cpu(psid->sub_auth[i]));
999                 }
1000
1001                 /* BB add length check to make sure that we do not have huge
1002                         num auths and therefore go off the end */
1003                 cFYI(1, "RID 0x%x",
1004                         le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
1005 #endif
1006         }
1007
1008         return 0;
1009 }
1010
1011
1012 /* Convert CIFS ACL to POSIX form */
1013 static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
1014                 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
1015 {
1016         int rc = 0;
1017         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1018         struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
1019         char *end_of_acl = ((char *)pntsd) + acl_len;
1020         __u32 dacloffset;
1021
1022         if (pntsd == NULL)
1023                 return -EIO;
1024
1025         owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1026                                 le32_to_cpu(pntsd->osidoffset));
1027         group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1028                                 le32_to_cpu(pntsd->gsidoffset));
1029         dacloffset = le32_to_cpu(pntsd->dacloffset);
1030         dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1031         cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x "
1032                  "sacloffset 0x%x dacloffset 0x%x",
1033                  pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
1034                  le32_to_cpu(pntsd->gsidoffset),
1035                  le32_to_cpu(pntsd->sacloffset), dacloffset);
1036 /*      cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
1037         rc = parse_sid(owner_sid_ptr, end_of_acl);
1038         if (rc) {
1039                 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
1040                 return rc;
1041         }
1042         rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
1043         if (rc) {
1044                 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
1045                 return rc;
1046         }
1047
1048         rc = parse_sid(group_sid_ptr, end_of_acl);
1049         if (rc) {
1050                 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
1051                 return rc;
1052         }
1053         rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
1054         if (rc) {
1055                 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
1056                 return rc;
1057         }
1058
1059         if (dacloffset)
1060                 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
1061                            group_sid_ptr, fattr);
1062         else
1063                 cFYI(1, "no ACL"); /* BB grant all or default perms? */
1064
1065         return rc;
1066 }
1067
1068 /* Convert permission bits from mode to equivalent CIFS ACL */
1069 static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
1070         __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag)
1071 {
1072         int rc = 0;
1073         __u32 dacloffset;
1074         __u32 ndacloffset;
1075         __u32 sidsoffset;
1076         struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
1077         struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
1078         struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
1079         struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
1080
1081         if (nmode != NO_CHANGE_64) { /* chmod */
1082                 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1083                                 le32_to_cpu(pntsd->osidoffset));
1084                 group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
1085                                 le32_to_cpu(pntsd->gsidoffset));
1086                 dacloffset = le32_to_cpu(pntsd->dacloffset);
1087                 dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
1088                 ndacloffset = sizeof(struct cifs_ntsd);
1089                 ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
1090                 ndacl_ptr->revision = dacl_ptr->revision;
1091                 ndacl_ptr->size = 0;
1092                 ndacl_ptr->num_aces = 0;
1093
1094                 rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
1095                                         nmode);
1096                 sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
1097                 /* copy sec desc control portion & owner and group sids */
1098                 copy_sec_desc(pntsd, pnntsd, sidsoffset);
1099                 *aclflag = CIFS_ACL_DACL;
1100         } else {
1101                 memcpy(pnntsd, pntsd, secdesclen);
1102                 if (uid != NO_CHANGE_32) { /* chown */
1103                         owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1104                                         le32_to_cpu(pnntsd->osidoffset));
1105                         nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1106                                                                 GFP_KERNEL);
1107                         if (!nowner_sid_ptr)
1108                                 return -ENOMEM;
1109                         rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr);
1110                         if (rc) {
1111                                 cFYI(1, "%s: Mapping error %d for owner id %d",
1112                                                 __func__, rc, uid);
1113                                 kfree(nowner_sid_ptr);
1114                                 return rc;
1115                         }
1116                         cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
1117                         kfree(nowner_sid_ptr);
1118                         *aclflag = CIFS_ACL_OWNER;
1119                 }
1120                 if (gid != NO_CHANGE_32) { /* chgrp */
1121                         group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
1122                                         le32_to_cpu(pnntsd->gsidoffset));
1123                         ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
1124                                                                 GFP_KERNEL);
1125                         if (!ngroup_sid_ptr)
1126                                 return -ENOMEM;
1127                         rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr);
1128                         if (rc) {
1129                                 cFYI(1, "%s: Mapping error %d for group id %d",
1130                                                 __func__, rc, gid);
1131                                 kfree(ngroup_sid_ptr);
1132                                 return rc;
1133                         }
1134                         cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
1135                         kfree(ngroup_sid_ptr);
1136                         *aclflag = CIFS_ACL_GROUP;
1137                 }
1138         }
1139
1140         return rc;
1141 }
1142
1143 static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
1144                 __u16 fid, u32 *pacllen)
1145 {
1146         struct cifs_ntsd *pntsd = NULL;
1147         unsigned int xid;
1148         int rc;
1149         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1150
1151         if (IS_ERR(tlink))
1152                 return ERR_CAST(tlink);
1153
1154         xid = get_xid();
1155         rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
1156         free_xid(xid);
1157
1158         cifs_put_tlink(tlink);
1159
1160         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1161         if (rc)
1162                 return ERR_PTR(rc);
1163         return pntsd;
1164 }
1165
1166 static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1167                 const char *path, u32 *pacllen)
1168 {
1169         struct cifs_ntsd *pntsd = NULL;
1170         int oplock = 0;
1171         unsigned int xid;
1172         int rc, create_options = 0;
1173         __u16 fid;
1174         struct cifs_tcon *tcon;
1175         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1176
1177         if (IS_ERR(tlink))
1178                 return ERR_CAST(tlink);
1179
1180         tcon = tlink_tcon(tlink);
1181         xid = get_xid();
1182
1183         if (backup_cred(cifs_sb))
1184                 create_options |= CREATE_OPEN_BACKUP_INTENT;
1185
1186         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
1187                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1188                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1189         if (!rc) {
1190                 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
1191                 CIFSSMBClose(xid, tcon, fid);
1192         }
1193
1194         cifs_put_tlink(tlink);
1195         free_xid(xid);
1196
1197         cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
1198         if (rc)
1199                 return ERR_PTR(rc);
1200         return pntsd;
1201 }
1202
1203 /* Retrieve an ACL from the server */
1204 struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1205                                       struct inode *inode, const char *path,
1206                                       u32 *pacllen)
1207 {
1208         struct cifs_ntsd *pntsd = NULL;
1209         struct cifsFileInfo *open_file = NULL;
1210
1211         if (inode)
1212                 open_file = find_readable_file(CIFS_I(inode), true);
1213         if (!open_file)
1214                 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1215
1216         pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->fid.netfid, pacllen);
1217         cifsFileInfo_put(open_file);
1218         return pntsd;
1219 }
1220
1221  /* Set an ACL on the server */
1222 int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1223                         struct inode *inode, const char *path, int aclflag)
1224 {
1225         int oplock = 0;
1226         unsigned int xid;
1227         int rc, access_flags, create_options = 0;
1228         __u16 fid;
1229         struct cifs_tcon *tcon;
1230         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1231         struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1232
1233         if (IS_ERR(tlink))
1234                 return PTR_ERR(tlink);
1235
1236         tcon = tlink_tcon(tlink);
1237         xid = get_xid();
1238
1239         if (backup_cred(cifs_sb))
1240                 create_options |= CREATE_OPEN_BACKUP_INTENT;
1241
1242         if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1243                 access_flags = WRITE_OWNER;
1244         else
1245                 access_flags = WRITE_DAC;
1246
1247         rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags,
1248                         create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
1249                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1250         if (rc) {
1251                 cERROR(1, "Unable to open file to set ACL");
1252                 goto out;
1253         }
1254
1255         rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag);
1256         cFYI(DBG2, "SetCIFSACL rc = %d", rc);
1257
1258         CIFSSMBClose(xid, tcon, fid);
1259 out:
1260         free_xid(xid);
1261         cifs_put_tlink(tlink);
1262         return rc;
1263 }
1264
1265 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1266 int
1267 cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1268                   struct inode *inode, const char *path, const __u16 *pfid)
1269 {
1270         struct cifs_ntsd *pntsd = NULL;
1271         u32 acllen = 0;
1272         int rc = 0;
1273
1274         cFYI(DBG2, "converting ACL to mode for %s", path);
1275
1276         if (pfid)
1277                 pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen);
1278         else
1279                 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
1280
1281         /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1282         if (IS_ERR(pntsd)) {
1283                 rc = PTR_ERR(pntsd);
1284                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1285         } else {
1286                 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1287                 kfree(pntsd);
1288                 if (rc)
1289                         cERROR(1, "parse sec desc failed rc = %d", rc);
1290         }
1291
1292         return rc;
1293 }
1294
1295 /* Convert mode bits to an ACL so we can update the ACL on the server */
1296 int
1297 id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1298                         uid_t uid, gid_t gid)
1299 {
1300         int rc = 0;
1301         int aclflag = CIFS_ACL_DACL; /* default flag to set */
1302         __u32 secdesclen = 0;
1303         struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1304         struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1305
1306         cFYI(DBG2, "set ACL from mode for %s", path);
1307
1308         /* Get the security descriptor */
1309         pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
1310
1311         /* Add three ACEs for owner, group, everyone getting rid of
1312            other ACEs as chmod disables ACEs and set the security descriptor */
1313
1314         if (IS_ERR(pntsd)) {
1315                 rc = PTR_ERR(pntsd);
1316                 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1317         } else {
1318                 /* allocate memory for the smb header,
1319                    set security descriptor request security descriptor
1320                    parameters, and secuirty descriptor itself */
1321
1322                 secdesclen = secdesclen < DEFSECDESCLEN ?
1323                                         DEFSECDESCLEN : secdesclen;
1324                 pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1325                 if (!pnntsd) {
1326                         cERROR(1, "Unable to allocate security descriptor");
1327                         kfree(pntsd);
1328                         return -ENOMEM;
1329                 }
1330
1331                 rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1332                                         &aclflag);
1333
1334                 cFYI(DBG2, "build_sec_desc rc: %d", rc);
1335
1336                 if (!rc) {
1337                         /* Set the security descriptor */
1338                         rc = set_cifs_acl(pnntsd, secdesclen, inode,
1339                                                 path, aclflag);
1340                         cFYI(DBG2, "set_cifs_acl rc: %d", rc);
1341                 }
1342
1343                 kfree(pnntsd);
1344                 kfree(pntsd);
1345         }
1346
1347         return rc;
1348 }