linux/security/keys/process_keys.c
<<
>>
Prefs
   1/* Manage a process's keyrings
   2 *
   3 * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/init.h>
  14#include <linux/sched.h>
  15#include <linux/keyctl.h>
  16#include <linux/fs.h>
  17#include <linux/err.h>
  18#include <linux/mutex.h>
  19#include <linux/security.h>
  20#include <linux/user_namespace.h>
  21#include <asm/uaccess.h>
  22#include "internal.h"
  23
  24/* Session keyring create vs join semaphore */
  25static DEFINE_MUTEX(key_session_mutex);
  26
  27/* User keyring creation semaphore */
  28static DEFINE_MUTEX(key_user_keyring_mutex);
  29
  30/* The root user's tracking struct */
  31struct key_user root_key_user = {
  32        .usage          = ATOMIC_INIT(3),
  33        .cons_lock      = __MUTEX_INITIALIZER(root_key_user.cons_lock),
  34        .lock           = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
  35        .nkeys          = ATOMIC_INIT(2),
  36        .nikeys         = ATOMIC_INIT(2),
  37        .uid            = 0,
  38        .user_ns        = &init_user_ns,
  39};
  40
  41/*
  42 * Install the user and user session keyrings for the current process's UID.
  43 */
  44int install_user_keyrings(void)
  45{
  46        struct user_struct *user;
  47        const struct cred *cred;
  48        struct key *uid_keyring, *session_keyring;
  49        char buf[20];
  50        int ret;
  51
  52        cred = current_cred();
  53        user = cred->user;
  54
  55        kenter("%p{%u}", user, user->uid);
  56
  57        if (user->uid_keyring) {
  58                kleave(" = 0 [exist]");
  59                return 0;
  60        }
  61
  62        mutex_lock(&key_user_keyring_mutex);
  63        ret = 0;
  64
  65        if (!user->uid_keyring) {
  66                /* get the UID-specific keyring
  67                 * - there may be one in existence already as it may have been
  68                 *   pinned by a session, but the user_struct pointing to it
  69                 *   may have been destroyed by setuid */
  70                sprintf(buf, "_uid.%u", user->uid);
  71
  72                uid_keyring = find_keyring_by_name(buf, true);
  73                if (IS_ERR(uid_keyring)) {
  74                        uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
  75                                                    cred, KEY_ALLOC_IN_QUOTA,
  76                                                    NULL);
  77                        if (IS_ERR(uid_keyring)) {
  78                                ret = PTR_ERR(uid_keyring);
  79                                goto error;
  80                        }
  81                }
  82
  83                /* get a default session keyring (which might also exist
  84                 * already) */
  85                sprintf(buf, "_uid_ses.%u", user->uid);
  86
  87                session_keyring = find_keyring_by_name(buf, true);
  88                if (IS_ERR(session_keyring)) {
  89                        session_keyring =
  90                                keyring_alloc(buf, user->uid, (gid_t) -1,
  91                                              cred, KEY_ALLOC_IN_QUOTA, NULL);
  92                        if (IS_ERR(session_keyring)) {
  93                                ret = PTR_ERR(session_keyring);
  94                                goto error_release;
  95                        }
  96
  97                        /* we install a link from the user session keyring to
  98                         * the user keyring */
  99                        ret = key_link(session_keyring, uid_keyring);
 100                        if (ret < 0)
 101                                goto error_release_both;
 102                }
 103
 104                /* install the keyrings */
 105                user->uid_keyring = uid_keyring;
 106                user->session_keyring = session_keyring;
 107        }
 108
 109        mutex_unlock(&key_user_keyring_mutex);
 110        kleave(" = 0");
 111        return 0;
 112
 113error_release_both:
 114        key_put(session_keyring);
 115error_release:
 116        key_put(uid_keyring);
 117error:
 118        mutex_unlock(&key_user_keyring_mutex);
 119        kleave(" = %d", ret);
 120        return ret;
 121}
 122
 123/*
 124 * Install a fresh thread keyring directly to new credentials.  This keyring is
 125 * allowed to overrun the quota.
 126 */
 127int install_thread_keyring_to_cred(struct cred *new)
 128{
 129        struct key *keyring;
 130
 131        keyring = keyring_alloc("_tid", new->uid, new->gid, new,
 132                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
 133        if (IS_ERR(keyring))
 134                return PTR_ERR(keyring);
 135
 136        new->thread_keyring = keyring;
 137        return 0;
 138}
 139
 140/*
 141 * Install a fresh thread keyring, discarding the old one.
 142 */
 143static int install_thread_keyring(void)
 144{
 145        struct cred *new;
 146        int ret;
 147
 148        new = prepare_creds();
 149        if (!new)
 150                return -ENOMEM;
 151
 152        BUG_ON(new->thread_keyring);
 153
 154        ret = install_thread_keyring_to_cred(new);
 155        if (ret < 0) {
 156                abort_creds(new);
 157                return ret;
 158        }
 159
 160        return commit_creds(new);
 161}
 162
 163/*
 164 * Install a process keyring directly to a credentials struct.
 165 *
 166 * Returns -EEXIST if there was already a process keyring, 0 if one installed,
 167 * and other value on any other error
 168 */
 169int install_process_keyring_to_cred(struct cred *new)
 170{
 171        struct key *keyring;
 172        int ret;
 173
 174        if (new->tgcred->process_keyring)
 175                return -EEXIST;
 176
 177        keyring = keyring_alloc("_pid", new->uid, new->gid,
 178                                new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
 179        if (IS_ERR(keyring))
 180                return PTR_ERR(keyring);
 181
 182        spin_lock_irq(&new->tgcred->lock);
 183        if (!new->tgcred->process_keyring) {
 184                new->tgcred->process_keyring = keyring;
 185                keyring = NULL;
 186                ret = 0;
 187        } else {
 188                ret = -EEXIST;
 189        }
 190        spin_unlock_irq(&new->tgcred->lock);
 191        key_put(keyring);
 192        return ret;
 193}
 194
 195/*
 196 * Make sure a process keyring is installed for the current process.  The
 197 * existing process keyring is not replaced.
 198 *
 199 * Returns 0 if there is a process keyring by the end of this function, some
 200 * error otherwise.
 201 */
 202static int install_process_keyring(void)
 203{
 204        struct cred *new;
 205        int ret;
 206
 207        new = prepare_creds();
 208        if (!new)
 209                return -ENOMEM;
 210
 211        ret = install_process_keyring_to_cred(new);
 212        if (ret < 0) {
 213                abort_creds(new);
 214                return ret != -EEXIST ? ret : 0;
 215        }
 216
 217        return commit_creds(new);
 218}
 219
 220/*
 221 * Install a session keyring directly to a credentials struct.
 222 */
 223int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
 224{
 225        unsigned long flags;
 226        struct key *old;
 227
 228        might_sleep();
 229
 230        /* create an empty session keyring */
 231        if (!keyring) {
 232                flags = KEY_ALLOC_QUOTA_OVERRUN;
 233                if (cred->tgcred->session_keyring)
 234                        flags = KEY_ALLOC_IN_QUOTA;
 235
 236                keyring = keyring_alloc("_ses", cred->uid, cred->gid,
 237                                        cred, flags, NULL);
 238                if (IS_ERR(keyring))
 239                        return PTR_ERR(keyring);
 240        } else {
 241                atomic_inc(&keyring->usage);
 242        }
 243
 244        /* install the keyring */
 245        spin_lock_irq(&cred->tgcred->lock);
 246        old = cred->tgcred->session_keyring;
 247        rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
 248        spin_unlock_irq(&cred->tgcred->lock);
 249
 250        /* we're using RCU on the pointer, but there's no point synchronising
 251         * on it if it didn't previously point to anything */
 252        if (old) {
 253                synchronize_rcu();
 254                key_put(old);
 255        }
 256
 257        return 0;
 258}
 259
 260/*
 261 * Install a session keyring, discarding the old one.  If a keyring is not
 262 * supplied, an empty one is invented.
 263 */
 264static int install_session_keyring(struct key *keyring)
 265{
 266        struct cred *new;
 267        int ret;
 268
 269        new = prepare_creds();
 270        if (!new)
 271                return -ENOMEM;
 272
 273        ret = install_session_keyring_to_cred(new, keyring);
 274        if (ret < 0) {
 275                abort_creds(new);
 276                return ret;
 277        }
 278
 279        return commit_creds(new);
 280}
 281
 282/*
 283 * Handle the fsuid changing.
 284 */
 285void key_fsuid_changed(struct task_struct *tsk)
 286{
 287        /* update the ownership of the thread keyring */
 288        BUG_ON(!tsk->cred);
 289        if (tsk->cred->thread_keyring) {
 290                down_write(&tsk->cred->thread_keyring->sem);
 291                tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
 292                up_write(&tsk->cred->thread_keyring->sem);
 293        }
 294}
 295
 296/*
 297 * Handle the fsgid changing.
 298 */
 299void key_fsgid_changed(struct task_struct *tsk)
 300{
 301        /* update the ownership of the thread keyring */
 302        BUG_ON(!tsk->cred);
 303        if (tsk->cred->thread_keyring) {
 304                down_write(&tsk->cred->thread_keyring->sem);
 305                tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
 306                up_write(&tsk->cred->thread_keyring->sem);
 307        }
 308}
 309
 310/*
 311 * Search the process keyrings attached to the supplied cred for the first
 312 * matching key.
 313 *
 314 * The search criteria are the type and the match function.  The description is
 315 * given to the match function as a parameter, but doesn't otherwise influence
 316 * the search.  Typically the match function will compare the description
 317 * parameter to the key's description.
 318 *
 319 * This can only search keyrings that grant Search permission to the supplied
 320 * credentials.  Keyrings linked to searched keyrings will also be searched if
 321 * they grant Search permission too.  Keys can only be found if they grant
 322 * Search permission to the credentials.
 323 *
 324 * Returns a pointer to the key with the key usage count incremented if
 325 * successful, -EAGAIN if we didn't find any matching key or -ENOKEY if we only
 326 * matched negative keys.
 327 *
 328 * In the case of a successful return, the possession attribute is set on the
 329 * returned key reference.
 330 */
 331key_ref_t search_my_process_keyrings(struct key_type *type,
 332                                     const void *description,
 333                                     key_match_func_t match,
 334                                     bool no_state_check,
 335                                     const struct cred *cred)
 336{
 337        key_ref_t key_ref, ret, err;
 338
 339        /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
 340         * searchable, but we failed to find a key or we found a negative key;
 341         * otherwise we want to return a sample error (probably -EACCES) if
 342         * none of the keyrings were searchable
 343         *
 344         * in terms of priority: success > -ENOKEY > -EAGAIN > other error
 345         */
 346        key_ref = NULL;
 347        ret = NULL;
 348        err = ERR_PTR(-EAGAIN);
 349
 350        /* search the thread keyring first */
 351        if (cred->thread_keyring) {
 352                key_ref = keyring_search_aux(
 353                        make_key_ref(cred->thread_keyring, 1),
 354                        cred, type, description, match, no_state_check);
 355                if (!IS_ERR(key_ref))
 356                        goto found;
 357
 358                switch (PTR_ERR(key_ref)) {
 359                case -EAGAIN: /* no key */
 360                        if (ret)
 361                                break;
 362                case -ENOKEY: /* negative key */
 363                        ret = key_ref;
 364                        break;
 365                default:
 366                        err = key_ref;
 367                        break;
 368                }
 369        }
 370
 371        /* search the process keyring second */
 372        if (cred->tgcred->process_keyring) {
 373                key_ref = keyring_search_aux(
 374                        make_key_ref(cred->tgcred->process_keyring, 1),
 375                        cred, type, description, match, no_state_check);
 376                if (!IS_ERR(key_ref))
 377                        goto found;
 378
 379                switch (PTR_ERR(key_ref)) {
 380                case -EAGAIN: /* no key */
 381                        if (ret)
 382                                break;
 383                case -ENOKEY: /* negative key */
 384                        ret = key_ref;
 385                        break;
 386                default:
 387                        err = key_ref;
 388                        break;
 389                }
 390        }
 391
 392        /* search the session keyring */
 393        if (cred->tgcred->session_keyring) {
 394                rcu_read_lock();
 395                key_ref = keyring_search_aux(
 396                        make_key_ref(rcu_dereference(
 397                                             cred->tgcred->session_keyring),
 398                                     1),
 399                        cred, type, description, match, no_state_check);
 400                rcu_read_unlock();
 401
 402                if (!IS_ERR(key_ref))
 403                        goto found;
 404
 405                switch (PTR_ERR(key_ref)) {
 406                case -EAGAIN: /* no key */
 407                        if (ret)
 408                                break;
 409                case -ENOKEY: /* negative key */
 410                        ret = key_ref;
 411                        break;
 412                default:
 413                        err = key_ref;
 414                        break;
 415                }
 416        }
 417        /* or search the user-session keyring */
 418        else if (cred->user->session_keyring) {
 419                key_ref = keyring_search_aux(
 420                        make_key_ref(cred->user->session_keyring, 1),
 421                        cred, type, description, match, no_state_check);
 422                if (!IS_ERR(key_ref))
 423                        goto found;
 424
 425                switch (PTR_ERR(key_ref)) {
 426                case -EAGAIN: /* no key */
 427                        if (ret)
 428                                break;
 429                case -ENOKEY: /* negative key */
 430                        ret = key_ref;
 431                        break;
 432                default:
 433                        err = key_ref;
 434                        break;
 435                }
 436        }
 437
 438        /* no key - decide on the error we're going to go for */
 439        key_ref = ret ? ret : err;
 440
 441found:
 442        return key_ref;
 443}
 444
 445/*
 446 * Search the process keyrings attached to the supplied cred for the first
 447 * matching key in the manner of search_my_process_keyrings(), but also search
 448 * the keys attached to the assumed authorisation key using its credentials if
 449 * one is available.
 450 *
 451 * Return same as search_my_process_keyrings().
 452 */
 453key_ref_t search_process_keyrings(struct key_type *type,
 454                                  const void *description,
 455                                  key_match_func_t match,
 456                                  const struct cred *cred)
 457{
 458        struct request_key_auth *rka;
 459        key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
 460
 461        might_sleep();
 462
 463        key_ref = search_my_process_keyrings(type, description, match,
 464                                             false, cred);
 465        if (!IS_ERR(key_ref))
 466                goto found;
 467        err = key_ref;
 468
 469        /* if this process has an instantiation authorisation key, then we also
 470         * search the keyrings of the process mentioned there
 471         * - we don't permit access to request_key auth keys via this method
 472         */
 473        if (cred->request_key_auth &&
 474            cred == current_cred() &&
 475            type != &key_type_request_key_auth
 476            ) {
 477                /* defend against the auth key being revoked */
 478                down_read(&cred->request_key_auth->sem);
 479
 480                if (key_validate(cred->request_key_auth) == 0) {
 481                        rka = cred->request_key_auth->payload.data;
 482
 483                        key_ref = search_process_keyrings(type, description,
 484                                                          match, rka->cred);
 485
 486                        up_read(&cred->request_key_auth->sem);
 487
 488                        if (!IS_ERR(key_ref))
 489                                goto found;
 490
 491                        ret = key_ref;
 492                } else {
 493                        up_read(&cred->request_key_auth->sem);
 494                }
 495        }
 496
 497        /* no key - decide on the error we're going to go for */
 498        if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
 499                key_ref = ERR_PTR(-ENOKEY);
 500        else if (err == ERR_PTR(-EACCES))
 501                key_ref = ret;
 502        else
 503                key_ref = err;
 504
 505found:
 506        return key_ref;
 507}
 508
 509/*
 510 * See if the key we're looking at is the target key.
 511 */
 512int lookup_user_key_possessed(const struct key *key, const void *target)
 513{
 514        return key == target;
 515}
 516
 517/*
 518 * Look up a key ID given us by userspace with a given permissions mask to get
 519 * the key it refers to.
 520 *
 521 * Flags can be passed to request that special keyrings be created if referred
 522 * to directly, to permit partially constructed keys to be found and to skip
 523 * validity and permission checks on the found key.
 524 *
 525 * Returns a pointer to the key with an incremented usage count if successful;
 526 * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond
 527 * to a key or the best found key was a negative key; -EKEYREVOKED or
 528 * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the
 529 * found key doesn't grant the requested permit or the LSM denied access to it;
 530 * or -ENOMEM if a special keyring couldn't be created.
 531 *
 532 * In the case of a successful return, the possession attribute is set on the
 533 * returned key reference.
 534 */
 535key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
 536                          key_perm_t perm)
 537{
 538        struct request_key_auth *rka;
 539        const struct cred *cred;
 540        struct key *key;
 541        key_ref_t key_ref, skey_ref;
 542        int ret;
 543
 544try_again:
 545        cred = get_current_cred();
 546        key_ref = ERR_PTR(-ENOKEY);
 547
 548        switch (id) {
 549        case KEY_SPEC_THREAD_KEYRING:
 550                if (!cred->thread_keyring) {
 551                        if (!(lflags & KEY_LOOKUP_CREATE))
 552                                goto error;
 553
 554                        ret = install_thread_keyring();
 555                        if (ret < 0) {
 556                                key_ref = ERR_PTR(ret);
 557                                goto error;
 558                        }
 559                        goto reget_creds;
 560                }
 561
 562                key = cred->thread_keyring;
 563                atomic_inc(&key->usage);
 564                key_ref = make_key_ref(key, 1);
 565                break;
 566
 567        case KEY_SPEC_PROCESS_KEYRING:
 568                if (!cred->tgcred->process_keyring) {
 569                        if (!(lflags & KEY_LOOKUP_CREATE))
 570                                goto error;
 571
 572                        ret = install_process_keyring();
 573                        if (ret < 0) {
 574                                key_ref = ERR_PTR(ret);
 575                                goto error;
 576                        }
 577                        goto reget_creds;
 578                }
 579
 580                key = cred->tgcred->process_keyring;
 581                atomic_inc(&key->usage);
 582                key_ref = make_key_ref(key, 1);
 583                break;
 584
 585        case KEY_SPEC_SESSION_KEYRING:
 586                if (!cred->tgcred->session_keyring) {
 587                        /* always install a session keyring upon access if one
 588                         * doesn't exist yet */
 589                        ret = install_user_keyrings();
 590                        if (ret < 0)
 591                                goto error;
 592                        if (lflags & KEY_LOOKUP_CREATE)
 593                                ret = join_session_keyring(NULL);
 594                        else
 595                                ret = install_session_keyring(
 596                                        cred->user->session_keyring);
 597
 598                        if (ret < 0)
 599                                goto error;
 600                        goto reget_creds;
 601                } else if (cred->tgcred->session_keyring ==
 602                           cred->user->session_keyring &&
 603                           lflags & KEY_LOOKUP_CREATE) {
 604                        ret = join_session_keyring(NULL);
 605                        if (ret < 0)
 606                                goto error;
 607                        goto reget_creds;
 608                }
 609
 610                rcu_read_lock();
 611                key = rcu_dereference(cred->tgcred->session_keyring);
 612                atomic_inc(&key->usage);
 613                rcu_read_unlock();
 614                key_ref = make_key_ref(key, 1);
 615                break;
 616
 617        case KEY_SPEC_USER_KEYRING:
 618                if (!cred->user->uid_keyring) {
 619                        ret = install_user_keyrings();
 620                        if (ret < 0)
 621                                goto error;
 622                }
 623
 624                key = cred->user->uid_keyring;
 625                atomic_inc(&key->usage);
 626                key_ref = make_key_ref(key, 1);
 627                break;
 628
 629        case KEY_SPEC_USER_SESSION_KEYRING:
 630                if (!cred->user->session_keyring) {
 631                        ret = install_user_keyrings();
 632                        if (ret < 0)
 633                                goto error;
 634                }
 635
 636                key = cred->user->session_keyring;
 637                atomic_inc(&key->usage);
 638                key_ref = make_key_ref(key, 1);
 639                break;
 640
 641        case KEY_SPEC_GROUP_KEYRING:
 642                /* group keyrings are not yet supported */
 643                key_ref = ERR_PTR(-EINVAL);
 644                goto error;
 645
 646        case KEY_SPEC_REQKEY_AUTH_KEY:
 647                key = cred->request_key_auth;
 648                if (!key)
 649                        goto error;
 650
 651                atomic_inc(&key->usage);
 652                key_ref = make_key_ref(key, 1);
 653                break;
 654
 655        case KEY_SPEC_REQUESTOR_KEYRING:
 656                if (!cred->request_key_auth)
 657                        goto error;
 658
 659                down_read(&cred->request_key_auth->sem);
 660                if (test_bit(KEY_FLAG_REVOKED,
 661                             &cred->request_key_auth->flags)) {
 662                        key_ref = ERR_PTR(-EKEYREVOKED);
 663                        key = NULL;
 664                } else {
 665                        rka = cred->request_key_auth->payload.data;
 666                        key = rka->dest_keyring;
 667                        atomic_inc(&key->usage);
 668                }
 669                up_read(&cred->request_key_auth->sem);
 670                if (!key)
 671                        goto error;
 672                key_ref = make_key_ref(key, 1);
 673                break;
 674
 675        default:
 676                key_ref = ERR_PTR(-EINVAL);
 677                if (id < 1)
 678                        goto error;
 679
 680                key = key_lookup(id);
 681                if (IS_ERR(key)) {
 682                        key_ref = ERR_CAST(key);
 683                        goto error;
 684                }
 685
 686                key_ref = make_key_ref(key, 0);
 687
 688                /* check to see if we possess the key */
 689                skey_ref = search_process_keyrings(key->type, key,
 690                                                   lookup_user_key_possessed,
 691                                                   cred);
 692
 693                if (!IS_ERR(skey_ref)) {
 694                        key_put(key);
 695                        key_ref = skey_ref;
 696                }
 697
 698                break;
 699        }
 700
 701        /* unlink does not use the nominated key in any way, so can skip all
 702         * the permission checks as it is only concerned with the keyring */
 703        if (lflags & KEY_LOOKUP_FOR_UNLINK) {
 704                ret = 0;
 705                goto error;
 706        }
 707
 708        if (!(lflags & KEY_LOOKUP_PARTIAL)) {
 709                ret = wait_for_key_construction(key, true);
 710                switch (ret) {
 711                case -ERESTARTSYS:
 712                        goto invalid_key;
 713                default:
 714                        if (perm)
 715                                goto invalid_key;
 716                case 0:
 717                        break;
 718                }
 719        } else if (perm) {
 720                ret = key_validate(key);
 721                if (ret < 0)
 722                        goto invalid_key;
 723        }
 724
 725        ret = -EIO;
 726        if (!(lflags & KEY_LOOKUP_PARTIAL) &&
 727            !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
 728                goto invalid_key;
 729
 730        /* check the permissions */
 731        ret = key_task_permission(key_ref, cred, perm);
 732        if (ret < 0)
 733                goto invalid_key;
 734
 735        key->last_used_at = current_kernel_time().tv_sec;
 736
 737error:
 738        put_cred(cred);
 739        return key_ref;
 740
 741invalid_key:
 742        key_ref_put(key_ref);
 743        key_ref = ERR_PTR(ret);
 744        goto error;
 745
 746        /* if we attempted to install a keyring, then it may have caused new
 747         * creds to be installed */
 748reget_creds:
 749        put_cred(cred);
 750        goto try_again;
 751}
 752
 753/*
 754 * Join the named keyring as the session keyring if possible else attempt to
 755 * create a new one of that name and join that.
 756 *
 757 * If the name is NULL, an empty anonymous keyring will be installed as the
 758 * session keyring.
 759 *
 760 * Named session keyrings are joined with a semaphore held to prevent the
 761 * keyrings from going away whilst the attempt is made to going them and also
 762 * to prevent a race in creating compatible session keyrings.
 763 */
 764long join_session_keyring(const char *name)
 765{
 766        const struct cred *old;
 767        struct cred *new;
 768        struct key *keyring;
 769        long ret, serial;
 770
 771        /* only permit this if there's a single thread in the thread group -
 772         * this avoids us having to adjust the creds on all threads and risking
 773         * ENOMEM */
 774        if (!current_is_single_threaded())
 775                return -EMLINK;
 776
 777        new = prepare_creds();
 778        if (!new)
 779                return -ENOMEM;
 780        old = current_cred();
 781
 782        /* if no name is provided, install an anonymous keyring */
 783        if (!name) {
 784                ret = install_session_keyring_to_cred(new, NULL);
 785                if (ret < 0)
 786                        goto error;
 787
 788                serial = new->tgcred->session_keyring->serial;
 789                ret = commit_creds(new);
 790                if (ret == 0)
 791                        ret = serial;
 792                goto okay;
 793        }
 794
 795        /* allow the user to join or create a named keyring */
 796        mutex_lock(&key_session_mutex);
 797
 798        /* look for an existing keyring of this name */
 799        keyring = find_keyring_by_name(name, false);
 800        if (PTR_ERR(keyring) == -ENOKEY) {
 801                /* not found - try and create a new one */
 802                keyring = keyring_alloc(name, old->uid, old->gid, old,
 803                                        KEY_ALLOC_IN_QUOTA, NULL);
 804                if (IS_ERR(keyring)) {
 805                        ret = PTR_ERR(keyring);
 806                        goto error2;
 807                }
 808        } else if (IS_ERR(keyring)) {
 809                ret = PTR_ERR(keyring);
 810                goto error2;
 811        }
 812
 813        /* we've got a keyring - now to install it */
 814        ret = install_session_keyring_to_cred(new, keyring);
 815        if (ret < 0)
 816                goto error2;
 817
 818        commit_creds(new);
 819        mutex_unlock(&key_session_mutex);
 820
 821        ret = keyring->serial;
 822        key_put(keyring);
 823okay:
 824        return ret;
 825
 826error2:
 827        mutex_unlock(&key_session_mutex);
 828error:
 829        abort_creds(new);
 830        return ret;
 831}
 832
 833/*
 834 * Replace a process's session keyring on behalf of one of its children when
 835 * the target  process is about to resume userspace execution.
 836 */
 837void key_change_session_keyring(struct callback_head *twork)
 838{
 839        const struct cred *old = current_cred();
 840        struct cred *new = container_of(twork, struct cred, rcu);
 841
 842        if (unlikely(current->flags & PF_EXITING)) {
 843                put_cred(new);
 844                return;
 845        }
 846
 847        new->  uid      = old->  uid;
 848        new-> euid      = old-> euid;
 849        new-> suid      = old-> suid;
 850        new->fsuid      = old->fsuid;
 851        new->  gid      = old->  gid;
 852        new-> egid      = old-> egid;
 853        new-> sgid      = old-> sgid;
 854        new->fsgid      = old->fsgid;
 855        new->user       = get_uid(old->user);
 856        new->user_ns    = get_user_ns(new->user_ns);
 857        new->group_info = get_group_info(old->group_info);
 858
 859        new->securebits = old->securebits;
 860        new->cap_inheritable    = old->cap_inheritable;
 861        new->cap_permitted      = old->cap_permitted;
 862        new->cap_effective      = old->cap_effective;
 863        new->cap_bset           = old->cap_bset;
 864
 865        new->jit_keyring        = old->jit_keyring;
 866        new->thread_keyring     = key_get(old->thread_keyring);
 867        new->tgcred->tgid       = old->tgcred->tgid;
 868        new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
 869
 870        security_transfer_creds(new, old);
 871
 872        commit_creds(new);
 873}
 874
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.