root/fs/cifs/cifsacl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cifs_idmap_key_instantiate
  2. cifs_idmap_key_destroy
  3. sid_to_key_str
  4. compare_sids
  5. is_well_known_sid
  6. cifs_copy_sid
  7. id_to_sid
  8. sid_to_id
  9. init_cifs_idmap
  10. exit_cifs_idmap
  11. copy_sec_desc
  12. access_flags_to_mode
  13. mode_to_access_flags
  14. fill_ace_for_sid
  15. dump_ace
  16. parse_dacl
  17. set_chmod_dacl
  18. parse_sid
  19. parse_sec_desc
  20. build_sec_desc
  21. get_cifs_acl_by_fid
  22. get_cifs_acl_by_path
  23. get_cifs_acl
  24. set_cifs_acl
  25. cifs_acl_to_fattr
  26. id_mode_to_cifs_acl

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

/* [<][>][^][v][top][bottom][index][help] */