aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/idmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/idmap.c')
-rw-r--r--fs/nfs/idmap.c733
1 files changed, 344 insertions, 389 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 2c05f1991e1e..a701a83047d3 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -34,11 +34,29 @@
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */ 35 */
36#include <linux/types.h> 36#include <linux/types.h>
37#include <linux/string.h> 37#include <linux/parser.h>
38#include <linux/kernel.h> 38#include <linux/fs.h>
39#include <linux/slab.h>
40#include <linux/nfs_idmap.h> 39#include <linux/nfs_idmap.h>
40#include <net/net_namespace.h>
41#include <linux/sunrpc/rpc_pipe_fs.h>
41#include <linux/nfs_fs.h> 42#include <linux/nfs_fs.h>
43#include <linux/nfs_fs_sb.h>
44#include <linux/key.h>
45#include <linux/keyctl.h>
46#include <linux/key-type.h>
47#include <keys/user-type.h>
48#include <linux/module.h>
49
50#include "internal.h"
51#include "netns.h"
52
53#define NFS_UINT_MAXLEN 11
54
55/* Default cache timeout is 10 minutes */
56unsigned int nfs_idmap_cache_timeout = 600;
57static const struct cred *id_resolver_cache;
58static struct key_type key_type_id_resolver_legacy;
59
42 60
43/** 61/**
44 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields 62 * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields
@@ -142,24 +160,7 @@ static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
142 return snprintf(buf, buflen, "%u", id); 160 return snprintf(buf, buflen, "%u", id);
143} 161}
144 162
145#ifdef CONFIG_NFS_USE_NEW_IDMAPPER 163static struct key_type key_type_id_resolver = {
146
147#include <linux/cred.h>
148#include <linux/sunrpc/sched.h>
149#include <linux/nfs4.h>
150#include <linux/nfs_fs_sb.h>
151#include <linux/keyctl.h>
152#include <linux/key-type.h>
153#include <linux/rcupdate.h>
154#include <linux/err.h>
155
156#include <keys/user-type.h>
157
158#define NFS_UINT_MAXLEN 11
159
160const struct cred *id_resolver_cache;
161
162struct key_type key_type_id_resolver = {
163 .name = "id_resolver", 164 .name = "id_resolver",
164 .instantiate = user_instantiate, 165 .instantiate = user_instantiate,
165 .match = user_match, 166 .match = user_match,
@@ -169,13 +170,14 @@ struct key_type key_type_id_resolver = {
169 .read = user_read, 170 .read = user_read,
170}; 171};
171 172
172int nfs_idmap_init(void) 173static int nfs_idmap_init_keyring(void)
173{ 174{
174 struct cred *cred; 175 struct cred *cred;
175 struct key *keyring; 176 struct key *keyring;
176 int ret = 0; 177 int ret = 0;
177 178
178 printk(KERN_NOTICE "Registering the %s key type\n", key_type_id_resolver.name); 179 printk(KERN_NOTICE "NFS: Registering the %s key type\n",
180 key_type_id_resolver.name);
179 181
180 cred = prepare_kernel_cred(NULL); 182 cred = prepare_kernel_cred(NULL);
181 if (!cred) 183 if (!cred)
@@ -210,7 +212,7 @@ failed_put_cred:
210 return ret; 212 return ret;
211} 213}
212 214
213void nfs_idmap_quit(void) 215static void nfs_idmap_quit_keyring(void)
214{ 216{
215 key_revoke(id_resolver_cache->thread_keyring); 217 key_revoke(id_resolver_cache->thread_keyring);
216 unregister_key_type(&key_type_id_resolver); 218 unregister_key_type(&key_type_id_resolver);
@@ -245,8 +247,10 @@ static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
245 return desclen; 247 return desclen;
246} 248}
247 249
248static ssize_t nfs_idmap_request_key(const char *name, size_t namelen, 250static ssize_t nfs_idmap_request_key(struct key_type *key_type,
249 const char *type, void *data, size_t data_size) 251 const char *name, size_t namelen,
252 const char *type, void *data,
253 size_t data_size, struct idmap *idmap)
250{ 254{
251 const struct cred *saved_cred; 255 const struct cred *saved_cred;
252 struct key *rkey; 256 struct key *rkey;
@@ -259,8 +263,12 @@ static ssize_t nfs_idmap_request_key(const char *name, size_t namelen,
259 goto out; 263 goto out;
260 264
261 saved_cred = override_creds(id_resolver_cache); 265 saved_cred = override_creds(id_resolver_cache);
262 rkey = request_key(&key_type_id_resolver, desc, ""); 266 if (idmap)
267 rkey = request_key_with_auxdata(key_type, desc, "", 0, idmap);
268 else
269 rkey = request_key(&key_type_id_resolver, desc, "");
263 revert_creds(saved_cred); 270 revert_creds(saved_cred);
271
264 kfree(desc); 272 kfree(desc);
265 if (IS_ERR(rkey)) { 273 if (IS_ERR(rkey)) {
266 ret = PTR_ERR(rkey); 274 ret = PTR_ERR(rkey);
@@ -293,31 +301,46 @@ out:
293 return ret; 301 return ret;
294} 302}
295 303
304static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
305 const char *type, void *data,
306 size_t data_size, struct idmap *idmap)
307{
308 ssize_t ret = nfs_idmap_request_key(&key_type_id_resolver,
309 name, namelen, type, data,
310 data_size, NULL);
311 if (ret < 0) {
312 ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,
313 name, namelen, type, data,
314 data_size, idmap);
315 }
316 return ret;
317}
296 318
297/* ID -> Name */ 319/* ID -> Name */
298static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, size_t buflen) 320static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
321 size_t buflen, struct idmap *idmap)
299{ 322{
300 char id_str[NFS_UINT_MAXLEN]; 323 char id_str[NFS_UINT_MAXLEN];
301 int id_len; 324 int id_len;
302 ssize_t ret; 325 ssize_t ret;
303 326
304 id_len = snprintf(id_str, sizeof(id_str), "%u", id); 327 id_len = snprintf(id_str, sizeof(id_str), "%u", id);
305 ret = nfs_idmap_request_key(id_str, id_len, type, buf, buflen); 328 ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
306 if (ret < 0) 329 if (ret < 0)
307 return -EINVAL; 330 return -EINVAL;
308 return ret; 331 return ret;
309} 332}
310 333
311/* Name -> ID */ 334/* Name -> ID */
312static int nfs_idmap_lookup_id(const char *name, size_t namelen, 335static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *type,
313 const char *type, __u32 *id) 336 __u32 *id, struct idmap *idmap)
314{ 337{
315 char id_str[NFS_UINT_MAXLEN]; 338 char id_str[NFS_UINT_MAXLEN];
316 long id_long; 339 long id_long;
317 ssize_t data_size; 340 ssize_t data_size;
318 int ret = 0; 341 int ret = 0;
319 342
320 data_size = nfs_idmap_request_key(name, namelen, type, id_str, NFS_UINT_MAXLEN); 343 data_size = nfs_idmap_get_key(name, namelen, type, id_str, NFS_UINT_MAXLEN, idmap);
321 if (data_size <= 0) { 344 if (data_size <= 0) {
322 ret = -EINVAL; 345 ret = -EINVAL;
323 } else { 346 } else {
@@ -327,114 +350,103 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen,
327 return ret; 350 return ret;
328} 351}
329 352
330int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) 353/* idmap classic begins here */
331{ 354module_param(nfs_idmap_cache_timeout, int, 0644);
332 if (nfs_map_string_to_numeric(name, namelen, uid))
333 return 0;
334 return nfs_idmap_lookup_id(name, namelen, "uid", uid);
335}
336
337int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid)
338{
339 if (nfs_map_string_to_numeric(name, namelen, gid))
340 return 0;
341 return nfs_idmap_lookup_id(name, namelen, "gid", gid);
342}
343
344int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
345{
346 int ret = -EINVAL;
347
348 if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
349 ret = nfs_idmap_lookup_name(uid, "user", buf, buflen);
350 if (ret < 0)
351 ret = nfs_map_numeric_to_string(uid, buf, buflen);
352 return ret;
353}
354int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
355{
356 int ret = -EINVAL;
357 355
358 if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) 356struct idmap {
359 ret = nfs_idmap_lookup_name(gid, "group", buf, buflen); 357 struct rpc_pipe *idmap_pipe;
360 if (ret < 0) 358 struct key_construction *idmap_key_cons;
361 ret = nfs_map_numeric_to_string(gid, buf, buflen);
362 return ret;
363}
364
365#else /* CONFIG_NFS_USE_NEW_IDMAPPER not defined */
366
367#include <linux/module.h>
368#include <linux/mutex.h>
369#include <linux/init.h>
370#include <linux/socket.h>
371#include <linux/in.h>
372#include <linux/sched.h>
373#include <linux/sunrpc/clnt.h>
374#include <linux/workqueue.h>
375#include <linux/sunrpc/rpc_pipe_fs.h>
376
377#include <linux/nfs_fs.h>
378
379#include "nfs4_fs.h"
380
381#define IDMAP_HASH_SZ 128
382
383/* Default cache timeout is 10 minutes */
384unsigned int nfs_idmap_cache_timeout = 600 * HZ;
385
386static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
387{
388 char *endp;
389 int num = simple_strtol(val, &endp, 0);
390 int jif = num * HZ;
391 if (endp == val || *endp || num < 0 || jif < num)
392 return -EINVAL;
393 *((int *)kp->arg) = jif;
394 return 0;
395}
396
397module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
398 &nfs_idmap_cache_timeout, 0644);
399
400struct idmap_hashent {
401 unsigned long ih_expires;
402 __u32 ih_id;
403 size_t ih_namelen;
404 char ih_name[IDMAP_NAMESZ];
405}; 359};
406 360
407struct idmap_hashtable { 361enum {
408 __u8 h_type; 362 Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err
409 struct idmap_hashent h_entries[IDMAP_HASH_SZ];
410}; 363};
411 364
412struct idmap { 365static const match_table_t nfs_idmap_tokens = {
413 struct dentry *idmap_dentry; 366 { Opt_find_uid, "uid:%s" },
414 wait_queue_head_t idmap_wq; 367 { Opt_find_gid, "gid:%s" },
415 struct idmap_msg idmap_im; 368 { Opt_find_user, "user:%s" },
416 struct mutex idmap_lock; /* Serializes upcalls */ 369 { Opt_find_group, "group:%s" },
417 struct mutex idmap_im_lock; /* Protects the hashtable */ 370 { Opt_find_err, NULL }
418 struct idmap_hashtable idmap_user_hash;
419 struct idmap_hashtable idmap_group_hash;
420}; 371};
421 372
373static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);
422static ssize_t idmap_pipe_downcall(struct file *, const char __user *, 374static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
423 size_t); 375 size_t);
424static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); 376static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);
425 377
426static unsigned int fnvhash32(const void *, size_t);
427
428static const struct rpc_pipe_ops idmap_upcall_ops = { 378static const struct rpc_pipe_ops idmap_upcall_ops = {
429 .upcall = rpc_pipe_generic_upcall, 379 .upcall = rpc_pipe_generic_upcall,
430 .downcall = idmap_pipe_downcall, 380 .downcall = idmap_pipe_downcall,
431 .destroy_msg = idmap_pipe_destroy_msg, 381 .destroy_msg = idmap_pipe_destroy_msg,
432}; 382};
433 383
384static struct key_type key_type_id_resolver_legacy = {
385 .name = "id_resolver",
386 .instantiate = user_instantiate,
387 .match = user_match,
388 .revoke = user_revoke,
389 .destroy = user_destroy,
390 .describe = user_describe,
391 .read = user_read,
392 .request_key = nfs_idmap_legacy_upcall,
393};
394
395static void __nfs_idmap_unregister(struct rpc_pipe *pipe)
396{
397 if (pipe->dentry)
398 rpc_unlink(pipe->dentry);
399}
400
401static int __nfs_idmap_register(struct dentry *dir,
402 struct idmap *idmap,
403 struct rpc_pipe *pipe)
404{
405 struct dentry *dentry;
406
407 dentry = rpc_mkpipe_dentry(dir, "idmap", idmap, pipe);
408 if (IS_ERR(dentry))
409 return PTR_ERR(dentry);
410 pipe->dentry = dentry;
411 return 0;
412}
413
414static void nfs_idmap_unregister(struct nfs_client *clp,
415 struct rpc_pipe *pipe)
416{
417 struct net *net = clp->net;
418 struct super_block *pipefs_sb;
419
420 pipefs_sb = rpc_get_sb_net(net);
421 if (pipefs_sb) {
422 __nfs_idmap_unregister(pipe);
423 rpc_put_sb_net(net);
424 }
425}
426
427static int nfs_idmap_register(struct nfs_client *clp,
428 struct idmap *idmap,
429 struct rpc_pipe *pipe)
430{
431 struct net *net = clp->net;
432 struct super_block *pipefs_sb;
433 int err = 0;
434
435 pipefs_sb = rpc_get_sb_net(net);
436 if (pipefs_sb) {
437 if (clp->cl_rpcclient->cl_dentry)
438 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
439 idmap, pipe);
440 rpc_put_sb_net(net);
441 }
442 return err;
443}
444
434int 445int
435nfs_idmap_new(struct nfs_client *clp) 446nfs_idmap_new(struct nfs_client *clp)
436{ 447{
437 struct idmap *idmap; 448 struct idmap *idmap;
449 struct rpc_pipe *pipe;
438 int error; 450 int error;
439 451
440 BUG_ON(clp->cl_idmap != NULL); 452 BUG_ON(clp->cl_idmap != NULL);
@@ -443,19 +455,19 @@ nfs_idmap_new(struct nfs_client *clp)
443 if (idmap == NULL) 455 if (idmap == NULL)
444 return -ENOMEM; 456 return -ENOMEM;
445 457
446 idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_path.dentry, 458 pipe = rpc_mkpipe_data(&idmap_upcall_ops, 0);
447 "idmap", idmap, &idmap_upcall_ops, 0); 459 if (IS_ERR(pipe)) {
448 if (IS_ERR(idmap->idmap_dentry)) { 460 error = PTR_ERR(pipe);
449 error = PTR_ERR(idmap->idmap_dentry);
450 kfree(idmap); 461 kfree(idmap);
451 return error; 462 return error;
452 } 463 }
453 464 error = nfs_idmap_register(clp, idmap, pipe);
454 mutex_init(&idmap->idmap_lock); 465 if (error) {
455 mutex_init(&idmap->idmap_im_lock); 466 rpc_destroy_pipe_data(pipe);
456 init_waitqueue_head(&idmap->idmap_wq); 467 kfree(idmap);
457 idmap->idmap_user_hash.h_type = IDMAP_TYPE_USER; 468 return error;
458 idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; 469 }
470 idmap->idmap_pipe = pipe;
459 471
460 clp->cl_idmap = idmap; 472 clp->cl_idmap = idmap;
461 return 0; 473 return 0;
@@ -468,211 +480,220 @@ nfs_idmap_delete(struct nfs_client *clp)
468 480
469 if (!idmap) 481 if (!idmap)
470 return; 482 return;
471 rpc_unlink(idmap->idmap_dentry); 483 nfs_idmap_unregister(clp, idmap->idmap_pipe);
484 rpc_destroy_pipe_data(idmap->idmap_pipe);
472 clp->cl_idmap = NULL; 485 clp->cl_idmap = NULL;
473 kfree(idmap); 486 kfree(idmap);
474} 487}
475 488
476/* 489static int __rpc_pipefs_event(struct nfs_client *clp, unsigned long event,
477 * Helper routines for manipulating the hashtable 490 struct super_block *sb)
478 */
479static inline struct idmap_hashent *
480idmap_name_hash(struct idmap_hashtable* h, const char *name, size_t len)
481{
482 return &h->h_entries[fnvhash32(name, len) % IDMAP_HASH_SZ];
483}
484
485static struct idmap_hashent *
486idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
487{ 491{
488 struct idmap_hashent *he = idmap_name_hash(h, name, len); 492 int err = 0;
489 493
490 if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) 494 switch (event) {
491 return NULL; 495 case RPC_PIPEFS_MOUNT:
492 if (time_after(jiffies, he->ih_expires)) 496 BUG_ON(clp->cl_rpcclient->cl_dentry == NULL);
493 return NULL; 497 err = __nfs_idmap_register(clp->cl_rpcclient->cl_dentry,
494 return he; 498 clp->cl_idmap,
499 clp->cl_idmap->idmap_pipe);
500 break;
501 case RPC_PIPEFS_UMOUNT:
502 if (clp->cl_idmap->idmap_pipe) {
503 struct dentry *parent;
504
505 parent = clp->cl_idmap->idmap_pipe->dentry->d_parent;
506 __nfs_idmap_unregister(clp->cl_idmap->idmap_pipe);
507 /*
508 * Note: This is a dirty hack. SUNRPC hook has been
509 * called already but simple_rmdir() call for the
510 * directory returned with error because of idmap pipe
511 * inside. Thus now we have to remove this directory
512 * here.
513 */
514 if (rpc_rmdir(parent))
515 printk(KERN_ERR "NFS: %s: failed to remove "
516 "clnt dir!\n", __func__);
517 }
518 break;
519 default:
520 printk(KERN_ERR "NFS: %s: unknown event: %ld\n", __func__,
521 event);
522 return -ENOTSUPP;
523 }
524 return err;
525}
526
527static struct nfs_client *nfs_get_client_for_event(struct net *net, int event)
528{
529 struct nfs_net *nn = net_generic(net, nfs_net_id);
530 struct dentry *cl_dentry;
531 struct nfs_client *clp;
532
533 spin_lock(&nn->nfs_client_lock);
534 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
535 if (clp->rpc_ops != &nfs_v4_clientops)
536 continue;
537 cl_dentry = clp->cl_idmap->idmap_pipe->dentry;
538 if (((event == RPC_PIPEFS_MOUNT) && cl_dentry) ||
539 ((event == RPC_PIPEFS_UMOUNT) && !cl_dentry))
540 continue;
541 atomic_inc(&clp->cl_count);
542 spin_unlock(&nn->nfs_client_lock);
543 return clp;
544 }
545 spin_unlock(&nn->nfs_client_lock);
546 return NULL;
495} 547}
496 548
497static inline struct idmap_hashent * 549static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
498idmap_id_hash(struct idmap_hashtable* h, __u32 id) 550 void *ptr)
499{ 551{
500 return &h->h_entries[fnvhash32(&id, sizeof(id)) % IDMAP_HASH_SZ]; 552 struct super_block *sb = ptr;
501} 553 struct nfs_client *clp;
554 int error = 0;
502 555
503static struct idmap_hashent * 556 while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
504idmap_lookup_id(struct idmap_hashtable *h, __u32 id) 557 error = __rpc_pipefs_event(clp, event, sb);
505{ 558 nfs_put_client(clp);
506 struct idmap_hashent *he = idmap_id_hash(h, id); 559 if (error)
507 if (he->ih_id != id || he->ih_namelen == 0) 560 break;
508 return NULL; 561 }
509 if (time_after(jiffies, he->ih_expires)) 562 return error;
510 return NULL;
511 return he;
512} 563}
513 564
514/* 565#define PIPEFS_NFS_PRIO 1
515 * Routines for allocating new entries in the hashtable. 566
516 * For now, we just have 1 entry per bucket, so it's all 567static struct notifier_block nfs_idmap_block = {
517 * pretty trivial. 568 .notifier_call = rpc_pipefs_event,
518 */ 569 .priority = SUNRPC_PIPEFS_NFS_PRIO,
519static inline struct idmap_hashent * 570};
520idmap_alloc_name(struct idmap_hashtable *h, char *name, size_t len)
521{
522 return idmap_name_hash(h, name, len);
523}
524 571
525static inline struct idmap_hashent * 572int nfs_idmap_init(void)
526idmap_alloc_id(struct idmap_hashtable *h, __u32 id)
527{ 573{
528 return idmap_id_hash(h, id); 574 int ret;
575 ret = nfs_idmap_init_keyring();
576 if (ret != 0)
577 goto out;
578 ret = rpc_pipefs_notifier_register(&nfs_idmap_block);
579 if (ret != 0)
580 nfs_idmap_quit_keyring();
581out:
582 return ret;
529} 583}
530 584
531static void 585void nfs_idmap_quit(void)
532idmap_update_entry(struct idmap_hashent *he, const char *name,
533 size_t namelen, __u32 id)
534{ 586{
535 he->ih_id = id; 587 rpc_pipefs_notifier_unregister(&nfs_idmap_block);
536 memcpy(he->ih_name, name, namelen); 588 nfs_idmap_quit_keyring();
537 he->ih_name[namelen] = '\0';
538 he->ih_namelen = namelen;
539 he->ih_expires = jiffies + nfs_idmap_cache_timeout;
540} 589}
541 590
542/* 591static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im,
543 * Name -> ID 592 struct rpc_pipe_msg *msg)
544 */
545static int
546nfs_idmap_id(struct idmap *idmap, struct idmap_hashtable *h,
547 const char *name, size_t namelen, __u32 *id)
548{ 593{
549 struct rpc_pipe_msg msg; 594 substring_t substr;
550 struct idmap_msg *im; 595 int token, ret;
551 struct idmap_hashent *he;
552 DECLARE_WAITQUEUE(wq, current);
553 int ret = -EIO;
554
555 im = &idmap->idmap_im;
556
557 /*
558 * String sanity checks
559 * Note that the userland daemon expects NUL terminated strings
560 */
561 for (;;) {
562 if (namelen == 0)
563 return -EINVAL;
564 if (name[namelen-1] != '\0')
565 break;
566 namelen--;
567 }
568 if (namelen >= IDMAP_NAMESZ)
569 return -EINVAL;
570 596
571 mutex_lock(&idmap->idmap_lock); 597 memset(im, 0, sizeof(*im));
572 mutex_lock(&idmap->idmap_im_lock); 598 memset(msg, 0, sizeof(*msg));
573
574 he = idmap_lookup_name(h, name, namelen);
575 if (he != NULL) {
576 *id = he->ih_id;
577 ret = 0;
578 goto out;
579 }
580 599
581 memset(im, 0, sizeof(*im)); 600 im->im_type = IDMAP_TYPE_GROUP;
582 memcpy(im->im_name, name, namelen); 601 token = match_token(desc, nfs_idmap_tokens, &substr);
583 602
584 im->im_type = h->h_type; 603 switch (token) {
585 im->im_conv = IDMAP_CONV_NAMETOID; 604 case Opt_find_uid:
605 im->im_type = IDMAP_TYPE_USER;
606 case Opt_find_gid:
607 im->im_conv = IDMAP_CONV_NAMETOID;
608 ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
609 break;
586 610
587 memset(&msg, 0, sizeof(msg)); 611 case Opt_find_user:
588 msg.data = im; 612 im->im_type = IDMAP_TYPE_USER;
589 msg.len = sizeof(*im); 613 case Opt_find_group:
614 im->im_conv = IDMAP_CONV_IDTONAME;
615 ret = match_int(&substr, &im->im_id);
616 break;
590 617
591 add_wait_queue(&idmap->idmap_wq, &wq); 618 default:
592 if (rpc_queue_upcall(idmap->idmap_dentry->d_inode, &msg) < 0) { 619 ret = -EINVAL;
593 remove_wait_queue(&idmap->idmap_wq, &wq);
594 goto out; 620 goto out;
595 } 621 }
596 622
597 set_current_state(TASK_UNINTERRUPTIBLE); 623 msg->data = im;
598 mutex_unlock(&idmap->idmap_im_lock); 624 msg->len = sizeof(struct idmap_msg);
599 schedule();
600 __set_current_state(TASK_RUNNING);
601 remove_wait_queue(&idmap->idmap_wq, &wq);
602 mutex_lock(&idmap->idmap_im_lock);
603 625
604 if (im->im_status & IDMAP_STATUS_SUCCESS) { 626out:
605 *id = im->im_id;
606 ret = 0;
607 }
608
609 out:
610 memset(im, 0, sizeof(*im));
611 mutex_unlock(&idmap->idmap_im_lock);
612 mutex_unlock(&idmap->idmap_lock);
613 return ret; 627 return ret;
614} 628}
615 629
616/* 630static int nfs_idmap_legacy_upcall(struct key_construction *cons,
617 * ID -> Name 631 const char *op,
618 */ 632 void *aux)
619static int
620nfs_idmap_name(struct idmap *idmap, struct idmap_hashtable *h,
621 __u32 id, char *name)
622{ 633{
623 struct rpc_pipe_msg msg; 634 struct rpc_pipe_msg *msg;
624 struct idmap_msg *im; 635 struct idmap_msg *im;
625 struct idmap_hashent *he; 636 struct idmap *idmap = (struct idmap *)aux;
626 DECLARE_WAITQUEUE(wq, current); 637 struct key *key = cons->key;
627 int ret = -EIO; 638 int ret;
628 unsigned int len;
629
630 im = &idmap->idmap_im;
631 639
632 mutex_lock(&idmap->idmap_lock); 640 /* msg and im are freed in idmap_pipe_destroy_msg */
633 mutex_lock(&idmap->idmap_im_lock); 641 msg = kmalloc(sizeof(*msg), GFP_KERNEL);
642 if (IS_ERR(msg)) {
643 ret = PTR_ERR(msg);
644 goto out0;
645 }
634 646
635 he = idmap_lookup_id(h, id); 647 im = kmalloc(sizeof(*im), GFP_KERNEL);
636 if (he) { 648 if (IS_ERR(im)) {
637 memcpy(name, he->ih_name, he->ih_namelen); 649 ret = PTR_ERR(im);
638 ret = he->ih_namelen; 650 goto out1;
639 goto out;
640 } 651 }
641 652
642 memset(im, 0, sizeof(*im)); 653 ret = nfs_idmap_prepare_message(key->description, im, msg);
643 im->im_type = h->h_type; 654 if (ret < 0)
644 im->im_conv = IDMAP_CONV_IDTONAME; 655 goto out2;
645 im->im_id = id;
646 656
647 memset(&msg, 0, sizeof(msg)); 657 idmap->idmap_key_cons = cons;
648 msg.data = im;
649 msg.len = sizeof(*im);
650 658
651 add_wait_queue(&idmap->idmap_wq, &wq); 659 ret = rpc_queue_upcall(idmap->idmap_pipe, msg);
660 if (ret < 0)
661 goto out2;
652 662
653 if (rpc_queue_upcall(idmap->idmap_dentry->d_inode, &msg) < 0) { 663 return ret;
654 remove_wait_queue(&idmap->idmap_wq, &wq); 664
655 goto out; 665out2:
656 } 666 kfree(im);
667out1:
668 kfree(msg);
669out0:
670 key_revoke(cons->key);
671 key_revoke(cons->authkey);
672 return ret;
673}
674
675static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data)
676{
677 return key_instantiate_and_link(key, data, strlen(data) + 1,
678 id_resolver_cache->thread_keyring,
679 authkey);
680}
657 681
658 set_current_state(TASK_UNINTERRUPTIBLE); 682static int nfs_idmap_read_message(struct idmap_msg *im, struct key *key, struct key *authkey)
659 mutex_unlock(&idmap->idmap_im_lock); 683{
660 schedule(); 684 char id_str[NFS_UINT_MAXLEN];
661 __set_current_state(TASK_RUNNING); 685 int ret = -EINVAL;
662 remove_wait_queue(&idmap->idmap_wq, &wq); 686
663 mutex_lock(&idmap->idmap_im_lock); 687 switch (im->im_conv) {
664 688 case IDMAP_CONV_NAMETOID:
665 if (im->im_status & IDMAP_STATUS_SUCCESS) { 689 sprintf(id_str, "%d", im->im_id);
666 if ((len = strnlen(im->im_name, IDMAP_NAMESZ)) == 0) 690 ret = nfs_idmap_instantiate(key, authkey, id_str);
667 goto out; 691 break;
668 memcpy(name, im->im_name, len); 692 case IDMAP_CONV_IDTONAME:
669 ret = len; 693 ret = nfs_idmap_instantiate(key, authkey, im->im_name);
694 break;
670 } 695 }
671 696
672 out:
673 memset(im, 0, sizeof(*im));
674 mutex_unlock(&idmap->idmap_im_lock);
675 mutex_unlock(&idmap->idmap_lock);
676 return ret; 697 return ret;
677} 698}
678 699
@@ -681,115 +702,51 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
681{ 702{
682 struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); 703 struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode);
683 struct idmap *idmap = (struct idmap *)rpci->private; 704 struct idmap *idmap = (struct idmap *)rpci->private;
684 struct idmap_msg im_in, *im = &idmap->idmap_im; 705 struct key_construction *cons = idmap->idmap_key_cons;
685 struct idmap_hashtable *h; 706 struct idmap_msg im;
686 struct idmap_hashent *he = NULL;
687 size_t namelen_in; 707 size_t namelen_in;
688 int ret; 708 int ret;
689 709
690 if (mlen != sizeof(im_in)) 710 if (mlen != sizeof(im)) {
691 return -ENOSPC; 711 ret = -ENOSPC;
692
693 if (copy_from_user(&im_in, src, mlen) != 0)
694 return -EFAULT;
695
696 mutex_lock(&idmap->idmap_im_lock);
697
698 ret = mlen;
699 im->im_status = im_in.im_status;
700 /* If we got an error, terminate now, and wake up pending upcalls */
701 if (!(im_in.im_status & IDMAP_STATUS_SUCCESS)) {
702 wake_up(&idmap->idmap_wq);
703 goto out; 712 goto out;
704 } 713 }
705 714
706 /* Sanity checking of strings */ 715 if (copy_from_user(&im, src, mlen) != 0) {
707 ret = -EINVAL; 716 ret = -EFAULT;
708 namelen_in = strnlen(im_in.im_name, IDMAP_NAMESZ);
709 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ)
710 goto out; 717 goto out;
718 }
711 719
712 switch (im_in.im_type) { 720 if (!(im.im_status & IDMAP_STATUS_SUCCESS)) {
713 case IDMAP_TYPE_USER: 721 ret = mlen;
714 h = &idmap->idmap_user_hash; 722 complete_request_key(idmap->idmap_key_cons, -ENOKEY);
715 break; 723 goto out_incomplete;
716 case IDMAP_TYPE_GROUP:
717 h = &idmap->idmap_group_hash;
718 break;
719 default:
720 goto out;
721 } 724 }
722 725
723 switch (im_in.im_conv) { 726 namelen_in = strnlen(im.im_name, IDMAP_NAMESZ);
724 case IDMAP_CONV_IDTONAME: 727 if (namelen_in == 0 || namelen_in == IDMAP_NAMESZ) {
725 /* Did we match the current upcall? */ 728 ret = -EINVAL;
726 if (im->im_conv == IDMAP_CONV_IDTONAME
727 && im->im_type == im_in.im_type
728 && im->im_id == im_in.im_id) {
729 /* Yes: copy string, including the terminating '\0' */
730 memcpy(im->im_name, im_in.im_name, namelen_in);
731 im->im_name[namelen_in] = '\0';
732 wake_up(&idmap->idmap_wq);
733 }
734 he = idmap_alloc_id(h, im_in.im_id);
735 break;
736 case IDMAP_CONV_NAMETOID:
737 /* Did we match the current upcall? */
738 if (im->im_conv == IDMAP_CONV_NAMETOID
739 && im->im_type == im_in.im_type
740 && strnlen(im->im_name, IDMAP_NAMESZ) == namelen_in
741 && memcmp(im->im_name, im_in.im_name, namelen_in) == 0) {
742 im->im_id = im_in.im_id;
743 wake_up(&idmap->idmap_wq);
744 }
745 he = idmap_alloc_name(h, im_in.im_name, namelen_in);
746 break;
747 default:
748 goto out; 729 goto out;
749 } 730 }
750 731
751 /* If the entry is valid, also copy it to the cache */ 732 ret = nfs_idmap_read_message(&im, cons->key, cons->authkey);
752 if (he != NULL) 733 if (ret >= 0) {
753 idmap_update_entry(he, im_in.im_name, namelen_in, im_in.im_id); 734 key_set_timeout(cons->key, nfs_idmap_cache_timeout);
754 ret = mlen; 735 ret = mlen;
736 }
737
755out: 738out:
756 mutex_unlock(&idmap->idmap_im_lock); 739 complete_request_key(idmap->idmap_key_cons, ret);
740out_incomplete:
757 return ret; 741 return ret;
758} 742}
759 743
760static void 744static void
761idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) 745idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)
762{ 746{
763 struct idmap_msg *im = msg->data; 747 /* Free memory allocated in nfs_idmap_legacy_upcall() */
764 struct idmap *idmap = container_of(im, struct idmap, idmap_im); 748 kfree(msg->data);
765 749 kfree(msg);
766 if (msg->errno >= 0)
767 return;
768 mutex_lock(&idmap->idmap_im_lock);
769 im->im_status = IDMAP_STATUS_LOOKUPFAIL;
770 wake_up(&idmap->idmap_wq);
771 mutex_unlock(&idmap->idmap_im_lock);
772}
773
774/*
775 * Fowler/Noll/Vo hash
776 * http://www.isthe.com/chongo/tech/comp/fnv/
777 */
778
779#define FNV_P_32 ((unsigned int)0x01000193) /* 16777619 */
780#define FNV_1_32 ((unsigned int)0x811c9dc5) /* 2166136261 */
781
782static unsigned int fnvhash32(const void *buf, size_t buflen)
783{
784 const unsigned char *p, *end = (const unsigned char *)buf + buflen;
785 unsigned int hash = FNV_1_32;
786
787 for (p = buf; p < end; p++) {
788 hash *= FNV_P_32;
789 hash ^= (unsigned int)*p;
790 }
791
792 return hash;
793} 750}
794 751
795int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) 752int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
@@ -798,16 +755,16 @@ int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_
798 755
799 if (nfs_map_string_to_numeric(name, namelen, uid)) 756 if (nfs_map_string_to_numeric(name, namelen, uid))
800 return 0; 757 return 0;
801 return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); 758 return nfs_idmap_lookup_id(name, namelen, "uid", uid, idmap);
802} 759}
803 760
804int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) 761int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid)
805{ 762{
806 struct idmap *idmap = server->nfs_client->cl_idmap; 763 struct idmap *idmap = server->nfs_client->cl_idmap;
807 764
808 if (nfs_map_string_to_numeric(name, namelen, uid)) 765 if (nfs_map_string_to_numeric(name, namelen, gid))
809 return 0; 766 return 0;
810 return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); 767 return nfs_idmap_lookup_id(name, namelen, "gid", gid, idmap);
811} 768}
812 769
813int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) 770int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
@@ -816,21 +773,19 @@ int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, s
816 int ret = -EINVAL; 773 int ret = -EINVAL;
817 774
818 if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) 775 if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
819 ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); 776 ret = nfs_idmap_lookup_name(uid, "user", buf, buflen, idmap);
820 if (ret < 0) 777 if (ret < 0)
821 ret = nfs_map_numeric_to_string(uid, buf, buflen); 778 ret = nfs_map_numeric_to_string(uid, buf, buflen);
822 return ret; 779 return ret;
823} 780}
824int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen) 781int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
825{ 782{
826 struct idmap *idmap = server->nfs_client->cl_idmap; 783 struct idmap *idmap = server->nfs_client->cl_idmap;
827 int ret = -EINVAL; 784 int ret = -EINVAL;
828 785
829 if (!(server->caps & NFS_CAP_UIDGID_NOMAP)) 786 if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
830 ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf); 787 ret = nfs_idmap_lookup_name(gid, "group", buf, buflen, idmap);
831 if (ret < 0) 788 if (ret < 0)
832 ret = nfs_map_numeric_to_string(uid, buf, buflen); 789 ret = nfs_map_numeric_to_string(gid, buf, buflen);
833 return ret; 790 return ret;
834} 791}
835
836#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */