linux/net/sunrpc/auth.c
<<
>>
Prefs
   1/*
   2 * linux/net/sunrpc/auth.c
   3 *
   4 * Generic RPC client authentication API.
   5 *
   6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/sched.h>
  11#include <linux/module.h>
  12#include <linux/slab.h>
  13#include <linux/errno.h>
  14#include <linux/hash.h>
  15#include <linux/sunrpc/clnt.h>
  16#include <linux/sunrpc/gss_api.h>
  17#include <linux/spinlock.h>
  18
  19#ifdef RPC_DEBUG
  20# define RPCDBG_FACILITY        RPCDBG_AUTH
  21#endif
  22
  23#define RPC_CREDCACHE_DEFAULT_HASHBITS  (4)
  24struct rpc_cred_cache {
  25        struct hlist_head       *hashtable;
  26        unsigned int            hashbits;
  27        spinlock_t              lock;
  28};
  29
  30static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
  31
  32static DEFINE_SPINLOCK(rpc_authflavor_lock);
  33static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
  34        &authnull_ops,          /* AUTH_NULL */
  35        &authunix_ops,          /* AUTH_UNIX */
  36        NULL,                   /* others can be loadable modules */
  37};
  38
  39static LIST_HEAD(cred_unused);
  40static unsigned long number_cred_unused;
  41
  42#define MAX_HASHTABLE_BITS (14)
  43static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp)
  44{
  45        unsigned long num;
  46        unsigned int nbits;
  47        int ret;
  48
  49        if (!val)
  50                goto out_inval;
  51        ret = strict_strtoul(val, 0, &num);
  52        if (ret == -EINVAL)
  53                goto out_inval;
  54        nbits = fls(num);
  55        if (num > (1U << nbits))
  56                nbits++;
  57        if (nbits > MAX_HASHTABLE_BITS || nbits < 2)
  58                goto out_inval;
  59        *(unsigned int *)kp->arg = nbits;
  60        return 0;
  61out_inval:
  62        return -EINVAL;
  63}
  64
  65static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp)
  66{
  67        unsigned int nbits;
  68
  69        nbits = *(unsigned int *)kp->arg;
  70        return sprintf(buffer, "%u", 1U << nbits);
  71}
  72
  73#define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int);
  74
  75static struct kernel_param_ops param_ops_hashtbl_sz = {
  76        .set = param_set_hashtbl_sz,
  77        .get = param_get_hashtbl_sz,
  78};
  79
  80module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
  81MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
  82
  83static u32
  84pseudoflavor_to_flavor(u32 flavor) {
  85        if (flavor >= RPC_AUTH_MAXFLAVOR)
  86                return RPC_AUTH_GSS;
  87        return flavor;
  88}
  89
  90int
  91rpcauth_register(const struct rpc_authops *ops)
  92{
  93        rpc_authflavor_t flavor;
  94        int ret = -EPERM;
  95
  96        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
  97                return -EINVAL;
  98        spin_lock(&rpc_authflavor_lock);
  99        if (auth_flavors[flavor] == NULL) {
 100                auth_flavors[flavor] = ops;
 101                ret = 0;
 102        }
 103        spin_unlock(&rpc_authflavor_lock);
 104        return ret;
 105}
 106EXPORT_SYMBOL_GPL(rpcauth_register);
 107
 108int
 109rpcauth_unregister(const struct rpc_authops *ops)
 110{
 111        rpc_authflavor_t flavor;
 112        int ret = -EPERM;
 113
 114        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
 115                return -EINVAL;
 116        spin_lock(&rpc_authflavor_lock);
 117        if (auth_flavors[flavor] == ops) {
 118                auth_flavors[flavor] = NULL;
 119                ret = 0;
 120        }
 121        spin_unlock(&rpc_authflavor_lock);
 122        return ret;
 123}
 124EXPORT_SYMBOL_GPL(rpcauth_unregister);
 125
 126/**
 127 * rpcauth_list_flavors - discover registered flavors and pseudoflavors
 128 * @array: array to fill in
 129 * @size: size of "array"
 130 *
 131 * Returns the number of array items filled in, or a negative errno.
 132 *
 133 * The returned array is not sorted by any policy.  Callers should not
 134 * rely on the order of the items in the returned array.
 135 */
 136int
 137rpcauth_list_flavors(rpc_authflavor_t *array, int size)
 138{
 139        rpc_authflavor_t flavor;
 140        int result = 0;
 141
 142        spin_lock(&rpc_authflavor_lock);
 143        for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) {
 144                const struct rpc_authops *ops = auth_flavors[flavor];
 145                rpc_authflavor_t pseudos[4];
 146                int i, len;
 147
 148                if (result >= size) {
 149                        result = -ENOMEM;
 150                        break;
 151                }
 152
 153                if (ops == NULL)
 154                        continue;
 155                if (ops->list_pseudoflavors == NULL) {
 156                        array[result++] = ops->au_flavor;
 157                        continue;
 158                }
 159                len = ops->list_pseudoflavors(pseudos, ARRAY_SIZE(pseudos));
 160                if (len < 0) {
 161                        result = len;
 162                        break;
 163                }
 164                for (i = 0; i < len; i++) {
 165                        if (result >= size) {
 166                                result = -ENOMEM;
 167                                break;
 168                        }
 169                        array[result++] = pseudos[i];
 170                }
 171        }
 172        spin_unlock(&rpc_authflavor_lock);
 173
 174        dprintk("RPC:       %s returns %d\n", __func__, result);
 175        return result;
 176}
 177EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
 178
 179struct rpc_auth *
 180rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
 181{
 182        struct rpc_auth         *auth;
 183        const struct rpc_authops *ops;
 184        u32                     flavor = pseudoflavor_to_flavor(pseudoflavor);
 185
 186        auth = ERR_PTR(-EINVAL);
 187        if (flavor >= RPC_AUTH_MAXFLAVOR)
 188                goto out;
 189
 190        if ((ops = auth_flavors[flavor]) == NULL)
 191                request_module("rpc-auth-%u", flavor);
 192        spin_lock(&rpc_authflavor_lock);
 193        ops = auth_flavors[flavor];
 194        if (ops == NULL || !try_module_get(ops->owner)) {
 195                spin_unlock(&rpc_authflavor_lock);
 196                goto out;
 197        }
 198        spin_unlock(&rpc_authflavor_lock);
 199        auth = ops->create(clnt, pseudoflavor);
 200        module_put(ops->owner);
 201        if (IS_ERR(auth))
 202                return auth;
 203        if (clnt->cl_auth)
 204                rpcauth_release(clnt->cl_auth);
 205        clnt->cl_auth = auth;
 206
 207out:
 208        return auth;
 209}
 210EXPORT_SYMBOL_GPL(rpcauth_create);
 211
 212void
 213rpcauth_release(struct rpc_auth *auth)
 214{
 215        if (!atomic_dec_and_test(&auth->au_count))
 216                return;
 217        auth->au_ops->destroy(auth);
 218}
 219
 220static DEFINE_SPINLOCK(rpc_credcache_lock);
 221
 222static void
 223rpcauth_unhash_cred_locked(struct rpc_cred *cred)
 224{
 225        hlist_del_rcu(&cred->cr_hash);
 226        smp_mb__before_clear_bit();
 227        clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
 228}
 229
 230static int
 231rpcauth_unhash_cred(struct rpc_cred *cred)
 232{
 233        spinlock_t *cache_lock;
 234        int ret;
 235
 236        cache_lock = &cred->cr_auth->au_credcache->lock;
 237        spin_lock(cache_lock);
 238        ret = atomic_read(&cred->cr_count) == 0;
 239        if (ret)
 240                rpcauth_unhash_cred_locked(cred);
 241        spin_unlock(cache_lock);
 242        return ret;
 243}
 244
 245/*
 246 * Initialize RPC credential cache
 247 */
 248int
 249rpcauth_init_credcache(struct rpc_auth *auth)
 250{
 251        struct rpc_cred_cache *new;
 252        unsigned int hashsize;
 253
 254        new = kmalloc(sizeof(*new), GFP_KERNEL);
 255        if (!new)
 256                goto out_nocache;
 257        new->hashbits = auth_hashbits;
 258        hashsize = 1U << new->hashbits;
 259        new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL);
 260        if (!new->hashtable)
 261                goto out_nohashtbl;
 262        spin_lock_init(&new->lock);
 263        auth->au_credcache = new;
 264        return 0;
 265out_nohashtbl:
 266        kfree(new);
 267out_nocache:
 268        return -ENOMEM;
 269}
 270EXPORT_SYMBOL_GPL(rpcauth_init_credcache);
 271
 272/*
 273 * Destroy a list of credentials
 274 */
 275static inline
 276void rpcauth_destroy_credlist(struct list_head *head)
 277{
 278        struct rpc_cred *cred;
 279
 280        while (!list_empty(head)) {
 281                cred = list_entry(head->next, struct rpc_cred, cr_lru);
 282                list_del_init(&cred->cr_lru);
 283                put_rpccred(cred);
 284        }
 285}
 286
 287/*
 288 * Clear the RPC credential cache, and delete those credentials
 289 * that are not referenced.
 290 */
 291void
 292rpcauth_clear_credcache(struct rpc_cred_cache *cache)
 293{
 294        LIST_HEAD(free);
 295        struct hlist_head *head;
 296        struct rpc_cred *cred;
 297        unsigned int hashsize = 1U << cache->hashbits;
 298        int             i;
 299
 300        spin_lock(&rpc_credcache_lock);
 301        spin_lock(&cache->lock);
 302        for (i = 0; i < hashsize; i++) {
 303                head = &cache->hashtable[i];
 304                while (!hlist_empty(head)) {
 305                        cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
 306                        get_rpccred(cred);
 307                        if (!list_empty(&cred->cr_lru)) {
 308                                list_del(&cred->cr_lru);
 309                                number_cred_unused--;
 310                        }
 311                        list_add_tail(&cred->cr_lru, &free);
 312                        rpcauth_unhash_cred_locked(cred);
 313                }
 314        }
 315        spin_unlock(&cache->lock);
 316        spin_unlock(&rpc_credcache_lock);
 317        rpcauth_destroy_credlist(&free);
 318}
 319
 320/*
 321 * Destroy the RPC credential cache
 322 */
 323void
 324rpcauth_destroy_credcache(struct rpc_auth *auth)
 325{
 326        struct rpc_cred_cache *cache = auth->au_credcache;
 327
 328        if (cache) {
 329                auth->au_credcache = NULL;
 330                rpcauth_clear_credcache(cache);
 331                kfree(cache->hashtable);
 332                kfree(cache);
 333        }
 334}
 335EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache);
 336
 337
 338#define RPC_AUTH_EXPIRY_MORATORIUM (60 * HZ)
 339
 340/*
 341 * Remove stale credentials. Avoid sleeping inside the loop.
 342 */
 343static int
 344rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
 345{
 346        spinlock_t *cache_lock;
 347        struct rpc_cred *cred, *next;
 348        unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM;
 349
 350        list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {
 351
 352                if (nr_to_scan-- == 0)
 353                        break;
 354                /*
 355                 * Enforce a 60 second garbage collection moratorium
 356                 * Note that the cred_unused list must be time-ordered.
 357                 */
 358                if (time_in_range(cred->cr_expire, expired, jiffies) &&
 359                    test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
 360                        return 0;
 361
 362                list_del_init(&cred->cr_lru);
 363                number_cred_unused--;
 364                if (atomic_read(&cred->cr_count) != 0)
 365                        continue;
 366
 367                cache_lock = &cred->cr_auth->au_credcache->lock;
 368                spin_lock(cache_lock);
 369                if (atomic_read(&cred->cr_count) == 0) {
 370                        get_rpccred(cred);
 371                        list_add_tail(&cred->cr_lru, free);
 372                        rpcauth_unhash_cred_locked(cred);
 373                }
 374                spin_unlock(cache_lock);
 375        }
 376        return (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
 377}
 378
 379/*
 380 * Run memory cache shrinker.
 381 */
 382static int
 383rpcauth_cache_shrinker(struct shrinker *shrink, struct shrink_control *sc)
 384{
 385        LIST_HEAD(free);
 386        int res;
 387        int nr_to_scan = sc->nr_to_scan;
 388        gfp_t gfp_mask = sc->gfp_mask;
 389
 390        if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
 391                return (nr_to_scan == 0) ? 0 : -1;
 392        if (list_empty(&cred_unused))
 393                return 0;
 394        spin_lock(&rpc_credcache_lock);
 395        res = rpcauth_prune_expired(&free, nr_to_scan);
 396        spin_unlock(&rpc_credcache_lock);
 397        rpcauth_destroy_credlist(&free);
 398        return res;
 399}
 400
 401/*
 402 * Look up a process' credentials in the authentication cache
 403 */
 404struct rpc_cred *
 405rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
 406                int flags)
 407{
 408        LIST_HEAD(free);
 409        struct rpc_cred_cache *cache = auth->au_credcache;
 410        struct hlist_node *pos;
 411        struct rpc_cred *cred = NULL,
 412                        *entry, *new;
 413        unsigned int nr;
 414
 415        nr = hash_long(acred->uid, cache->hashbits);
 416
 417        rcu_read_lock();
 418        hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
 419                if (!entry->cr_ops->crmatch(acred, entry, flags))
 420                        continue;
 421                spin_lock(&cache->lock);
 422                if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
 423                        spin_unlock(&cache->lock);
 424                        continue;
 425                }
 426                cred = get_rpccred(entry);
 427                spin_unlock(&cache->lock);
 428                break;
 429        }
 430        rcu_read_unlock();
 431
 432        if (cred != NULL)
 433                goto found;
 434
 435        new = auth->au_ops->crcreate(auth, acred, flags);
 436        if (IS_ERR(new)) {
 437                cred = new;
 438                goto out;
 439        }
 440
 441        spin_lock(&cache->lock);
 442        hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
 443                if (!entry->cr_ops->crmatch(acred, entry, flags))
 444                        continue;
 445                cred = get_rpccred(entry);
 446                break;
 447        }
 448        if (cred == NULL) {
 449                cred = new;
 450                set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
 451                hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
 452        } else
 453                list_add_tail(&new->cr_lru, &free);
 454        spin_unlock(&cache->lock);
 455found:
 456        if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
 457            cred->cr_ops->cr_init != NULL &&
 458            !(flags & RPCAUTH_LOOKUP_NEW)) {
 459                int res = cred->cr_ops->cr_init(auth, cred);
 460                if (res < 0) {
 461                        put_rpccred(cred);
 462                        cred = ERR_PTR(res);
 463                }
 464        }
 465        rpcauth_destroy_credlist(&free);
 466out:
 467        return cred;
 468}
 469EXPORT_SYMBOL_GPL(rpcauth_lookup_credcache);
 470
 471struct rpc_cred *
 472rpcauth_lookupcred(struct rpc_auth *auth, int flags)
 473{
 474        struct auth_cred acred;
 475        struct rpc_cred *ret;
 476        const struct cred *cred = current_cred();
 477
 478        dprintk("RPC:       looking up %s cred\n",
 479                auth->au_ops->au_name);
 480
 481        memset(&acred, 0, sizeof(acred));
 482        acred.uid = cred->fsuid;
 483        acred.gid = cred->fsgid;
 484        acred.group_info = get_group_info(((struct cred *)cred)->group_info);
 485
 486        ret = auth->au_ops->lookup_cred(auth, &acred, flags);
 487        put_group_info(acred.group_info);
 488        return ret;
 489}
 490
 491void
 492rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
 493                  struct rpc_auth *auth, const struct rpc_credops *ops)
 494{
 495        INIT_HLIST_NODE(&cred->cr_hash);
 496        INIT_LIST_HEAD(&cred->cr_lru);
 497        atomic_set(&cred->cr_count, 1);
 498        cred->cr_auth = auth;
 499        cred->cr_ops = ops;
 500        cred->cr_expire = jiffies;
 501#ifdef RPC_DEBUG
 502        cred->cr_magic = RPCAUTH_CRED_MAGIC;
 503#endif
 504        cred->cr_uid = acred->uid;
 505}
 506EXPORT_SYMBOL_GPL(rpcauth_init_cred);
 507
 508struct rpc_cred *
 509rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags)
 510{
 511        dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
 512                        cred->cr_auth->au_ops->au_name, cred);
 513        return get_rpccred(cred);
 514}
 515EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
 516
 517static struct rpc_cred *
 518rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags)
 519{
 520        struct rpc_auth *auth = task->tk_client->cl_auth;
 521        struct auth_cred acred = {
 522                .uid = 0,
 523                .gid = 0,
 524        };
 525
 526        dprintk("RPC: %5u looking up %s cred\n",
 527                task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
 528        return auth->au_ops->lookup_cred(auth, &acred, lookupflags);
 529}
 530
 531static struct rpc_cred *
 532rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags)
 533{
 534        struct rpc_auth *auth = task->tk_client->cl_auth;
 535
 536        dprintk("RPC: %5u looking up %s cred\n",
 537                task->tk_pid, auth->au_ops->au_name);
 538        return rpcauth_lookupcred(auth, lookupflags);
 539}
 540
 541static int
 542rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags)
 543{
 544        struct rpc_rqst *req = task->tk_rqstp;
 545        struct rpc_cred *new;
 546        int lookupflags = 0;
 547
 548        if (flags & RPC_TASK_ASYNC)
 549                lookupflags |= RPCAUTH_LOOKUP_NEW;
 550        if (cred != NULL)
 551                new = cred->cr_ops->crbind(task, cred, lookupflags);
 552        else if (flags & RPC_TASK_ROOTCREDS)
 553                new = rpcauth_bind_root_cred(task, lookupflags);
 554        else
 555                new = rpcauth_bind_new_cred(task, lookupflags);
 556        if (IS_ERR(new))
 557                return PTR_ERR(new);
 558        if (req->rq_cred != NULL)
 559                put_rpccred(req->rq_cred);
 560        req->rq_cred = new;
 561        return 0;
 562}
 563
 564void
 565put_rpccred(struct rpc_cred *cred)
 566{
 567        /* Fast path for unhashed credentials */
 568        if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
 569                if (atomic_dec_and_test(&cred->cr_count))
 570                        cred->cr_ops->crdestroy(cred);
 571                return;
 572        }
 573
 574        if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
 575                return;
 576        if (!list_empty(&cred->cr_lru)) {
 577                number_cred_unused--;
 578                list_del_init(&cred->cr_lru);
 579        }
 580        if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
 581                if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
 582                        cred->cr_expire = jiffies;
 583                        list_add_tail(&cred->cr_lru, &cred_unused);
 584                        number_cred_unused++;
 585                        goto out_nodestroy;
 586                }
 587                if (!rpcauth_unhash_cred(cred)) {
 588                        /* We were hashed and someone looked us up... */
 589                        goto out_nodestroy;
 590                }
 591        }
 592        spin_unlock(&rpc_credcache_lock);
 593        cred->cr_ops->crdestroy(cred);
 594        return;
 595out_nodestroy:
 596        spin_unlock(&rpc_credcache_lock);
 597}
 598EXPORT_SYMBOL_GPL(put_rpccred);
 599
 600__be32 *
 601rpcauth_marshcred(struct rpc_task *task, __be32 *p)
 602{
 603        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 604
 605        dprintk("RPC: %5u marshaling %s cred %p\n",
 606                task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 607
 608        return cred->cr_ops->crmarshal(task, p);
 609}
 610
 611__be32 *
 612rpcauth_checkverf(struct rpc_task *task, __be32 *p)
 613{
 614        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 615
 616        dprintk("RPC: %5u validating %s cred %p\n",
 617                task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 618
 619        return cred->cr_ops->crvalidate(task, p);
 620}
 621
 622static void rpcauth_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp,
 623                                   __be32 *data, void *obj)
 624{
 625        struct xdr_stream xdr;
 626
 627        xdr_init_encode(&xdr, &rqstp->rq_snd_buf, data);
 628        encode(rqstp, &xdr, obj);
 629}
 630
 631int
 632rpcauth_wrap_req(struct rpc_task *task, kxdreproc_t encode, void *rqstp,
 633                __be32 *data, void *obj)
 634{
 635        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 636
 637        dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
 638                        task->tk_pid, cred->cr_ops->cr_name, cred);
 639        if (cred->cr_ops->crwrap_req)
 640                return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
 641        /* By default, we encode the arguments normally. */
 642        rpcauth_wrap_req_encode(encode, rqstp, data, obj);
 643        return 0;
 644}
 645
 646static int
 647rpcauth_unwrap_req_decode(kxdrdproc_t decode, struct rpc_rqst *rqstp,
 648                          __be32 *data, void *obj)
 649{
 650        struct xdr_stream xdr;
 651
 652        xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, data);
 653        return decode(rqstp, &xdr, obj);
 654}
 655
 656int
 657rpcauth_unwrap_resp(struct rpc_task *task, kxdrdproc_t decode, void *rqstp,
 658                __be32 *data, void *obj)
 659{
 660        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 661
 662        dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
 663                        task->tk_pid, cred->cr_ops->cr_name, cred);
 664        if (cred->cr_ops->crunwrap_resp)
 665                return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
 666                                                   data, obj);
 667        /* By default, we decode the arguments normally. */
 668        return rpcauth_unwrap_req_decode(decode, rqstp, data, obj);
 669}
 670
 671int
 672rpcauth_refreshcred(struct rpc_task *task)
 673{
 674        struct rpc_cred *cred;
 675        int err;
 676
 677        cred = task->tk_rqstp->rq_cred;
 678        if (cred == NULL) {
 679                err = rpcauth_bindcred(task, task->tk_msg.rpc_cred, task->tk_flags);
 680                if (err < 0)
 681                        goto out;
 682                cred = task->tk_rqstp->rq_cred;
 683        }
 684        dprintk("RPC: %5u refreshing %s cred %p\n",
 685                task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 686
 687        err = cred->cr_ops->crrefresh(task);
 688out:
 689        if (err < 0)
 690                task->tk_status = err;
 691        return err;
 692}
 693
 694void
 695rpcauth_invalcred(struct rpc_task *task)
 696{
 697        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 698
 699        dprintk("RPC: %5u invalidating %s cred %p\n",
 700                task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
 701        if (cred)
 702                clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
 703}
 704
 705int
 706rpcauth_uptodatecred(struct rpc_task *task)
 707{
 708        struct rpc_cred *cred = task->tk_rqstp->rq_cred;
 709
 710        return cred == NULL ||
 711                test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
 712}
 713
 714static struct shrinker rpc_cred_shrinker = {
 715        .shrink = rpcauth_cache_shrinker,
 716        .seeks = DEFAULT_SEEKS,
 717};
 718
 719int __init rpcauth_init_module(void)
 720{
 721        int err;
 722
 723        err = rpc_init_authunix();
 724        if (err < 0)
 725                goto out1;
 726        err = rpc_init_generic_auth();
 727        if (err < 0)
 728                goto out2;
 729        register_shrinker(&rpc_cred_shrinker);
 730        return 0;
 731out2:
 732        rpc_destroy_authunix();
 733out1:
 734        return err;
 735}
 736
 737void rpcauth_remove_module(void)
 738{
 739        rpc_destroy_authunix();
 740        rpc_destroy_generic_auth();
 741        unregister_shrinker(&rpc_cred_shrinker);
 742}
 743
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.