aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifsacl.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/cifs/cifsacl.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/cifs/cifsacl.c')
-rw-r--r--fs/cifs/cifsacl.c589
1 files changed, 493 insertions, 96 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 85d7cf7ff2c8..21de1d6d5849 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -23,76 +23,405 @@
23 23
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/slab.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>
26#include "cifspdu.h" 30#include "cifspdu.h"
27#include "cifsglob.h" 31#include "cifsglob.h"
28#include "cifsacl.h" 32#include "cifsacl.h"
29#include "cifsproto.h" 33#include "cifsproto.h"
30#include "cifs_debug.h" 34#include "cifs_debug.h"
31 35
32 36/* security id for everyone/world system group */
33#ifdef CONFIG_CIFS_EXPERIMENTAL
34
35static struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
36 {{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
37 {{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
38 {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11), 0, 0, 0, 0} }, "net-users"},
39 {{1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(18), 0, 0, 0, 0} }, "sys"},
40 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(544), 0, 0, 0} }, "root"},
41 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(545), 0, 0, 0} }, "users"},
42 {{1, 2, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(32), __constant_cpu_to_le32(546), 0, 0, 0} }, "guest"} }
43;
44
45
46/* security id for everyone */
47static const struct cifs_sid sid_everyone = { 37static const struct cifs_sid sid_everyone = {
48 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; 38 1, 1, {0, 0, 0, 0, 0, 1}, {0} };
39/* security id for Authenticated Users system group */
40static const struct cifs_sid sid_authusers = {
41 1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
49/* group users */ 42/* group users */
50static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; 43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
51 44
45const struct cred *root_cred;
52 46
53int match_sid(struct cifs_sid *ctsid) 47static void
48shrink_idmap_tree(struct rb_root *root, int nr_to_scan, int *nr_rem,
49 int *nr_del)
54{ 50{
55 int i, j; 51 struct rb_node *node;
56 int num_subauth, num_sat, num_saw; 52 struct rb_node *tmp;
57 struct cifs_sid *cwsid; 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}
58 72
59 if (!ctsid) 73/*
60 return -1; 74 * Run idmap cache shrinker.
75 */
76static int
77cifs_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 return nr_rem;
95}
96
97static struct shrinker cifs_shrinker = {
98 .shrink = cifs_idmap_shrinker,
99 .seeks = DEFAULT_SEEKS,
100};
61 101
62 for (i = 0; i < NUM_WK_SIDS; ++i) { 102static int
63 cwsid = &(wksidarr[i].cifssid); 103cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen)
104{
105 char *payload;
106
107 payload = kmalloc(datalen, GFP_KERNEL);
108 if (!payload)
109 return -ENOMEM;
64 110
65 /* compare the revision */ 111 memcpy(payload, data, datalen);
66 if (ctsid->revision != cwsid->revision) 112 key->payload.data = payload;
67 continue; 113 return 0;
114}
68 115
69 /* compare all of the six auth values */ 116static inline void
70 for (j = 0; j < 6; ++j) { 117cifs_idmap_key_destroy(struct key *key)
71 if (ctsid->authority[j] != cwsid->authority[j]) 118{
72 break; 119 kfree(key->payload.data);
120}
121
122struct key_type cifs_idmap_key_type = {
123 .name = "cifs.idmap",
124 .instantiate = cifs_idmap_key_instantiate,
125 .destroy = cifs_idmap_key_destroy,
126 .describe = user_describe,
127 .match = user_match,
128};
129
130static void
131sid_to_str(struct cifs_sid *sidptr, char *sidstr)
132{
133 int i;
134 unsigned long saval;
135 char *strptr;
136
137 strptr = sidstr;
138
139 sprintf(strptr, "%s", "S");
140 strptr = sidstr + strlen(sidstr);
141
142 sprintf(strptr, "-%d", sidptr->revision);
143 strptr = sidstr + strlen(sidstr);
144
145 for (i = 0; i < 6; ++i) {
146 if (sidptr->authority[i]) {
147 sprintf(strptr, "-%d", sidptr->authority[i]);
148 strptr = sidstr + strlen(sidstr);
73 } 149 }
74 if (j < 6) 150 }
75 continue; /* all of the auth values did not match */ 151
76 152 for (i = 0; i < sidptr->num_subauth; ++i) {
77 /* compare all of the subauth values if any */ 153 saval = le32_to_cpu(sidptr->sub_auth[i]);
78 num_sat = ctsid->num_subauth; 154 sprintf(strptr, "-%ld", saval);
79 num_saw = cwsid->num_subauth; 155 strptr = sidstr + strlen(sidstr);
80 num_subauth = num_sat < num_saw ? num_sat : num_saw; 156 }
81 if (num_subauth) { 157}
82 for (j = 0; j < num_subauth; ++j) { 158
83 if (ctsid->sub_auth[j] != cwsid->sub_auth[j]) 159static void
84 break; 160id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
85 } 161 struct cifs_sid_id **psidid, char *typestr)
86 if (j < num_subauth) 162{
87 continue; /* all sub_auth values do not match */ 163 int rc;
164 char *strptr;
165 struct rb_node *node = root->rb_node;
166 struct rb_node *parent = NULL;
167 struct rb_node **linkto = &(root->rb_node);
168 struct cifs_sid_id *lsidid;
169
170 while (node) {
171 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
172 parent = node;
173 rc = compare_sids(sidptr, &((lsidid)->sid));
174 if (rc > 0) {
175 linkto = &(node->rb_left);
176 node = node->rb_left;
177 } else if (rc < 0) {
178 linkto = &(node->rb_right);
179 node = node->rb_right;
88 } 180 }
181 }
182
183 memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
184 (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
185 (*psidid)->refcount = 0;
186
187 sprintf((*psidid)->sidstr, "%s", typestr);
188 strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr);
189 sid_to_str(&(*psidid)->sid, strptr);
190
191 clear_bit(SID_ID_PENDING, &(*psidid)->state);
192 clear_bit(SID_ID_MAPPED, &(*psidid)->state);
193
194 rb_link_node(&(*psidid)->rbnode, parent, linkto);
195 rb_insert_color(&(*psidid)->rbnode, root);
196}
89 197
90 cFYI(1, "matching sid: %s\n", wksidarr[i].sidname); 198static struct cifs_sid_id *
91 return 0; /* sids compare/match */ 199id_rb_search(struct rb_root *root, struct cifs_sid *sidptr)
200{
201 int rc;
202 struct rb_node *node = root->rb_node;
203 struct cifs_sid_id *lsidid;
204
205 while (node) {
206 lsidid = rb_entry(node, struct cifs_sid_id, rbnode);
207 rc = compare_sids(sidptr, &((lsidid)->sid));
208 if (rc > 0) {
209 node = node->rb_left;
210 } else if (rc < 0) {
211 node = node->rb_right;
212 } else /* node found */
213 return lsidid;
92 } 214 }
93 215
94 cFYI(1, "No matching sid"); 216 return NULL;
95 return -1; 217}
218
219static int
220sidid_pending_wait(void *unused)
221{
222 schedule();
223 return signal_pending(current) ? -ERESTARTSYS : 0;
224}
225
226static int
227sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
228 struct cifs_fattr *fattr, uint sidtype)
229{
230 int rc;
231 unsigned long cid;
232 struct key *idkey;
233 const struct cred *saved_cred;
234 struct cifs_sid_id *psidid, *npsidid;
235 struct rb_root *cidtree;
236 spinlock_t *cidlock;
237
238 if (sidtype == SIDOWNER) {
239 cid = cifs_sb->mnt_uid; /* default uid, in case upcall fails */
240 cidlock = &siduidlock;
241 cidtree = &uidtree;
242 } else if (sidtype == SIDGROUP) {
243 cid = cifs_sb->mnt_gid; /* default gid, in case upcall fails */
244 cidlock = &sidgidlock;
245 cidtree = &gidtree;
246 } else
247 return -ENOENT;
248
249 spin_lock(cidlock);
250 psidid = id_rb_search(cidtree, psid);
251
252 if (!psidid) { /* node does not exist, allocate one & attempt adding */
253 spin_unlock(cidlock);
254 npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL);
255 if (!npsidid)
256 return -ENOMEM;
257
258 npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
259 if (!npsidid->sidstr) {
260 kfree(npsidid);
261 return -ENOMEM;
262 }
263
264 spin_lock(cidlock);
265 psidid = id_rb_search(cidtree, psid);
266 if (psidid) { /* node happened to get inserted meanwhile */
267 ++psidid->refcount;
268 spin_unlock(cidlock);
269 kfree(npsidid->sidstr);
270 kfree(npsidid);
271 } else {
272 psidid = npsidid;
273 id_rb_insert(cidtree, psid, &psidid,
274 sidtype == SIDOWNER ? "os:" : "gs:");
275 ++psidid->refcount;
276 spin_unlock(cidlock);
277 }
278 } else {
279 ++psidid->refcount;
280 spin_unlock(cidlock);
281 }
282
283 /*
284 * If we are here, it is safe to access psidid and its fields
285 * since a reference was taken earlier while holding the spinlock.
286 * A reference on the node is put without holding the spinlock
287 * and it is OK to do so in this case, shrinker will not erase
288 * this node until all references are put and we do not access
289 * any fields of the node after a reference is put .
290 */
291 if (test_bit(SID_ID_MAPPED, &psidid->state)) {
292 cid = psidid->id;
293 psidid->time = jiffies; /* update ts for accessing */
294 goto sid_to_id_out;
295 }
296
297 if (time_after(psidid->time + SID_MAP_RETRY, jiffies))
298 goto sid_to_id_out;
299
300 if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) {
301 saved_cred = override_creds(root_cred);
302 idkey = request_key(&cifs_idmap_key_type, psidid->sidstr, "");
303 if (IS_ERR(idkey))
304 cFYI(1, "%s: Can't map SID to an id", __func__);
305 else {
306 cid = *(unsigned long *)idkey->payload.value;
307 psidid->id = cid;
308 set_bit(SID_ID_MAPPED, &psidid->state);
309 key_put(idkey);
310 kfree(psidid->sidstr);
311 }
312 revert_creds(saved_cred);
313 psidid->time = jiffies; /* update ts for accessing */
314 clear_bit(SID_ID_PENDING, &psidid->state);
315 wake_up_bit(&psidid->state, SID_ID_PENDING);
316 } else {
317 rc = wait_on_bit(&psidid->state, SID_ID_PENDING,
318 sidid_pending_wait, TASK_INTERRUPTIBLE);
319 if (rc) {
320 cFYI(1, "%s: sidid_pending_wait interrupted %d",
321 __func__, rc);
322 --psidid->refcount; /* decremented without spinlock */
323 return rc;
324 }
325 if (test_bit(SID_ID_MAPPED, &psidid->state))
326 cid = psidid->id;
327 }
328
329sid_to_id_out:
330 --psidid->refcount; /* decremented without spinlock */
331 if (sidtype == SIDOWNER)
332 fattr->cf_uid = cid;
333 else
334 fattr->cf_gid = cid;
335
336 return 0;
337}
338
339int
340init_cifs_idmap(void)
341{
342 struct cred *cred;
343 struct key *keyring;
344 int ret;
345
346 cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name);
347
348 /* create an override credential set with a special thread keyring in
349 * which requests are cached
350 *
351 * this is used to prevent malicious redirections from being installed
352 * with add_key().
353 */
354 cred = prepare_kernel_cred(NULL);
355 if (!cred)
356 return -ENOMEM;
357
358 keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred,
359 (KEY_POS_ALL & ~KEY_POS_SETATTR) |
360 KEY_USR_VIEW | KEY_USR_READ,
361 KEY_ALLOC_NOT_IN_QUOTA);
362 if (IS_ERR(keyring)) {
363 ret = PTR_ERR(keyring);
364 goto failed_put_cred;
365 }
366
367 ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
368 if (ret < 0)
369 goto failed_put_key;
370
371 ret = register_key_type(&cifs_idmap_key_type);
372 if (ret < 0)
373 goto failed_put_key;
374
375 /* instruct request_key() to use this special keyring as a cache for
376 * the results it looks up */
377 cred->thread_keyring = keyring;
378 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
379 root_cred = cred;
380
381 spin_lock_init(&siduidlock);
382 uidtree = RB_ROOT;
383 spin_lock_init(&sidgidlock);
384 gidtree = RB_ROOT;
385
386 register_shrinker(&cifs_shrinker);
387
388 cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring));
389 return 0;
390
391failed_put_key:
392 key_put(keyring);
393failed_put_cred:
394 put_cred(cred);
395 return ret;
396}
397
398void
399exit_cifs_idmap(void)
400{
401 key_revoke(root_cred->thread_keyring);
402 unregister_key_type(&cifs_idmap_key_type);
403 put_cred(root_cred);
404 unregister_shrinker(&cifs_shrinker);
405 cFYI(1, "Unregistered %s key type\n", cifs_idmap_key_type.name);
406}
407
408void
409cifs_destroy_idmaptrees(void)
410{
411 struct rb_root *root;
412 struct rb_node *node;
413
414 root = &uidtree;
415 spin_lock(&siduidlock);
416 while ((node = rb_first(root)))
417 rb_erase(node, root);
418 spin_unlock(&siduidlock);
419
420 root = &gidtree;
421 spin_lock(&sidgidlock);
422 while ((node = rb_first(root)))
423 rb_erase(node, root);
424 spin_unlock(&sidgidlock);
96} 425}
97 426
98/* if the two SIDs (roughly equivalent to a UUID for a user or group) are 427/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
@@ -103,16 +432,24 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
103 int num_subauth, num_sat, num_saw; 432 int num_subauth, num_sat, num_saw;
104 433
105 if ((!ctsid) || (!cwsid)) 434 if ((!ctsid) || (!cwsid))
106 return 0; 435 return 1;
107 436
108 /* compare the revision */ 437 /* compare the revision */
109 if (ctsid->revision != cwsid->revision) 438 if (ctsid->revision != cwsid->revision) {
110 return 0; 439 if (ctsid->revision > cwsid->revision)
440 return 1;
441 else
442 return -1;
443 }
111 444
112 /* compare all of the six auth values */ 445 /* compare all of the six auth values */
113 for (i = 0; i < 6; ++i) { 446 for (i = 0; i < 6; ++i) {
114 if (ctsid->authority[i] != cwsid->authority[i]) 447 if (ctsid->authority[i] != cwsid->authority[i]) {
115 return 0; 448 if (ctsid->authority[i] > cwsid->authority[i])
449 return 1;
450 else
451 return -1;
452 }
116 } 453 }
117 454
118 /* compare all of the subauth values if any */ 455 /* compare all of the subauth values if any */
@@ -121,12 +458,17 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
121 num_subauth = num_sat < num_saw ? num_sat : num_saw; 458 num_subauth = num_sat < num_saw ? num_sat : num_saw;
122 if (num_subauth) { 459 if (num_subauth) {
123 for (i = 0; i < num_subauth; ++i) { 460 for (i = 0; i < num_subauth; ++i) {
124 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) 461 if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
125 return 0; 462 if (le32_to_cpu(ctsid->sub_auth[i]) >
463 le32_to_cpu(cwsid->sub_auth[i]))
464 return 1;
465 else
466 return -1;
467 }
126 } 468 }
127 } 469 }
128 470
129 return 1; /* sids compare/match */ 471 return 0; /* sids compare/match */
130} 472}
131 473
132 474
@@ -367,32 +709,42 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
367 if (num_aces > 0) { 709 if (num_aces > 0) {
368 umode_t user_mask = S_IRWXU; 710 umode_t user_mask = S_IRWXU;
369 umode_t group_mask = S_IRWXG; 711 umode_t group_mask = S_IRWXG;
370 umode_t other_mask = S_IRWXO; 712 umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
371 713
372 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), 714 ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
373 GFP_KERNEL); 715 GFP_KERNEL);
716 if (!ppace) {
717 cERROR(1, "DACL memory allocation error");
718 return;
719 }
374 720
375 for (i = 0; i < num_aces; ++i) { 721 for (i = 0; i < num_aces; ++i) {
376 ppace[i] = (struct cifs_ace *) (acl_base + acl_size); 722 ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
377#ifdef CONFIG_CIFS_DEBUG2 723#ifdef CONFIG_CIFS_DEBUG2
378 dump_ace(ppace[i], end_of_acl); 724 dump_ace(ppace[i], end_of_acl);
379#endif 725#endif
380 if (compare_sids(&(ppace[i]->sid), pownersid)) 726 if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
381 access_flags_to_mode(ppace[i]->access_req, 727 access_flags_to_mode(ppace[i]->access_req,
382 ppace[i]->type, 728 ppace[i]->type,
383 &fattr->cf_mode, 729 &fattr->cf_mode,
384 &user_mask); 730 &user_mask);
385 if (compare_sids(&(ppace[i]->sid), pgrpsid)) 731 if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
386 access_flags_to_mode(ppace[i]->access_req, 732 access_flags_to_mode(ppace[i]->access_req,
387 ppace[i]->type, 733 ppace[i]->type,
388 &fattr->cf_mode, 734 &fattr->cf_mode,
389 &group_mask); 735 &group_mask);
390 if (compare_sids(&(ppace[i]->sid), &sid_everyone)) 736 if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
737 access_flags_to_mode(ppace[i]->access_req,
738 ppace[i]->type,
739 &fattr->cf_mode,
740 &other_mask);
741 if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
391 access_flags_to_mode(ppace[i]->access_req, 742 access_flags_to_mode(ppace[i]->access_req,
392 ppace[i]->type, 743 ppace[i]->type,
393 &fattr->cf_mode, 744 &fattr->cf_mode,
394 &other_mask); 745 &other_mask);
395 746
747
396/* memcpy((void *)(&(cifscred->aces[i])), 748/* memcpy((void *)(&(cifscred->aces[i])),
397 (void *)ppace[i], 749 (void *)ppace[i],
398 sizeof(struct cifs_ace)); */ 750 sizeof(struct cifs_ace)); */
@@ -464,10 +816,10 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
464 816
465 817
466/* Convert CIFS ACL to POSIX form */ 818/* Convert CIFS ACL to POSIX form */
467static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, 819static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
468 struct cifs_fattr *fattr) 820 struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
469{ 821{
470 int rc; 822 int rc = 0;
471 struct cifs_sid *owner_sid_ptr, *group_sid_ptr; 823 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
472 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */ 824 struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
473 char *end_of_acl = ((char *)pntsd) + acl_len; 825 char *end_of_acl = ((char *)pntsd) + acl_len;
@@ -489,12 +841,26 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
489 le32_to_cpu(pntsd->sacloffset), dacloffset); 841 le32_to_cpu(pntsd->sacloffset), dacloffset);
490/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ 842/* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
491 rc = parse_sid(owner_sid_ptr, end_of_acl); 843 rc = parse_sid(owner_sid_ptr, end_of_acl);
492 if (rc) 844 if (rc) {
845 cFYI(1, "%s: Error %d parsing Owner SID", __func__, rc);
493 return rc; 846 return rc;
847 }
848 rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
849 if (rc) {
850 cFYI(1, "%s: Error %d mapping Owner SID to uid", __func__, rc);
851 return rc;
852 }
494 853
495 rc = parse_sid(group_sid_ptr, end_of_acl); 854 rc = parse_sid(group_sid_ptr, end_of_acl);
496 if (rc) 855 if (rc) {
856 cFYI(1, "%s: Error %d mapping Owner SID to gid", __func__, rc);
857 return rc;
858 }
859 rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
860 if (rc) {
861 cFYI(1, "%s: Error %d mapping Group SID to gid", __func__, rc);
497 return rc; 862 return rc;
863 }
498 864
499 if (dacloffset) 865 if (dacloffset)
500 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, 866 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
@@ -509,7 +875,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
509 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, 875 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
510 sizeof(struct cifs_sid)); */ 876 sizeof(struct cifs_sid)); */
511 877
512 return 0; 878 return rc;
513} 879}
514 880
515 881
@@ -557,13 +923,20 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
557{ 923{
558 struct cifs_ntsd *pntsd = NULL; 924 struct cifs_ntsd *pntsd = NULL;
559 int xid, rc; 925 int xid, rc;
926 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
927
928 if (IS_ERR(tlink))
929 return ERR_CAST(tlink);
560 930
561 xid = GetXid(); 931 xid = GetXid();
562 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 932 rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen);
563 FreeXid(xid); 933 FreeXid(xid);
564 934
935 cifs_put_tlink(tlink);
565 936
566 cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); 937 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
938 if (rc)
939 return ERR_PTR(rc);
567 return pntsd; 940 return pntsd;
568} 941}
569 942
@@ -574,28 +947,34 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
574 int oplock = 0; 947 int oplock = 0;
575 int xid, rc; 948 int xid, rc;
576 __u16 fid; 949 __u16 fid;
950 struct cifs_tcon *tcon;
951 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
577 952
953 if (IS_ERR(tlink))
954 return ERR_CAST(tlink);
955
956 tcon = tlink_tcon(tlink);
578 xid = GetXid(); 957 xid = GetXid();
579 958
580 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, READ_CONTROL, 0, 959 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
581 &fid, &oplock, NULL, cifs_sb->local_nls, 960 &fid, &oplock, NULL, cifs_sb->local_nls,
582 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 961 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
583 if (rc) { 962 if (!rc) {
584 cERROR(1, "Unable to open file to get ACL"); 963 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
585 goto out; 964 CIFSSMBClose(xid, tcon, fid);
586 } 965 }
587 966
588 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 967 cifs_put_tlink(tlink);
589 cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen);
590
591 CIFSSMBClose(xid, cifs_sb->tcon, fid);
592 out:
593 FreeXid(xid); 968 FreeXid(xid);
969
970 cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen);
971 if (rc)
972 return ERR_PTR(rc);
594 return pntsd; 973 return pntsd;
595} 974}
596 975
597/* Retrieve an ACL from the server */ 976/* Retrieve an ACL from the server */
598static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, 977struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
599 struct inode *inode, const char *path, 978 struct inode *inode, const char *path,
600 u32 *pacllen) 979 u32 *pacllen)
601{ 980{
@@ -603,7 +982,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
603 struct cifsFileInfo *open_file = NULL; 982 struct cifsFileInfo *open_file = NULL;
604 983
605 if (inode) 984 if (inode)
606 open_file = find_readable_file(CIFS_I(inode)); 985 open_file = find_readable_file(CIFS_I(inode), true);
607 if (!open_file) 986 if (!open_file)
608 return get_cifs_acl_by_path(cifs_sb, path, pacllen); 987 return get_cifs_acl_by_path(cifs_sb, path, pacllen);
609 988
@@ -616,10 +995,15 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid,
616 struct cifs_ntsd *pnntsd, u32 acllen) 995 struct cifs_ntsd *pnntsd, u32 acllen)
617{ 996{
618 int xid, rc; 997 int xid, rc;
998 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
999
1000 if (IS_ERR(tlink))
1001 return PTR_ERR(tlink);
619 1002
620 xid = GetXid(); 1003 xid = GetXid();
621 rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); 1004 rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen);
622 FreeXid(xid); 1005 FreeXid(xid);
1006 cifs_put_tlink(tlink);
623 1007
624 cFYI(DBG2, "SetCIFSACL rc = %d", rc); 1008 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
625 return rc; 1009 return rc;
@@ -631,10 +1015,16 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
631 int oplock = 0; 1015 int oplock = 0;
632 int xid, rc; 1016 int xid, rc;
633 __u16 fid; 1017 __u16 fid;
1018 struct cifs_tcon *tcon;
1019 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1020
1021 if (IS_ERR(tlink))
1022 return PTR_ERR(tlink);
634 1023
1024 tcon = tlink_tcon(tlink);
635 xid = GetXid(); 1025 xid = GetXid();
636 1026
637 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, WRITE_DAC, 0, 1027 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
638 &fid, &oplock, NULL, cifs_sb->local_nls, 1028 &fid, &oplock, NULL, cifs_sb->local_nls,
639 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1029 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
640 if (rc) { 1030 if (rc) {
@@ -642,17 +1032,18 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
642 goto out; 1032 goto out;
643 } 1033 }
644 1034
645 rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); 1035 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen);
646 cFYI(DBG2, "SetCIFSACL rc = %d", rc); 1036 cFYI(DBG2, "SetCIFSACL rc = %d", rc);
647 1037
648 CIFSSMBClose(xid, cifs_sb->tcon, fid); 1038 CIFSSMBClose(xid, tcon, fid);
649 out: 1039out:
650 FreeXid(xid); 1040 FreeXid(xid);
1041 cifs_put_tlink(tlink);
651 return rc; 1042 return rc;
652} 1043}
653 1044
654/* Set an ACL on the server */ 1045/* Set an ACL on the server */
655static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, 1046int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
656 struct inode *inode, const char *path) 1047 struct inode *inode, const char *path)
657{ 1048{
658 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1049 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
@@ -661,7 +1052,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
661 1052
662 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode); 1053 cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode);
663 1054
664 open_file = find_readable_file(CIFS_I(inode)); 1055 open_file = find_readable_file(CIFS_I(inode), true);
665 if (!open_file) 1056 if (!open_file)
666 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen); 1057 return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
667 1058
@@ -671,7 +1062,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
671} 1062}
672 1063
673/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 1064/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
674void 1065int
675cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 1066cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
676 struct inode *inode, const char *path, const __u16 *pfid) 1067 struct inode *inode, const char *path, const __u16 *pfid)
677{ 1068{
@@ -687,17 +1078,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
687 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); 1078 pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen);
688 1079
689 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 1080 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
690 if (pntsd) 1081 if (IS_ERR(pntsd)) {
691 rc = parse_sec_desc(pntsd, acllen, fattr); 1082 rc = PTR_ERR(pntsd);
692 if (rc) 1083 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
693 cFYI(1, "parse sec desc failed rc = %d", rc); 1084 } else {
1085 rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1086 kfree(pntsd);
1087 if (rc)
1088 cERROR(1, "parse sec desc failed rc = %d", rc);
1089 }
694 1090
695 kfree(pntsd); 1091 return rc;
696 return;
697} 1092}
698 1093
699/* Convert mode bits to an ACL so we can update the ACL on the server */ 1094/* Convert mode bits to an ACL so we can update the ACL on the server */
700int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) 1095int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode)
701{ 1096{
702 int rc = 0; 1097 int rc = 0;
703 __u32 secdesclen = 0; 1098 __u32 secdesclen = 0;
@@ -712,7 +1107,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
712 /* Add three ACEs for owner, group, everyone getting rid of 1107 /* Add three ACEs for owner, group, everyone getting rid of
713 other ACEs as chmod disables ACEs and set the security descriptor */ 1108 other ACEs as chmod disables ACEs and set the security descriptor */
714 1109
715 if (pntsd) { 1110 if (IS_ERR(pntsd)) {
1111 rc = PTR_ERR(pntsd);
1112 cERROR(1, "%s: error %d getting sec desc", __func__, rc);
1113 } else {
716 /* allocate memory for the smb header, 1114 /* allocate memory for the smb header,
717 set security descriptor request security descriptor 1115 set security descriptor request security descriptor
718 parameters, and secuirty descriptor itself */ 1116 parameters, and secuirty descriptor itself */
@@ -742,4 +1140,3 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
742 1140
743 return rc; 1141 return rc;
744} 1142}
745#endif /* CONFIG_CIFS_EXPERIMENTAL */