~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/cifsacl.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp