linux/security/keys/process_keys.c
<<
>>
Prefs
   1/* Management of 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/*
  43 * install user and user session keyrings for a particular UID
  44 */
  45int install_user_keyrings(void)
  46{
  47        struct user_struct *user;
  48        const struct cred *cred;
  49        struct key *uid_keyring, *session_keyring;
  50        char buf[20];
  51        int ret;
  52
  53        cred = current_cred();
  54        user = cred->user;
  55
  56        kenter("%p{%u}", user, user->uid);
  57
  58        if (user->uid_keyring) {
  59                kleave(" = 0 [exist]");
  60                return 0;
  61        }
  62
  63        mutex_lock(&key_user_keyring_mutex);
  64        ret = 0;
  65
  66        if (!user->uid_keyring) {
  67                /* get the UID-specific keyring
  68                 * - there may be one in existence already as it may have been
  69                 *   pinned by a session, but the user_struct pointing to it
  70                 *   may have been destroyed by setuid */
  71                sprintf(buf, "_uid.%u", user->uid);
  72
  73                uid_keyring = find_keyring_by_name(buf, true);
  74                if (IS_ERR(uid_keyring)) {
  75                        uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
  76                                                    cred, KEY_ALLOC_IN_QUOTA,
  77                                                    NULL);
  78                        if (IS_ERR(uid_keyring)) {
  79                                ret = PTR_ERR(uid_keyring);
  80                                goto error;
  81                        }
  82                }
  83
  84                /* get a default session keyring (which might also exist
  85                 * already) */
  86                sprintf(buf, "_uid_ses.%u", user->uid);
  87
  88                session_keyring = find_keyring_by_name(buf, true);
  89                if (IS_ERR(session_keyring)) {
  90                        session_keyring =
  91                                keyring_alloc(buf, user->uid, (gid_t) -1,
  92                                              cred, KEY_ALLOC_IN_QUOTA, NULL);
  93                        if (IS_ERR(session_keyring)) {
  94                                ret = PTR_ERR(session_keyring);
  95                                goto error_release;
  96                        }
  97
  98                        /* we install a link from the user session keyring to
  99                         * the user keyring */
 100                        ret = key_link(session_keyring, uid_keyring);
 101                        if (ret < 0)
 102                                goto error_release_both;
 103                }
 104
 105                /* install the keyrings */
 106                user->uid_keyring = uid_keyring;
 107                user->session_keyring = session_keyring;
 108        }
 109
 110        mutex_unlock(&key_user_keyring_mutex);
 111        kleave(" = 0");
 112        return 0;
 113
 114error_release_both:
 115        key_put(session_keyring);
 116error_release:
 117        key_put(uid_keyring);
 118error:
 119        mutex_unlock(&key_user_keyring_mutex);
 120        kleave(" = %d", ret);
 121        return ret;
 122}
 123
 124/*
 125 * install a fresh thread keyring directly to new credentials
 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 * - returns -EEXIST if there was already a process keyring, 0 if one installed,
 166 *   and other -ve on any other error
 167 */
 168int install_process_keyring_to_cred(struct cred *new)
 169{
 170        struct key *keyring;
 171        int ret;
 172
 173        if (new->tgcred->process_keyring)
 174                return -EEXIST;
 175
 176        keyring = keyring_alloc("_pid", new->uid, new->gid,
 177                                new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
 178        if (IS_ERR(keyring))
 179                return PTR_ERR(keyring);
 180
 181        spin_lock_irq(&new->tgcred->lock);
 182        if (!new->tgcred->process_keyring) {
 183                new->tgcred->process_keyring = keyring;
 184                keyring = NULL;
 185                ret = 0;
 186        } else {
 187                ret = -EEXIST;
 188        }
 189        spin_unlock_irq(&new->tgcred->lock);
 190        key_put(keyring);
 191        return ret;
 192}
 193
 194/*
 195 * make sure a process keyring is installed
 196 * - we
 197 */
 198static int install_process_keyring(void)
 199{
 200        struct cred *new;
 201        int ret;
 202
 203        new = prepare_creds();
 204        if (!new)
 205                return -ENOMEM;
 206
 207        ret = install_process_keyring_to_cred(new);
 208        if (ret < 0) {
 209                abort_creds(new);
 210                return ret != -EEXIST ? ret : 0;
 211        }
 212
 213        return commit_creds(new);
 214}
 215
 216/*
 217 * install a session keyring directly to a credentials struct
 218 */
 219int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
 220{
 221        unsigned long flags;
 222        struct key *old;
 223
 224        might_sleep();
 225
 226        /* create an empty session keyring */
 227        if (!keyring) {
 228                flags = KEY_ALLOC_QUOTA_OVERRUN;
 229                if (cred->tgcred->session_keyring)
 230                        flags = KEY_ALLOC_IN_QUOTA;
 231
 232                keyring = keyring_alloc("_ses", cred->uid, cred->gid,
 233                                        cred, flags, NULL);
 234                if (IS_ERR(keyring))
 235                        return PTR_ERR(keyring);
 236        } else {
 237                atomic_inc(&keyring->usage);
 238        }
 239
 240        /* install the keyring */
 241        spin_lock_irq(&cred->tgcred->lock);
 242        old = cred->tgcred->session_keyring;
 243        rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
 244        spin_unlock_irq(&cred->tgcred->lock);
 245
 246        /* we're using RCU on the pointer, but there's no point synchronising
 247         * on it if it didn't previously point to anything */
 248        if (old) {
 249                synchronize_rcu();
 250                key_put(old);
 251        }
 252
 253        return 0;
 254}
 255
 256/*
 257 * install a session keyring, discarding the old one
 258 * - if a keyring is not supplied, an empty one is invented
 259 */
 260static int install_session_keyring(struct key *keyring)
 261{
 262        struct cred *new;
 263        int ret;
 264
 265        new = prepare_creds();
 266        if (!new)
 267                return -ENOMEM;
 268
 269        ret = install_session_keyring_to_cred(new, NULL);
 270        if (ret < 0) {
 271                abort_creds(new);
 272                return ret;
 273        }
 274
 275        return commit_creds(new);
 276}
 277
 278/*****************************************************************************/
 279/*
 280 * the filesystem user ID changed
 281 */
 282void key_fsuid_changed(struct task_struct *tsk)
 283{
 284        /* update the ownership of the thread keyring */
 285        BUG_ON(!tsk->cred);
 286        if (tsk->cred->thread_keyring) {
 287                down_write(&tsk->cred->thread_keyring->sem);
 288                tsk->cred->thread_keyring->uid = tsk->cred->fsuid;
 289                up_write(&tsk->cred->thread_keyring->sem);
 290        }
 291
 292} /* end key_fsuid_changed() */
 293
 294/*****************************************************************************/
 295/*
 296 * the filesystem group ID changed
 297 */
 298void key_fsgid_changed(struct task_struct *tsk)
 299{
 300        /* update the ownership of the thread keyring */
 301        BUG_ON(!tsk->cred);
 302        if (tsk->cred->thread_keyring) {
 303                down_write(&tsk->cred->thread_keyring->sem);
 304                tsk->cred->thread_keyring->gid = tsk->cred->fsgid;
 305                up_write(&tsk->cred->thread_keyring->sem);
 306        }
 307
 308} /* end key_fsgid_changed() */
 309
 310/*****************************************************************************/
 311/*
 312 * search only my process keyrings for the first matching key
 313 * - we use the supplied match function to see if the description (or other
 314 *   feature of interest) matches
 315 * - we return -EAGAIN if we didn't find any matching key
 316 * - we return -ENOKEY if we found only negative matching keys
 317 */
 318key_ref_t search_my_process_keyrings(struct key_type *type,
 319                                     const void *description,
 320                                     key_match_func_t match,
 321                                     const struct cred *cred)
 322{
 323        key_ref_t key_ref, ret, err;
 324
 325        /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
 326         * searchable, but we failed to find a key or we found a negative key;
 327         * otherwise we want to return a sample error (probably -EACCES) if
 328         * none of the keyrings were searchable
 329         *
 330         * in terms of priority: success > -ENOKEY > -EAGAIN > other error
 331         */
 332        key_ref = NULL;
 333        ret = NULL;
 334        err = ERR_PTR(-EAGAIN);
 335
 336        /* search the thread keyring first */
 337        if (cred->thread_keyring) {
 338                key_ref = keyring_search_aux(
 339                        make_key_ref(cred->thread_keyring, 1),
 340                        cred, type, description, match);
 341                if (!IS_ERR(key_ref))
 342                        goto found;
 343
 344                switch (PTR_ERR(key_ref)) {
 345                case -EAGAIN: /* no key */
 346                        if (ret)
 347                                break;
 348                case -ENOKEY: /* negative key */
 349                        ret = key_ref;
 350                        break;
 351                default:
 352                        err = key_ref;
 353                        break;
 354                }
 355        }
 356
 357        /* search the process keyring second */
 358        if (cred->tgcred->process_keyring) {
 359                key_ref = keyring_search_aux(
 360                        make_key_ref(cred->tgcred->process_keyring, 1),
 361                        cred, type, description, match);
 362                if (!IS_ERR(key_ref))
 363                        goto found;
 364
 365                switch (PTR_ERR(key_ref)) {
 366                case -EAGAIN: /* no key */
 367                        if (ret)
 368                                break;
 369                case -ENOKEY: /* negative key */
 370                        ret = key_ref;
 371                        break;
 372                default:
 373                        err = key_ref;
 374                        break;
 375                }
 376        }
 377
 378        /* search the session keyring */
 379        if (cred->tgcred->session_keyring) {
 380                rcu_read_lock();
 381                key_ref = keyring_search_aux(
 382                        make_key_ref(rcu_dereference(
 383                                             cred->tgcred->session_keyring),
 384                                     1),
 385                        cred, type, description, match);
 386                rcu_read_unlock();
 387
 388                if (!IS_ERR(key_ref))
 389                        goto found;
 390
 391                switch (PTR_ERR(key_ref)) {
 392                case -EAGAIN: /* no key */
 393                        if (ret)
 394                                break;
 395                case -ENOKEY: /* negative key */
 396                        ret = key_ref;
 397                        break;
 398                default:
 399                        err = key_ref;
 400                        break;
 401                }
 402        }
 403        /* or search the user-session keyring */
 404        else if (cred->user->session_keyring) {
 405                key_ref = keyring_search_aux(
 406                        make_key_ref(cred->user->session_keyring, 1),
 407                        cred, type, description, match);
 408                if (!IS_ERR(key_ref))
 409                        goto found;
 410
 411                switch (PTR_ERR(key_ref)) {
 412                case -EAGAIN: /* no key */
 413                        if (ret)
 414                                break;
 415                case -ENOKEY: /* negative key */
 416                        ret = key_ref;
 417                        break;
 418                default:
 419                        err = key_ref;
 420                        break;
 421                }
 422        }
 423
 424        /* no key - decide on the error we're going to go for */
 425        key_ref = ret ? ret : err;
 426
 427found:
 428        return key_ref;
 429}
 430
 431/*****************************************************************************/
 432/*
 433 * search the process keyrings for the first matching key
 434 * - we use the supplied match function to see if the description (or other
 435 *   feature of interest) matches
 436 * - we return -EAGAIN if we didn't find any matching key
 437 * - we return -ENOKEY if we found only negative matching keys
 438 */
 439key_ref_t search_process_keyrings(struct key_type *type,
 440                                  const void *description,
 441                                  key_match_func_t match,
 442                                  const struct cred *cred)
 443{
 444        struct request_key_auth *rka;
 445        key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
 446
 447        might_sleep();
 448
 449        key_ref = search_my_process_keyrings(type, description, match, cred);
 450        if (!IS_ERR(key_ref))
 451                goto found;
 452        err = key_ref;
 453
 454        /* if this process has an instantiation authorisation key, then we also
 455         * search the keyrings of the process mentioned there
 456         * - we don't permit access to request_key auth keys via this method
 457         */
 458        if (cred->request_key_auth &&
 459            cred == current_cred() &&
 460            type != &key_type_request_key_auth
 461            ) {
 462                /* defend against the auth key being revoked */
 463                down_read(&cred->request_key_auth->sem);
 464
 465                if (key_validate(cred->request_key_auth) == 0) {
 466                        rka = cred->request_key_auth->payload.data;
 467
 468                        key_ref = search_process_keyrings(type, description,
 469                                                          match, rka->cred);
 470
 471                        up_read(&cred->request_key_auth->sem);
 472
 473                        if (!IS_ERR(key_ref))
 474                                goto found;
 475
 476                        ret = key_ref;
 477                } else {
 478                        up_read(&cred->request_key_auth->sem);
 479                }
 480        }
 481
 482        /* no key - decide on the error we're going to go for */
 483        if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
 484                key_ref = ERR_PTR(-ENOKEY);
 485        else if (err == ERR_PTR(-EACCES))
 486                key_ref = ret;
 487        else
 488                key_ref = err;
 489
 490found:
 491        return key_ref;
 492
 493} /* end search_process_keyrings() */
 494
 495/*****************************************************************************/
 496/*
 497 * see if the key we're looking at is the target key
 498 */
 499int lookup_user_key_possessed(const struct key *key, const void *target)
 500{
 501        return key == target;
 502
 503} /* end lookup_user_key_possessed() */
 504
 505/*****************************************************************************/
 506/*
 507 * lookup a key given a key ID from userspace with a given permissions mask
 508 * - don't create special keyrings unless so requested
 509 * - partially constructed keys aren't found unless requested
 510 */
 511key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
 512                          key_perm_t perm)
 513{
 514        struct request_key_auth *rka;
 515        const struct cred *cred;
 516        struct key *key;
 517        key_ref_t key_ref, skey_ref;
 518        int ret;
 519
 520try_again:
 521        cred = get_current_cred();
 522        key_ref = ERR_PTR(-ENOKEY);
 523
 524        switch (id) {
 525        case KEY_SPEC_THREAD_KEYRING:
 526                if (!cred->thread_keyring) {
 527                        if (!(lflags & KEY_LOOKUP_CREATE))
 528                                goto error;
 529
 530                        ret = install_thread_keyring();
 531                        if (ret < 0) {
 532                                key_ref = ERR_PTR(ret);
 533                                goto error;
 534                        }
 535                        goto reget_creds;
 536                }
 537
 538                key = cred->thread_keyring;
 539                atomic_inc(&key->usage);
 540                key_ref = make_key_ref(key, 1);
 541                break;
 542
 543        case KEY_SPEC_PROCESS_KEYRING:
 544                if (!cred->tgcred->process_keyring) {
 545                        if (!(lflags & KEY_LOOKUP_CREATE))
 546                                goto error;
 547
 548                        ret = install_process_keyring();
 549                        if (ret < 0) {
 550                                key_ref = ERR_PTR(ret);
 551                                goto error;
 552                        }
 553                        goto reget_creds;
 554                }
 555
 556                key = cred->tgcred->process_keyring;
 557                atomic_inc(&key->usage);
 558                key_ref = make_key_ref(key, 1);
 559                break;
 560
 561        case KEY_SPEC_SESSION_KEYRING:
 562                if (!cred->tgcred->session_keyring) {
 563                        /* always install a session keyring upon access if one
 564                         * doesn't exist yet */
 565                        ret = install_user_keyrings();
 566                        if (ret < 0)
 567                                goto error;
 568                        ret = install_session_keyring(
 569                                cred->user->session_keyring);
 570
 571                        if (ret < 0)
 572                                goto error;
 573                        goto reget_creds;
 574                }
 575
 576                rcu_read_lock();
 577                key = rcu_dereference(cred->tgcred->session_keyring);
 578                atomic_inc(&key->usage);
 579                rcu_read_unlock();
 580                key_ref = make_key_ref(key, 1);
 581                break;
 582
 583        case KEY_SPEC_USER_KEYRING:
 584                if (!cred->user->uid_keyring) {
 585                        ret = install_user_keyrings();
 586                        if (ret < 0)
 587                                goto error;
 588                }
 589
 590                key = cred->user->uid_keyring;
 591                atomic_inc(&key->usage);
 592                key_ref = make_key_ref(key, 1);
 593                break;
 594
 595        case KEY_SPEC_USER_SESSION_KEYRING:
 596                if (!cred->user->session_keyring) {
 597                        ret = install_user_keyrings();
 598                        if (ret < 0)
 599                                goto error;
 600                }
 601
 602                key = cred->user->session_keyring;
 603                atomic_inc(&key->usage);
 604                key_ref = make_key_ref(key, 1);
 605                break;
 606
 607        case KEY_SPEC_GROUP_KEYRING:
 608                /* group keyrings are not yet supported */
 609                key_ref = ERR_PTR(-EINVAL);
 610                goto error;
 611
 612        case KEY_SPEC_REQKEY_AUTH_KEY:
 613                key = cred->request_key_auth;
 614                if (!key)
 615                        goto error;
 616
 617                atomic_inc(&key->usage);
 618                key_ref = make_key_ref(key, 1);
 619                break;
 620
 621        case KEY_SPEC_REQUESTOR_KEYRING:
 622                if (!cred->request_key_auth)
 623                        goto error;
 624
 625                down_read(&cred->request_key_auth->sem);
 626                if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) {
 627                        key_ref = ERR_PTR(-EKEYREVOKED);
 628                        key = NULL;
 629                } else {
 630                        rka = cred->request_key_auth->payload.data;
 631                        key = rka->dest_keyring;
 632                        atomic_inc(&key->usage);
 633                }
 634                up_read(&cred->request_key_auth->sem);
 635                if (!key)
 636                        goto error;
 637                key_ref = make_key_ref(key, 1);
 638                break;
 639
 640        default:
 641                key_ref = ERR_PTR(-EINVAL);
 642                if (id < 1)
 643                        goto error;
 644
 645                key = key_lookup(id);
 646                if (IS_ERR(key)) {
 647                        key_ref = ERR_CAST(key);
 648                        goto error;
 649                }
 650
 651                key_ref = make_key_ref(key, 0);
 652
 653                /* check to see if we possess the key */
 654                skey_ref = search_process_keyrings(key->type, key,
 655                                                   lookup_user_key_possessed,
 656                                                   cred);
 657
 658                if (!IS_ERR(skey_ref)) {
 659                        key_put(key);
 660                        key_ref = skey_ref;
 661                }
 662
 663                break;
 664        }
 665
 666        /* unlink does not use the nominated key in any way, so can skip all
 667         * the permission checks as it is only concerned with the keyring */
 668        if (lflags & KEY_LOOKUP_FOR_UNLINK) {
 669                ret = 0;
 670                goto error;
 671        }
 672
 673        if (!(lflags & KEY_LOOKUP_PARTIAL)) {
 674                ret = wait_for_key_construction(key, true);
 675                switch (ret) {
 676                case -ERESTARTSYS:
 677                        goto invalid_key;
 678                default:
 679                        if (perm)
 680                                goto invalid_key;
 681                case 0:
 682                        break;
 683                }
 684        } else if (perm) {
 685                ret = key_validate(key);
 686                if (ret < 0)
 687                        goto invalid_key;
 688        }
 689
 690        ret = -EIO;
 691        if (!(lflags & KEY_LOOKUP_PARTIAL) &&
 692            !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
 693                goto invalid_key;
 694
 695        /* check the permissions */
 696        ret = key_task_permission(key_ref, cred, perm);
 697        if (ret < 0)
 698                goto invalid_key;
 699
 700error:
 701        put_cred(cred);
 702        return key_ref;
 703
 704invalid_key:
 705        key_ref_put(key_ref);
 706        key_ref = ERR_PTR(ret);
 707        goto error;
 708
 709        /* if we attempted to install a keyring, then it may have caused new
 710         * creds to be installed */
 711reget_creds:
 712        put_cred(cred);
 713        goto try_again;
 714
 715} /* end lookup_user_key() */
 716
 717/*****************************************************************************/
 718/*
 719 * join the named keyring as the session keyring if possible, or attempt to
 720 * create a new one of that name if not
 721 * - if the name is NULL, an empty anonymous keyring is installed instead
 722 * - named session keyring joining is done with a semaphore held
 723 */
 724long join_session_keyring(const char *name)
 725{
 726        const struct cred *old;
 727        struct cred *new;
 728        struct key *keyring;
 729        long ret, serial;
 730
 731        /* only permit this if there's a single thread in the thread group -
 732         * this avoids us having to adjust the creds on all threads and risking
 733         * ENOMEM */
 734        if (!current_is_single_threaded())
 735                return -EMLINK;
 736
 737        new = prepare_creds();
 738        if (!new)
 739                return -ENOMEM;
 740        old = current_cred();
 741
 742        /* if no name is provided, install an anonymous keyring */
 743        if (!name) {
 744                ret = install_session_keyring_to_cred(new, NULL);
 745                if (ret < 0)
 746                        goto error;
 747
 748                serial = new->tgcred->session_keyring->serial;
 749                ret = commit_creds(new);
 750                if (ret == 0)
 751                        ret = serial;
 752                goto okay;
 753        }
 754
 755        /* allow the user to join or create a named keyring */
 756        mutex_lock(&key_session_mutex);
 757
 758        /* look for an existing keyring of this name */
 759        keyring = find_keyring_by_name(name, false);
 760        if (PTR_ERR(keyring) == -ENOKEY) {
 761                /* not found - try and create a new one */
 762                keyring = keyring_alloc(name, old->uid, old->gid, old,
 763                                        KEY_ALLOC_IN_QUOTA, NULL);
 764                if (IS_ERR(keyring)) {
 765                        ret = PTR_ERR(keyring);
 766                        goto error2;
 767                }
 768        } else if (IS_ERR(keyring)) {
 769                ret = PTR_ERR(keyring);
 770                goto error2;
 771        }
 772
 773        /* we've got a keyring - now to install it */
 774        ret = install_session_keyring_to_cred(new, keyring);
 775        if (ret < 0)
 776                goto error2;
 777
 778        commit_creds(new);
 779        mutex_unlock(&key_session_mutex);
 780
 781        ret = keyring->serial;
 782        key_put(keyring);
 783okay:
 784        return ret;
 785
 786error2:
 787        mutex_unlock(&key_session_mutex);
 788error:
 789        abort_creds(new);
 790        return ret;
 791}
 792
 793/*
 794 * Replace a process's session keyring when that process resumes userspace on
 795 * behalf of one of its children
 796 */
 797void key_replace_session_keyring(void)
 798{
 799        const struct cred *old;
 800        struct cred *new;
 801
 802        if (!current->replacement_session_keyring)
 803                return;
 804
 805        write_lock_irq(&tasklist_lock);
 806        new = current->replacement_session_keyring;
 807        current->replacement_session_keyring = NULL;
 808        write_unlock_irq(&tasklist_lock);
 809
 810        if (!new)
 811                return;
 812
 813        old = current_cred();
 814        new->  uid      = old->  uid;
 815        new-> euid      = old-> euid;
 816        new-> suid      = old-> suid;
 817        new->fsuid      = old->fsuid;
 818        new->  gid      = old->  gid;
 819        new-> egid      = old-> egid;
 820        new-> sgid      = old-> sgid;
 821        new->fsgid      = old->fsgid;
 822        new->user       = get_uid(old->user);
 823        new->group_info = get_group_info(old->group_info);
 824
 825        new->securebits = old->securebits;
 826        new->cap_inheritable    = old->cap_inheritable;
 827        new->cap_permitted      = old->cap_permitted;
 828        new->cap_effective      = old->cap_effective;
 829        new->cap_bset           = old->cap_bset;
 830
 831        new->jit_keyring        = old->jit_keyring;
 832        new->thread_keyring     = key_get(old->thread_keyring);
 833        new->tgcred->tgid       = old->tgcred->tgid;
 834        new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
 835
 836        security_transfer_creds(new, old);
 837
 838        commit_creds(new);
 839}
 840
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.