linux/fs/cifs/cifsacl.c
<<
>>
Prefs
   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 */
  37static const struct cifs_sid sid_everyone = {
  38        1, 1, {0, 0, 0, 0, 0, 1}, {0} };
  39/* security id for Authenticated Users system group */
  40static const struct cifs_sid sid_authusers = {
  41        1, 1, {0, 0, 0, 0, 0, 5}, {cpu_to_le32(11)} };
  42/* group users */
  43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
  44
  45/* S-1-22-1 Unmapped Unix users */
  46static 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 */
  50static 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 */
  60static 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 */
  65static 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 */
  70static 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
  74static const struct cred *root_cred;
  75
  76static int
  77cifs_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
 103static inline void
 104cifs_idmap_key_destroy(struct key *key)
 105{
 106        if (key->datalen > sizeof(key->payload))
 107                kfree(key->payload.data[0]);
 108}
 109
 110static 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
 117static char *
 118sid_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 */
 169static int
 170compare_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
 215static bool
 216is_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
 271static void
 272cifs_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
 284static int
 285id_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);
 332out_key_put:
 333        key_put(sidkey);
 334out_revert_creds:
 335        revert_creds(saved_cred);
 336        return rc;
 337
 338invalidate_key:
 339        key_invalidate(sidkey);
 340        goto out_key_put;
 341}
 342
 343static int
 344sid_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
 400try_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
 444out_key_put:
 445        key_put(sidkey);
 446out_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         */
 454got_valid_id:
 455        if (sidtype == SIDOWNER)
 456                fattr->cf_uid = fuid;
 457        else
 458                fattr->cf_gid = fgid;
 459        return 0;
 460}
 461
 462int
 463init_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
 506failed_put_key:
 507        key_put(keyring);
 508failed_put_cred:
 509        put_cred(cred);
 510        return ret;
 511}
 512
 513void
 514exit_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 */
 523static 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*/
 559static 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 0x%x\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
 616static 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: 0x%x, access flags now 0x%x\n",
 636                 mode, *pace_flags);
 637        return;
 638}
 639
 640static __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
 669static 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
 705static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 706                       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
 707                       struct cifs_fattr *fattr)
 708{
 709        int i;
 710        int num_aces = 0;
 711        int acl_size;
 712        char *acl_base;
 713        struct cifs_ace **ppace;
 714
 715        /* BB need to add parm so we can store the SID BB */
 716
 717        if (!pdacl) {
 718                /* no DACL in the security descriptor, set
 719                   all the permissions for user/group/other */
 720                fattr->cf_mode |= S_IRWXUGO;
 721                return;
 722        }
 723
 724        /* validate that we do not go past end of acl */
 725        if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
 726                cifs_dbg(VFS, "ACL too small to parse DACL\n");
 727                return;
 728        }
 729
 730        cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
 731                 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
 732                 le32_to_cpu(pdacl->num_aces));
 733
 734        /* reset rwx permissions for user/group/other.
 735           Also, if num_aces is 0 i.e. DACL has no ACEs,
 736           user/group/other have no permissions */
 737        fattr->cf_mode &= ~(S_IRWXUGO);
 738
 739        acl_base = (char *)pdacl;
 740        acl_size = sizeof(struct cifs_acl);
 741
 742        num_aces = le32_to_cpu(pdacl->num_aces);
 743        if (num_aces > 0) {
 744                umode_t user_mask = S_IRWXU;
 745                umode_t group_mask = S_IRWXG;
 746                umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 747
 748                if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
 749                        return;
 750                ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
 751                                      GFP_KERNEL);
 752                if (!ppace)
 753                        return;
 754
 755                for (i = 0; i < num_aces; ++i) {
 756                        ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
 757#ifdef CONFIG_CIFS_DEBUG2
 758                        dump_ace(ppace[i], end_of_acl);
 759#endif
 760                        if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
 761                                access_flags_to_mode(ppace[i]->access_req,
 762                                                     ppace[i]->type,
 763                                                     &fattr->cf_mode,
 764                                                     &user_mask);
 765                        if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
 766                                access_flags_to_mode(ppace[i]->access_req,
 767                                                     ppace[i]->type,
 768                                                     &fattr->cf_mode,
 769                                                     &group_mask);
 770                        if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
 771                                access_flags_to_mode(ppace[i]->access_req,
 772                                                     ppace[i]->type,
 773                                                     &fattr->cf_mode,
 774                                                     &other_mask);
 775                        if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
 776                                access_flags_to_mode(ppace[i]->access_req,
 777                                                     ppace[i]->type,
 778                                                     &fattr->cf_mode,
 779                                                     &other_mask);
 780
 781
 782/*                      memcpy((void *)(&(cifscred->aces[i])),
 783                                (void *)ppace[i],
 784                                sizeof(struct cifs_ace)); */
 785
 786                        acl_base = (char *)ppace[i];
 787                        acl_size = le16_to_cpu(ppace[i]->size);
 788                }
 789
 790                kfree(ppace);
 791        }
 792
 793        return;
 794}
 795
 796
 797static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
 798                        struct cifs_sid *pgrpsid, __u64 nmode)
 799{
 800        u16 size = 0;
 801        struct cifs_acl *pnndacl;
 802
 803        pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
 804
 805        size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
 806                                        pownersid, nmode, S_IRWXU);
 807        size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 808                                        pgrpsid, nmode, S_IRWXG);
 809        size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 810                                         &sid_everyone, nmode, S_IRWXO);
 811
 812        pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
 813        pndacl->num_aces = cpu_to_le32(3);
 814
 815        return 0;
 816}
 817
 818
 819static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 820{
 821        /* BB need to add parm so we can store the SID BB */
 822
 823        /* validate that we do not go past end of ACL - sid must be at least 8
 824           bytes long (assuming no sub-auths - e.g. the null SID */
 825        if (end_of_acl < (char *)psid + 8) {
 826                cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
 827                return -EINVAL;
 828        }
 829
 830#ifdef CONFIG_CIFS_DEBUG2
 831        if (psid->num_subauth) {
 832                int i;
 833                cifs_dbg(FYI, "SID revision %d num_auth %d\n",
 834                         psid->revision, psid->num_subauth);
 835
 836                for (i = 0; i < psid->num_subauth; i++) {
 837                        cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
 838                                 i, le32_to_cpu(psid->sub_auth[i]));
 839                }
 840
 841                /* BB add length check to make sure that we do not have huge
 842                        num auths and therefore go off the end */
 843                cifs_dbg(FYI, "RID 0x%x\n",
 844                         le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
 845        }
 846#endif
 847
 848        return 0;
 849}
 850
 851
 852/* Convert CIFS ACL to POSIX form */
 853static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 854                struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
 855{
 856        int rc = 0;
 857        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 858        struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
 859        char *end_of_acl = ((char *)pntsd) + acl_len;
 860        __u32 dacloffset;
 861
 862        if (pntsd == NULL)
 863                return -EIO;
 864
 865        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 866                                le32_to_cpu(pntsd->osidoffset));
 867        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 868                                le32_to_cpu(pntsd->gsidoffset));
 869        dacloffset = le32_to_cpu(pntsd->dacloffset);
 870        dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 871        cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
 872                 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
 873                 le32_to_cpu(pntsd->gsidoffset),
 874                 le32_to_cpu(pntsd->sacloffset), dacloffset);
 875/*      cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
 876        rc = parse_sid(owner_sid_ptr, end_of_acl);
 877        if (rc) {
 878                cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
 879                return rc;
 880        }
 881        rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
 882        if (rc) {
 883                cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
 884                         __func__, rc);
 885                return rc;
 886        }
 887
 888        rc = parse_sid(group_sid_ptr, end_of_acl);
 889        if (rc) {
 890                cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
 891                         __func__, rc);
 892                return rc;
 893        }
 894        rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
 895        if (rc) {
 896                cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
 897                         __func__, rc);
 898                return rc;
 899        }
 900
 901        if (dacloffset)
 902                parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
 903                           group_sid_ptr, fattr);
 904        else
 905                cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
 906
 907        return rc;
 908}
 909
 910/* Convert permission bits from mode to equivalent CIFS ACL */
 911static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 912        __u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
 913{
 914        int rc = 0;
 915        __u32 dacloffset;
 916        __u32 ndacloffset;
 917        __u32 sidsoffset;
 918        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 919        struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 920        struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
 921        struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
 922
 923        if (nmode != NO_CHANGE_64) { /* chmod */
 924                owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 925                                le32_to_cpu(pntsd->osidoffset));
 926                group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 927                                le32_to_cpu(pntsd->gsidoffset));
 928                dacloffset = le32_to_cpu(pntsd->dacloffset);
 929                dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 930                ndacloffset = sizeof(struct cifs_ntsd);
 931                ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
 932                ndacl_ptr->revision = dacl_ptr->revision;
 933                ndacl_ptr->size = 0;
 934                ndacl_ptr->num_aces = 0;
 935
 936                rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
 937                                        nmode);
 938                sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
 939                /* copy sec desc control portion & owner and group sids */
 940                copy_sec_desc(pntsd, pnntsd, sidsoffset);
 941                *aclflag = CIFS_ACL_DACL;
 942        } else {
 943                memcpy(pnntsd, pntsd, secdesclen);
 944                if (uid_valid(uid)) { /* chown */
 945                        uid_t id;
 946                        owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 947                                        le32_to_cpu(pnntsd->osidoffset));
 948                        nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 949                                                                GFP_KERNEL);
 950                        if (!nowner_sid_ptr)
 951                                return -ENOMEM;
 952                        id = from_kuid(&init_user_ns, uid);
 953                        rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
 954                        if (rc) {
 955                                cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
 956                                         __func__, rc, id);
 957                                kfree(nowner_sid_ptr);
 958                                return rc;
 959                        }
 960                        cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
 961                        kfree(nowner_sid_ptr);
 962                        *aclflag = CIFS_ACL_OWNER;
 963                }
 964                if (gid_valid(gid)) { /* chgrp */
 965                        gid_t id;
 966                        group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 967                                        le32_to_cpu(pnntsd->gsidoffset));
 968                        ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 969                                                                GFP_KERNEL);
 970                        if (!ngroup_sid_ptr)
 971                                return -ENOMEM;
 972                        id = from_kgid(&init_user_ns, gid);
 973                        rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
 974                        if (rc) {
 975                                cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
 976                                         __func__, rc, id);
 977                                kfree(ngroup_sid_ptr);
 978                                return rc;
 979                        }
 980                        cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
 981                        kfree(ngroup_sid_ptr);
 982                        *aclflag = CIFS_ACL_GROUP;
 983                }
 984        }
 985
 986        return rc;
 987}
 988
 989struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 990                const struct cifs_fid *cifsfid, u32 *pacllen)
 991{
 992        struct cifs_ntsd *pntsd = NULL;
 993        unsigned int xid;
 994        int rc;
 995        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 996
 997        if (IS_ERR(tlink))
 998                return ERR_CAST(tlink);
 999
1000        xid = get_xid();
1001        rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
1002                                pacllen);
1003        free_xid(xid);
1004
1005        cifs_put_tlink(tlink);
1006
1007        cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1008        if (rc)
1009                return ERR_PTR(rc);
1010        return pntsd;
1011}
1012
1013static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
1014                const char *path, u32 *pacllen)
1015{
1016        struct cifs_ntsd *pntsd = NULL;
1017        int oplock = 0;
1018        unsigned int xid;
1019        int rc, create_options = 0;
1020        struct cifs_tcon *tcon;
1021        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1022        struct cifs_fid fid;
1023        struct cifs_open_parms oparms;
1024
1025        if (IS_ERR(tlink))
1026                return ERR_CAST(tlink);
1027
1028        tcon = tlink_tcon(tlink);
1029        xid = get_xid();
1030
1031        if (backup_cred(cifs_sb))
1032                create_options |= CREATE_OPEN_BACKUP_INTENT;
1033
1034        oparms.tcon = tcon;
1035        oparms.cifs_sb = cifs_sb;
1036        oparms.desired_access = READ_CONTROL;
1037        oparms.create_options = create_options;
1038        oparms.disposition = FILE_OPEN;
1039        oparms.path = path;
1040        oparms.fid = &fid;
1041        oparms.reconnect = false;
1042
1043        rc = CIFS_open(xid, &oparms, &oplock, NULL);
1044        if (!rc) {
1045                rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
1046                CIFSSMBClose(xid, tcon, fid.netfid);
1047        }
1048
1049        cifs_put_tlink(tlink);
1050        free_xid(xid);
1051
1052        cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
1053        if (rc)
1054                return ERR_PTR(rc);
1055        return pntsd;
1056}
1057
1058/* Retrieve an ACL from the server */
1059struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
1060                                      struct inode *inode, const char *path,
1061                                      u32 *pacllen)
1062{
1063        struct cifs_ntsd *pntsd = NULL;
1064        struct cifsFileInfo *open_file = NULL;
1065
1066        if (inode)
1067                open_file = find_readable_file(CIFS_I(inode), true);
1068        if (!open_file)
1069                return get_cifs_acl_by_path(cifs_sb, path, pacllen);
1070
1071        pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
1072        cifsFileInfo_put(open_file);
1073        return pntsd;
1074}
1075
1076 /* Set an ACL on the server */
1077int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
1078                        struct inode *inode, const char *path, int aclflag)
1079{
1080        int oplock = 0;
1081        unsigned int xid;
1082        int rc, access_flags, create_options = 0;
1083        struct cifs_tcon *tcon;
1084        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1085        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1086        struct cifs_fid fid;
1087        struct cifs_open_parms oparms;
1088
1089        if (IS_ERR(tlink))
1090                return PTR_ERR(tlink);
1091
1092        tcon = tlink_tcon(tlink);
1093        xid = get_xid();
1094
1095        if (backup_cred(cifs_sb))
1096                create_options |= CREATE_OPEN_BACKUP_INTENT;
1097
1098        if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
1099                access_flags = WRITE_OWNER;
1100        else
1101                access_flags = WRITE_DAC;
1102
1103        oparms.tcon = tcon;
1104        oparms.cifs_sb = cifs_sb;
1105        oparms.desired_access = access_flags;
1106        oparms.create_options = create_options;
1107        oparms.disposition = FILE_OPEN;
1108        oparms.path = path;
1109        oparms.fid = &fid;
1110        oparms.reconnect = false;
1111
1112        rc = CIFS_open(xid, &oparms, &oplock, NULL);
1113        if (rc) {
1114                cifs_dbg(VFS, "Unable to open file to set ACL\n");
1115                goto out;
1116        }
1117
1118        rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
1119        cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
1120
1121        CIFSSMBClose(xid, tcon, fid.netfid);
1122out:
1123        free_xid(xid);
1124        cifs_put_tlink(tlink);
1125        return rc;
1126}
1127
1128/* Translate the CIFS ACL (similar to NTFS ACL) for a file into mode bits */
1129int
1130cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1131                  struct inode *inode, const char *path,
1132                  const struct cifs_fid *pfid)
1133{
1134        struct cifs_ntsd *pntsd = NULL;
1135        u32 acllen = 0;
1136        int rc = 0;
1137        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1138        struct smb_version_operations *ops;
1139
1140        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1141
1142        if (IS_ERR(tlink))
1143                return PTR_ERR(tlink);
1144
1145        ops = tlink_tcon(tlink)->ses->server->ops;
1146
1147        if (pfid && (ops->get_acl_by_fid))
1148                pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
1149        else if (ops->get_acl)
1150                pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
1151        else {
1152                cifs_put_tlink(tlink);
1153                return -EOPNOTSUPP;
1154        }
1155        /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1156        if (IS_ERR(pntsd)) {
1157                rc = PTR_ERR(pntsd);
1158                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1159        } else {
1160                rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1161                kfree(pntsd);
1162                if (rc)
1163                        cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1164        }
1165
1166        cifs_put_tlink(tlink);
1167
1168        return rc;
1169}
1170
1171/* Convert mode bits to an ACL so we can update the ACL on the server */
1172int
1173id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1174                        kuid_t uid, kgid_t gid)
1175{
1176        int rc = 0;
1177        int aclflag = CIFS_ACL_DACL; /* default flag to set */
1178        __u32 secdesclen = 0;
1179        struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1180        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1181        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1182        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1183        struct smb_version_operations *ops;
1184
1185        if (IS_ERR(tlink))
1186                return PTR_ERR(tlink);
1187
1188        ops = tlink_tcon(tlink)->ses->server->ops;
1189
1190        cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1191
1192        /* Get the security descriptor */
1193
1194        if (ops->get_acl == NULL) {
1195                cifs_put_tlink(tlink);
1196                return -EOPNOTSUPP;
1197        }
1198
1199        pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
1200        if (IS_ERR(pntsd)) {
1201                rc = PTR_ERR(pntsd);
1202                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1203                cifs_put_tlink(tlink);
1204                return rc;
1205        }
1206
1207        /*
1208         * Add three ACEs for owner, group, everyone getting rid of other ACEs
1209         * as chmod disables ACEs and set the security descriptor. Allocate
1210         * memory for the smb header, set security descriptor request security
1211         * descriptor parameters, and secuirty descriptor itself
1212         */
1213        secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1214        pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1215        if (!pnntsd) {
1216                kfree(pntsd);
1217                cifs_put_tlink(tlink);
1218                return -ENOMEM;
1219        }
1220
1221        rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1222                                &aclflag);
1223
1224        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1225
1226        if (ops->set_acl == NULL)
1227                rc = -EOPNOTSUPP;
1228
1229        if (!rc) {
1230                /* Set the security descriptor */
1231                rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
1232                cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1233        }
1234        cifs_put_tlink(tlink);
1235
1236        kfree(pnntsd);
1237        kfree(pntsd);
1238        return rc;
1239}
1240