2 * linux/net/sunrpc/auth.c
4 * Generic RPC client authentication API.
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
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/sunrpc/clnt.h>
15 #include <linux/spinlock.h>
18 # define RPCDBG_FACILITY RPCDBG_AUTH
21 static DEFINE_SPINLOCK(rpc_authflavor_lock
);
22 static const struct rpc_authops
*auth_flavors
[RPC_AUTH_MAXFLAVOR
] = {
23 &authnull_ops
, /* AUTH_NULL */
24 &authunix_ops
, /* AUTH_UNIX */
25 NULL
, /* others can be loadable modules */
28 static LIST_HEAD(cred_unused
);
29 static unsigned long number_cred_unused
;
32 pseudoflavor_to_flavor(u32 flavor
) {
33 if (flavor
>= RPC_AUTH_MAXFLAVOR
)
39 rpcauth_register(const struct rpc_authops
*ops
)
41 rpc_authflavor_t flavor
;
44 if ((flavor
= ops
->au_flavor
) >= RPC_AUTH_MAXFLAVOR
)
46 spin_lock(&rpc_authflavor_lock
);
47 if (auth_flavors
[flavor
] == NULL
) {
48 auth_flavors
[flavor
] = ops
;
51 spin_unlock(&rpc_authflavor_lock
);
56 rpcauth_unregister(const struct rpc_authops
*ops
)
58 rpc_authflavor_t flavor
;
61 if ((flavor
= ops
->au_flavor
) >= RPC_AUTH_MAXFLAVOR
)
63 spin_lock(&rpc_authflavor_lock
);
64 if (auth_flavors
[flavor
] == ops
) {
65 auth_flavors
[flavor
] = NULL
;
68 spin_unlock(&rpc_authflavor_lock
);
73 rpcauth_create(rpc_authflavor_t pseudoflavor
, struct rpc_clnt
*clnt
)
75 struct rpc_auth
*auth
;
76 const struct rpc_authops
*ops
;
77 u32 flavor
= pseudoflavor_to_flavor(pseudoflavor
);
79 auth
= ERR_PTR(-EINVAL
);
80 if (flavor
>= RPC_AUTH_MAXFLAVOR
)
84 if ((ops
= auth_flavors
[flavor
]) == NULL
)
85 request_module("rpc-auth-%u", flavor
);
87 spin_lock(&rpc_authflavor_lock
);
88 ops
= auth_flavors
[flavor
];
89 if (ops
== NULL
|| !try_module_get(ops
->owner
)) {
90 spin_unlock(&rpc_authflavor_lock
);
93 spin_unlock(&rpc_authflavor_lock
);
94 auth
= ops
->create(clnt
, pseudoflavor
);
95 module_put(ops
->owner
);
99 rpcauth_release(clnt
->cl_auth
);
100 clnt
->cl_auth
= auth
;
107 rpcauth_release(struct rpc_auth
*auth
)
109 if (!atomic_dec_and_test(&auth
->au_count
))
111 auth
->au_ops
->destroy(auth
);
114 static DEFINE_SPINLOCK(rpc_credcache_lock
);
117 rpcauth_unhash_cred_locked(struct rpc_cred
*cred
)
119 hlist_del_rcu(&cred
->cr_hash
);
120 smp_mb__before_clear_bit();
121 clear_bit(RPCAUTH_CRED_HASHED
, &cred
->cr_flags
);
125 rpcauth_unhash_cred(struct rpc_cred
*cred
)
127 spinlock_t
*cache_lock
;
129 cache_lock
= &cred
->cr_auth
->au_credcache
->lock
;
130 spin_lock(cache_lock
);
131 if (atomic_read(&cred
->cr_count
) == 0)
132 rpcauth_unhash_cred_locked(cred
);
133 spin_unlock(cache_lock
);
137 * Initialize RPC credential cache
140 rpcauth_init_credcache(struct rpc_auth
*auth
)
142 struct rpc_cred_cache
*new;
145 new = kmalloc(sizeof(*new), GFP_KERNEL
);
148 for (i
= 0; i
< RPC_CREDCACHE_NR
; i
++)
149 INIT_HLIST_HEAD(&new->hashtable
[i
]);
150 spin_lock_init(&new->lock
);
151 auth
->au_credcache
= new;
156 * Destroy a list of credentials
159 void rpcauth_destroy_credlist(struct list_head
*head
)
161 struct rpc_cred
*cred
;
163 while (!list_empty(head
)) {
164 cred
= list_entry(head
->next
, struct rpc_cred
, cr_lru
);
165 list_del_init(&cred
->cr_lru
);
171 * Clear the RPC credential cache, and delete those credentials
172 * that are not referenced.
175 rpcauth_clear_credcache(struct rpc_cred_cache
*cache
)
178 struct hlist_head
*head
;
179 struct rpc_cred
*cred
;
182 spin_lock(&rpc_credcache_lock
);
183 spin_lock(&cache
->lock
);
184 for (i
= 0; i
< RPC_CREDCACHE_NR
; i
++) {
185 head
= &cache
->hashtable
[i
];
186 while (!hlist_empty(head
)) {
187 cred
= hlist_entry(head
->first
, struct rpc_cred
, cr_hash
);
189 if (!list_empty(&cred
->cr_lru
)) {
190 list_del(&cred
->cr_lru
);
191 number_cred_unused
--;
193 list_add_tail(&cred
->cr_lru
, &free
);
194 rpcauth_unhash_cred_locked(cred
);
197 spin_unlock(&cache
->lock
);
198 spin_unlock(&rpc_credcache_lock
);
199 rpcauth_destroy_credlist(&free
);
203 * Destroy the RPC credential cache
206 rpcauth_destroy_credcache(struct rpc_auth
*auth
)
208 struct rpc_cred_cache
*cache
= auth
->au_credcache
;
211 auth
->au_credcache
= NULL
;
212 rpcauth_clear_credcache(cache
);
218 * Remove stale credentials. Avoid sleeping inside the loop.
221 rpcauth_prune_expired(struct list_head
*free
, int nr_to_scan
)
223 spinlock_t
*cache_lock
;
224 struct rpc_cred
*cred
;
226 while (!list_empty(&cred_unused
)) {
227 cred
= list_entry(cred_unused
.next
, struct rpc_cred
, cr_lru
);
228 list_del_init(&cred
->cr_lru
);
229 number_cred_unused
--;
230 if (atomic_read(&cred
->cr_count
) != 0)
232 cache_lock
= &cred
->cr_auth
->au_credcache
->lock
;
233 spin_lock(cache_lock
);
234 if (atomic_read(&cred
->cr_count
) == 0) {
236 list_add_tail(&cred
->cr_lru
, free
);
237 rpcauth_unhash_cred_locked(cred
);
240 spin_unlock(cache_lock
);
248 * Run memory cache shrinker.
251 rpcauth_cache_shrinker(int nr_to_scan
, gfp_t gfp_mask
)
256 if (list_empty(&cred_unused
))
258 spin_lock(&rpc_credcache_lock
);
259 nr_to_scan
= rpcauth_prune_expired(&free
, nr_to_scan
);
260 res
= (number_cred_unused
/ 100) * sysctl_vfs_cache_pressure
;
261 spin_unlock(&rpc_credcache_lock
);
262 rpcauth_destroy_credlist(&free
);
267 * Look up a process' credentials in the authentication cache
270 rpcauth_lookup_credcache(struct rpc_auth
*auth
, struct auth_cred
* acred
,
274 struct rpc_cred_cache
*cache
= auth
->au_credcache
;
275 struct hlist_node
*pos
;
276 struct rpc_cred
*cred
= NULL
,
280 if (!(flags
& RPCAUTH_LOOKUP_ROOTCREDS
))
281 nr
= acred
->uid
& RPC_CREDCACHE_MASK
;
284 hlist_for_each_entry_rcu(entry
, pos
, &cache
->hashtable
[nr
], cr_hash
) {
285 if (!entry
->cr_ops
->crmatch(acred
, entry
, flags
))
287 spin_lock(&cache
->lock
);
288 if (test_bit(RPCAUTH_CRED_HASHED
, &entry
->cr_flags
) == 0) {
289 spin_unlock(&cache
->lock
);
292 cred
= get_rpccred(entry
);
293 spin_unlock(&cache
->lock
);
301 new = auth
->au_ops
->crcreate(auth
, acred
, flags
);
307 spin_lock(&cache
->lock
);
308 hlist_for_each_entry(entry
, pos
, &cache
->hashtable
[nr
], cr_hash
) {
309 if (!entry
->cr_ops
->crmatch(acred
, entry
, flags
))
311 cred
= get_rpccred(entry
);
316 set_bit(RPCAUTH_CRED_HASHED
, &cred
->cr_flags
);
317 hlist_add_head_rcu(&cred
->cr_hash
, &cache
->hashtable
[nr
]);
319 list_add_tail(&new->cr_lru
, &free
);
320 spin_unlock(&cache
->lock
);
322 if (test_bit(RPCAUTH_CRED_NEW
, &cred
->cr_flags
)
323 && cred
->cr_ops
->cr_init
!= NULL
324 && !(flags
& RPCAUTH_LOOKUP_NEW
)) {
325 int res
= cred
->cr_ops
->cr_init(auth
, cred
);
331 rpcauth_destroy_credlist(&free
);
337 rpcauth_lookupcred(struct rpc_auth
*auth
, int flags
)
339 struct auth_cred acred
= {
340 .uid
= current
->fsuid
,
341 .gid
= current
->fsgid
,
342 .group_info
= current
->group_info
,
344 struct rpc_cred
*ret
;
346 dprintk("RPC: looking up %s cred\n",
347 auth
->au_ops
->au_name
);
348 get_group_info(acred
.group_info
);
349 ret
= auth
->au_ops
->lookup_cred(auth
, &acred
, flags
);
350 put_group_info(acred
.group_info
);
355 rpcauth_init_cred(struct rpc_cred
*cred
, const struct auth_cred
*acred
,
356 struct rpc_auth
*auth
, const struct rpc_credops
*ops
)
358 INIT_HLIST_NODE(&cred
->cr_hash
);
359 INIT_LIST_HEAD(&cred
->cr_lru
);
360 atomic_set(&cred
->cr_count
, 1);
361 cred
->cr_auth
= auth
;
363 cred
->cr_expire
= jiffies
;
365 cred
->cr_magic
= RPCAUTH_CRED_MAGIC
;
367 cred
->cr_uid
= acred
->uid
;
369 EXPORT_SYMBOL(rpcauth_init_cred
);
372 rpcauth_bindcred(struct rpc_task
*task
)
374 struct rpc_auth
*auth
= task
->tk_client
->cl_auth
;
375 struct auth_cred acred
= {
376 .uid
= current
->fsuid
,
377 .gid
= current
->fsgid
,
378 .group_info
= current
->group_info
,
380 struct rpc_cred
*ret
;
383 dprintk("RPC: %5u looking up %s cred\n",
384 task
->tk_pid
, task
->tk_client
->cl_auth
->au_ops
->au_name
);
385 get_group_info(acred
.group_info
);
386 if (task
->tk_flags
& RPC_TASK_ROOTCREDS
)
387 flags
|= RPCAUTH_LOOKUP_ROOTCREDS
;
388 ret
= auth
->au_ops
->lookup_cred(auth
, &acred
, flags
);
390 task
->tk_msg
.rpc_cred
= ret
;
392 task
->tk_status
= PTR_ERR(ret
);
393 put_group_info(acred
.group_info
);
398 rpcauth_holdcred(struct rpc_task
*task
)
400 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
403 dprintk("RPC: %5u holding %s cred %p\n", task
->tk_pid
,
404 cred
->cr_auth
->au_ops
->au_name
, cred
);
409 put_rpccred(struct rpc_cred
*cred
)
411 /* Fast path for unhashed credentials */
412 if (test_bit(RPCAUTH_CRED_HASHED
, &cred
->cr_flags
) != 0)
415 if (!atomic_dec_and_test(&cred
->cr_count
))
419 if (!atomic_dec_and_lock(&cred
->cr_count
, &rpc_credcache_lock
))
421 if (!list_empty(&cred
->cr_lru
)) {
422 number_cred_unused
--;
423 list_del_init(&cred
->cr_lru
);
425 if (test_bit(RPCAUTH_CRED_UPTODATE
, &cred
->cr_flags
) == 0)
426 rpcauth_unhash_cred(cred
);
427 else if (test_bit(RPCAUTH_CRED_HASHED
, &cred
->cr_flags
) != 0) {
428 cred
->cr_expire
= jiffies
;
429 list_add_tail(&cred
->cr_lru
, &cred_unused
);
430 number_cred_unused
++;
431 spin_unlock(&rpc_credcache_lock
);
434 spin_unlock(&rpc_credcache_lock
);
436 cred
->cr_ops
->crdestroy(cred
);
440 rpcauth_unbindcred(struct rpc_task
*task
)
442 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
444 dprintk("RPC: %5u releasing %s cred %p\n",
445 task
->tk_pid
, cred
->cr_auth
->au_ops
->au_name
, cred
);
448 task
->tk_msg
.rpc_cred
= NULL
;
452 rpcauth_marshcred(struct rpc_task
*task
, __be32
*p
)
454 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
456 dprintk("RPC: %5u marshaling %s cred %p\n",
457 task
->tk_pid
, cred
->cr_auth
->au_ops
->au_name
, cred
);
459 return cred
->cr_ops
->crmarshal(task
, p
);
463 rpcauth_checkverf(struct rpc_task
*task
, __be32
*p
)
465 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
467 dprintk("RPC: %5u validating %s cred %p\n",
468 task
->tk_pid
, cred
->cr_auth
->au_ops
->au_name
, cred
);
470 return cred
->cr_ops
->crvalidate(task
, p
);
474 rpcauth_wrap_req(struct rpc_task
*task
, kxdrproc_t encode
, void *rqstp
,
475 __be32
*data
, void *obj
)
477 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
479 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
480 task
->tk_pid
, cred
->cr_ops
->cr_name
, cred
);
481 if (cred
->cr_ops
->crwrap_req
)
482 return cred
->cr_ops
->crwrap_req(task
, encode
, rqstp
, data
, obj
);
483 /* By default, we encode the arguments normally. */
484 return rpc_call_xdrproc(encode
, rqstp
, data
, obj
);
488 rpcauth_unwrap_resp(struct rpc_task
*task
, kxdrproc_t decode
, void *rqstp
,
489 __be32
*data
, void *obj
)
491 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
493 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
494 task
->tk_pid
, cred
->cr_ops
->cr_name
, cred
);
495 if (cred
->cr_ops
->crunwrap_resp
)
496 return cred
->cr_ops
->crunwrap_resp(task
, decode
, rqstp
,
498 /* By default, we decode the arguments normally. */
499 return rpc_call_xdrproc(decode
, rqstp
, data
, obj
);
503 rpcauth_refreshcred(struct rpc_task
*task
)
505 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
508 dprintk("RPC: %5u refreshing %s cred %p\n",
509 task
->tk_pid
, cred
->cr_auth
->au_ops
->au_name
, cred
);
511 err
= cred
->cr_ops
->crrefresh(task
);
513 task
->tk_status
= err
;
518 rpcauth_invalcred(struct rpc_task
*task
)
520 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
522 dprintk("RPC: %5u invalidating %s cred %p\n",
523 task
->tk_pid
, cred
->cr_auth
->au_ops
->au_name
, cred
);
525 clear_bit(RPCAUTH_CRED_UPTODATE
, &cred
->cr_flags
);
529 rpcauth_uptodatecred(struct rpc_task
*task
)
531 struct rpc_cred
*cred
= task
->tk_msg
.rpc_cred
;
533 return cred
== NULL
||
534 test_bit(RPCAUTH_CRED_UPTODATE
, &cred
->cr_flags
) != 0;
537 static struct shrinker rpc_cred_shrinker
= {
538 .shrink
= rpcauth_cache_shrinker
,
539 .seeks
= DEFAULT_SEEKS
,
542 void __init
rpcauth_init_module(void)
545 register_shrinker(&rpc_cred_shrinker
);
548 void __exit
rpcauth_remove_module(void)
550 unregister_shrinker(&rpc_cred_shrinker
);