1 /* 2 * Copyright (c) 2004 The Regents of the University of Michigan. 3 * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com> 4 * All rights reserved. 5 * 6 * Andy Adamson <andros@citi.umich.edu> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 #include <linux/file.h> 36 #include <linux/slab.h> 37 #include <linux/namei.h> 38 #include <linux/crypto.h> 39 #include <linux/sched.h> 40 #include <linux/fs.h> 41 #include <linux/module.h> 42 #include <net/net_namespace.h> 43 #include <linux/sunrpc/rpc_pipe_fs.h> 44 #include <linux/sunrpc/clnt.h> 45 #include <linux/nfsd/cld.h> 46 47 #include "nfsd.h" 48 #include "state.h" 49 #include "vfs.h" 50 #include "netns.h" 51 52 #define NFSDDBG_FACILITY NFSDDBG_PROC 53 54 /* Declarations */ 55 struct nfsd4_client_tracking_ops { 56 int (*init)(struct net *); 57 void (*exit)(struct net *); 58 void (*create)(struct nfs4_client *); 59 void (*remove)(struct nfs4_client *); 60 int (*check)(struct nfs4_client *); 61 void (*grace_done)(struct nfsd_net *, time_t); 62 }; 63 64 /* Globals */ 65 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 66 67 static int 68 nfs4_save_creds(const struct cred **original_creds) 69 { 70 struct cred *new; 71 72 new = prepare_creds(); 73 if (!new) 74 return -ENOMEM; 75 76 new->fsuid = GLOBAL_ROOT_UID; 77 new->fsgid = GLOBAL_ROOT_GID; 78 *original_creds = override_creds(new); 79 put_cred(new); 80 return 0; 81 } 82 83 static void 84 nfs4_reset_creds(const struct cred *original) 85 { 86 revert_creds(original); 87 } 88 89 static void 90 md5_to_hex(char *out, char *md5) 91 { 92 int i; 93 94 for (i=0; i<16; i++) { 95 unsigned char c = md5[i]; 96 97 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); 98 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); 99 } 100 *out = '\0'; 101 } 102 103 static int 104 nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname) 105 { 106 struct xdr_netobj cksum; 107 struct hash_desc desc; 108 struct scatterlist sg; 109 int status; 110 111 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 112 clname->len, clname->data); 113 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; 114 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); 115 if (IS_ERR(desc.tfm)) { 116 status = PTR_ERR(desc.tfm); 117 goto out_no_tfm; 118 } 119 120 cksum.len = crypto_hash_digestsize(desc.tfm); 121 cksum.data = kmalloc(cksum.len, GFP_KERNEL); 122 if (cksum.data == NULL) { 123 status = -ENOMEM; 124 goto out; 125 } 126 127 sg_init_one(&sg, clname->data, clname->len); 128 129 status = crypto_hash_digest(&desc, &sg, sg.length, cksum.data); 130 if (status) 131 goto out; 132 133 md5_to_hex(dname, cksum.data); 134 135 status = 0; 136 out: 137 kfree(cksum.data); 138 crypto_free_hash(desc.tfm); 139 out_no_tfm: 140 return status; 141 } 142 143 /* 144 * If we had an error generating the recdir name for the legacy tracker 145 * then warn the admin. If the error doesn't appear to be transient, 146 * then disable recovery tracking. 147 */ 148 static void 149 legacy_recdir_name_error(struct nfs4_client *clp, int error) 150 { 151 printk(KERN_ERR "NFSD: unable to generate recoverydir " 152 "name (%d).\n", error); 153 154 /* 155 * if the algorithm just doesn't exist, then disable the recovery 156 * tracker altogether. The crypto libs will generally return this if 157 * FIPS is enabled as well. 158 */ 159 if (error == -ENOENT) { 160 printk(KERN_ERR "NFSD: disabling legacy clientid tracking. " 161 "Reboot recovery will not function correctly!\n"); 162 nfsd4_client_tracking_exit(clp->net); 163 } 164 } 165 166 static void 167 nfsd4_create_clid_dir(struct nfs4_client *clp) 168 { 169 const struct cred *original_cred; 170 char dname[HEXDIR_LEN]; 171 struct dentry *dir, *dentry; 172 struct nfs4_client_reclaim *crp; 173 int status; 174 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 175 176 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 177 178 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 179 return; 180 if (!nn->rec_file) 181 return; 182 183 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 184 if (status) 185 return legacy_recdir_name_error(clp, status); 186 187 status = nfs4_save_creds(&original_cred); 188 if (status < 0) 189 return; 190 191 status = mnt_want_write_file(nn->rec_file); 192 if (status) 193 return; 194 195 dir = nn->rec_file->f_path.dentry; 196 /* lock the parent */ 197 mutex_lock(&dir->d_inode->i_mutex); 198 199 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1); 200 if (IS_ERR(dentry)) { 201 status = PTR_ERR(dentry); 202 goto out_unlock; 203 } 204 if (dentry->d_inode) 205 /* 206 * In the 4.1 case, where we're called from 207 * reclaim_complete(), records from the previous reboot 208 * may still be left, so this is OK. 209 * 210 * In the 4.0 case, we should never get here; but we may 211 * as well be forgiving and just succeed silently. 212 */ 213 goto out_put; 214 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); 215 out_put: 216 dput(dentry); 217 out_unlock: 218 mutex_unlock(&dir->d_inode->i_mutex); 219 if (status == 0) { 220 if (nn->in_grace) { 221 crp = nfs4_client_to_reclaim(dname, nn); 222 if (crp) 223 crp->cr_clp = clp; 224 } 225 vfs_fsync(nn->rec_file, 0); 226 } else { 227 printk(KERN_ERR "NFSD: failed to write recovery record" 228 " (err %d); please check that %s exists" 229 " and is writeable", status, 230 user_recovery_dirname); 231 } 232 mnt_drop_write_file(nn->rec_file); 233 nfs4_reset_creds(original_cred); 234 } 235 236 typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *); 237 238 struct name_list { 239 char name[HEXDIR_LEN]; 240 struct list_head list; 241 }; 242 243 static int 244 nfsd4_build_namelist(void *arg, const char *name, int namlen, 245 loff_t offset, u64 ino, unsigned int d_type) 246 { 247 struct list_head *names = arg; 248 struct name_list *entry; 249 250 if (namlen != HEXDIR_LEN - 1) 251 return 0; 252 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL); 253 if (entry == NULL) 254 return -ENOMEM; 255 memcpy(entry->name, name, HEXDIR_LEN - 1); 256 entry->name[HEXDIR_LEN - 1] = '\0'; 257 list_add(&entry->list, names); 258 return 0; 259 } 260 261 static int 262 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 263 { 264 const struct cred *original_cred; 265 struct dentry *dir = nn->rec_file->f_path.dentry; 266 LIST_HEAD(names); 267 int status; 268 269 status = nfs4_save_creds(&original_cred); 270 if (status < 0) 271 return status; 272 273 status = vfs_llseek(nn->rec_file, 0, SEEK_SET); 274 if (status < 0) { 275 nfs4_reset_creds(original_cred); 276 return status; 277 } 278 279 status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names); 280 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 281 while (!list_empty(&names)) { 282 struct name_list *entry; 283 entry = list_entry(names.next, struct name_list, list); 284 if (!status) { 285 struct dentry *dentry; 286 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); 287 if (IS_ERR(dentry)) { 288 status = PTR_ERR(dentry); 289 break; 290 } 291 status = f(dir, dentry, nn); 292 dput(dentry); 293 } 294 list_del(&entry->list); 295 kfree(entry); 296 } 297 mutex_unlock(&dir->d_inode->i_mutex); 298 nfs4_reset_creds(original_cred); 299 return status; 300 } 301 302 static int 303 nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn) 304 { 305 struct dentry *dir, *dentry; 306 int status; 307 308 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 309 310 dir = nn->rec_file->f_path.dentry; 311 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 312 dentry = lookup_one_len(name, dir, namlen); 313 if (IS_ERR(dentry)) { 314 status = PTR_ERR(dentry); 315 goto out_unlock; 316 } 317 status = -ENOENT; 318 if (!dentry->d_inode) 319 goto out; 320 status = vfs_rmdir(dir->d_inode, dentry); 321 out: 322 dput(dentry); 323 out_unlock: 324 mutex_unlock(&dir->d_inode->i_mutex); 325 return status; 326 } 327 328 static void 329 nfsd4_remove_clid_dir(struct nfs4_client *clp) 330 { 331 const struct cred *original_cred; 332 struct nfs4_client_reclaim *crp; 333 char dname[HEXDIR_LEN]; 334 int status; 335 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 336 337 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 338 return; 339 340 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 341 if (status) 342 return legacy_recdir_name_error(clp, status); 343 344 status = mnt_want_write_file(nn->rec_file); 345 if (status) 346 goto out; 347 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 348 349 status = nfs4_save_creds(&original_cred); 350 if (status < 0) 351 goto out_drop_write; 352 353 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn); 354 nfs4_reset_creds(original_cred); 355 if (status == 0) { 356 vfs_fsync(nn->rec_file, 0); 357 if (nn->in_grace) { 358 /* remove reclaim record */ 359 crp = nfsd4_find_reclaim_client(dname, nn); 360 if (crp) 361 nfs4_remove_reclaim_record(crp, nn); 362 } 363 } 364 out_drop_write: 365 mnt_drop_write_file(nn->rec_file); 366 out: 367 if (status) 368 printk("NFSD: Failed to remove expired client state directory" 369 " %.*s\n", HEXDIR_LEN, dname); 370 } 371 372 static int 373 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 374 { 375 int status; 376 377 if (nfs4_has_reclaimed_state(child->d_name.name, nn)) 378 return 0; 379 380 status = vfs_rmdir(parent->d_inode, child); 381 if (status) 382 printk("failed to remove client recovery directory %s\n", 383 child->d_name.name); 384 /* Keep trying, success or failure: */ 385 return 0; 386 } 387 388 static void 389 nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time) 390 { 391 int status; 392 393 nn->in_grace = false; 394 if (!nn->rec_file) 395 return; 396 status = mnt_want_write_file(nn->rec_file); 397 if (status) 398 goto out; 399 status = nfsd4_list_rec_dir(purge_old, nn); 400 if (status == 0) 401 vfs_fsync(nn->rec_file, 0); 402 mnt_drop_write_file(nn->rec_file); 403 out: 404 nfs4_release_reclaim(nn); 405 if (status) 406 printk("nfsd4: failed to purge old clients from recovery" 407 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name); 408 } 409 410 static int 411 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 412 { 413 if (child->d_name.len != HEXDIR_LEN - 1) { 414 printk("nfsd4: illegal name %s in recovery directory\n", 415 child->d_name.name); 416 /* Keep trying; maybe the others are OK: */ 417 return 0; 418 } 419 nfs4_client_to_reclaim(child->d_name.name, nn); 420 return 0; 421 } 422 423 static int 424 nfsd4_recdir_load(struct net *net) { 425 int status; 426 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 427 428 if (!nn->rec_file) 429 return 0; 430 431 status = nfsd4_list_rec_dir(load_recdir, nn); 432 if (status) 433 printk("nfsd4: failed loading clients from recovery" 434 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name); 435 return status; 436 } 437 438 /* 439 * Hold reference to the recovery directory. 440 */ 441 442 static int 443 nfsd4_init_recdir(struct net *net) 444 { 445 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 446 const struct cred *original_cred; 447 int status; 448 449 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 450 user_recovery_dirname); 451 452 BUG_ON(nn->rec_file); 453 454 status = nfs4_save_creds(&original_cred); 455 if (status < 0) { 456 printk("NFSD: Unable to change credentials to find recovery" 457 " directory: error %d\n", 458 status); 459 return status; 460 } 461 462 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 463 if (IS_ERR(nn->rec_file)) { 464 printk("NFSD: unable to find recovery directory %s\n", 465 user_recovery_dirname); 466 status = PTR_ERR(nn->rec_file); 467 nn->rec_file = NULL; 468 } 469 470 nfs4_reset_creds(original_cred); 471 if (!status) 472 nn->in_grace = true; 473 return status; 474 } 475 476 477 static int 478 nfs4_legacy_state_init(struct net *net) 479 { 480 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 481 int i; 482 483 nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) * 484 CLIENT_HASH_SIZE, GFP_KERNEL); 485 if (!nn->reclaim_str_hashtbl) 486 return -ENOMEM; 487 488 for (i = 0; i < CLIENT_HASH_SIZE; i++) 489 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 490 nn->reclaim_str_hashtbl_size = 0; 491 492 return 0; 493 } 494 495 static void 496 nfs4_legacy_state_shutdown(struct net *net) 497 { 498 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 499 500 kfree(nn->reclaim_str_hashtbl); 501 } 502 503 static int 504 nfsd4_load_reboot_recovery_data(struct net *net) 505 { 506 int status; 507 508 status = nfsd4_init_recdir(net); 509 if (!status) 510 status = nfsd4_recdir_load(net); 511 if (status) 512 printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n"); 513 return status; 514 } 515 516 static int 517 nfsd4_legacy_tracking_init(struct net *net) 518 { 519 int status; 520 521 /* XXX: The legacy code won't work in a container */ 522 if (net != &init_net) { 523 WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client " 524 "tracking in a container!\n"); 525 return -EINVAL; 526 } 527 528 status = nfs4_legacy_state_init(net); 529 if (status) 530 return status; 531 532 status = nfsd4_load_reboot_recovery_data(net); 533 if (status) 534 goto err; 535 return 0; 536 537 err: 538 nfs4_legacy_state_shutdown(net); 539 return status; 540 } 541 542 static void 543 nfsd4_shutdown_recdir(struct nfsd_net *nn) 544 { 545 if (!nn->rec_file) 546 return; 547 fput(nn->rec_file); 548 nn->rec_file = NULL; 549 } 550 551 static void 552 nfsd4_legacy_tracking_exit(struct net *net) 553 { 554 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 555 556 nfs4_release_reclaim(nn); 557 nfsd4_shutdown_recdir(nn); 558 nfs4_legacy_state_shutdown(net); 559 } 560 561 /* 562 * Change the NFSv4 recovery directory to recdir. 563 */ 564 int 565 nfs4_reset_recoverydir(char *recdir) 566 { 567 int status; 568 struct path path; 569 570 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 571 if (status) 572 return status; 573 status = -ENOTDIR; 574 if (S_ISDIR(path.dentry->d_inode->i_mode)) { 575 strcpy(user_recovery_dirname, recdir); 576 status = 0; 577 } 578 path_put(&path); 579 return status; 580 } 581 582 char * 583 nfs4_recoverydir(void) 584 { 585 return user_recovery_dirname; 586 } 587 588 static int 589 nfsd4_check_legacy_client(struct nfs4_client *clp) 590 { 591 int status; 592 char dname[HEXDIR_LEN]; 593 struct nfs4_client_reclaim *crp; 594 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 595 596 /* did we already find that this client is stable? */ 597 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 598 return 0; 599 600 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 601 if (status) { 602 legacy_recdir_name_error(clp, status); 603 return status; 604 } 605 606 /* look for it in the reclaim hashtable otherwise */ 607 crp = nfsd4_find_reclaim_client(dname, nn); 608 if (crp) { 609 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 610 crp->cr_clp = clp; 611 return 0; 612 } 613 614 return -ENOENT; 615 } 616 617 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 618 .init = nfsd4_legacy_tracking_init, 619 .exit = nfsd4_legacy_tracking_exit, 620 .create = nfsd4_create_clid_dir, 621 .remove = nfsd4_remove_clid_dir, 622 .check = nfsd4_check_legacy_client, 623 .grace_done = nfsd4_recdir_purge_old, 624 }; 625 626 /* Globals */ 627 #define NFSD_PIPE_DIR "nfsd" 628 #define NFSD_CLD_PIPE "cld" 629 630 /* per-net-ns structure for holding cld upcall info */ 631 struct cld_net { 632 struct rpc_pipe *cn_pipe; 633 spinlock_t cn_lock; 634 struct list_head cn_list; 635 unsigned int cn_xid; 636 }; 637 638 struct cld_upcall { 639 struct list_head cu_list; 640 struct cld_net *cu_net; 641 struct task_struct *cu_task; 642 struct cld_msg cu_msg; 643 }; 644 645 static int 646 __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 647 { 648 int ret; 649 struct rpc_pipe_msg msg; 650 651 memset(&msg, 0, sizeof(msg)); 652 msg.data = cmsg; 653 msg.len = sizeof(*cmsg); 654 655 /* 656 * Set task state before we queue the upcall. That prevents 657 * wake_up_process in the downcall from racing with schedule. 658 */ 659 set_current_state(TASK_UNINTERRUPTIBLE); 660 ret = rpc_queue_upcall(pipe, &msg); 661 if (ret < 0) { 662 set_current_state(TASK_RUNNING); 663 goto out; 664 } 665 666 schedule(); 667 set_current_state(TASK_RUNNING); 668 669 if (msg.errno < 0) 670 ret = msg.errno; 671 out: 672 return ret; 673 } 674 675 static int 676 cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 677 { 678 int ret; 679 680 /* 681 * -EAGAIN occurs when pipe is closed and reopened while there are 682 * upcalls queued. 683 */ 684 do { 685 ret = __cld_pipe_upcall(pipe, cmsg); 686 } while (ret == -EAGAIN); 687 688 return ret; 689 } 690 691 static ssize_t 692 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 693 { 694 struct cld_upcall *tmp, *cup; 695 struct cld_msg __user *cmsg = (struct cld_msg __user *)src; 696 uint32_t xid; 697 struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info, 698 nfsd_net_id); 699 struct cld_net *cn = nn->cld_net; 700 701 if (mlen != sizeof(*cmsg)) { 702 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, 703 sizeof(*cmsg)); 704 return -EINVAL; 705 } 706 707 /* copy just the xid so we can try to find that */ 708 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) { 709 dprintk("%s: error when copying xid from userspace", __func__); 710 return -EFAULT; 711 } 712 713 /* walk the list and find corresponding xid */ 714 cup = NULL; 715 spin_lock(&cn->cn_lock); 716 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 717 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { 718 cup = tmp; 719 list_del_init(&cup->cu_list); 720 break; 721 } 722 } 723 spin_unlock(&cn->cn_lock); 724 725 /* couldn't find upcall? */ 726 if (!cup) { 727 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 728 return -EINVAL; 729 } 730 731 if (copy_from_user(&cup->cu_msg, src, mlen) != 0) 732 return -EFAULT; 733 734 wake_up_process(cup->cu_task); 735 return mlen; 736 } 737 738 static void 739 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 740 { 741 struct cld_msg *cmsg = msg->data; 742 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, 743 cu_msg); 744 745 /* errno >= 0 means we got a downcall */ 746 if (msg->errno >= 0) 747 return; 748 749 wake_up_process(cup->cu_task); 750 } 751 752 static const struct rpc_pipe_ops cld_upcall_ops = { 753 .upcall = rpc_pipe_generic_upcall, 754 .downcall = cld_pipe_downcall, 755 .destroy_msg = cld_pipe_destroy_msg, 756 }; 757 758 static struct dentry * 759 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 760 { 761 struct dentry *dir, *dentry; 762 763 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 764 if (dir == NULL) 765 return ERR_PTR(-ENOENT); 766 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 767 dput(dir); 768 return dentry; 769 } 770 771 static void 772 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe) 773 { 774 if (pipe->dentry) 775 rpc_unlink(pipe->dentry); 776 } 777 778 static struct dentry * 779 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 780 { 781 struct super_block *sb; 782 struct dentry *dentry; 783 784 sb = rpc_get_sb_net(net); 785 if (!sb) 786 return NULL; 787 dentry = nfsd4_cld_register_sb(sb, pipe); 788 rpc_put_sb_net(net); 789 return dentry; 790 } 791 792 static void 793 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 794 { 795 struct super_block *sb; 796 797 sb = rpc_get_sb_net(net); 798 if (sb) { 799 nfsd4_cld_unregister_sb(pipe); 800 rpc_put_sb_net(net); 801 } 802 } 803 804 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 805 static int 806 nfsd4_init_cld_pipe(struct net *net) 807 { 808 int ret; 809 struct dentry *dentry; 810 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 811 struct cld_net *cn; 812 813 if (nn->cld_net) 814 return 0; 815 816 cn = kzalloc(sizeof(*cn), GFP_KERNEL); 817 if (!cn) { 818 ret = -ENOMEM; 819 goto err; 820 } 821 822 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 823 if (IS_ERR(cn->cn_pipe)) { 824 ret = PTR_ERR(cn->cn_pipe); 825 goto err; 826 } 827 spin_lock_init(&cn->cn_lock); 828 INIT_LIST_HEAD(&cn->cn_list); 829 830 dentry = nfsd4_cld_register_net(net, cn->cn_pipe); 831 if (IS_ERR(dentry)) { 832 ret = PTR_ERR(dentry); 833 goto err_destroy_data; 834 } 835 836 cn->cn_pipe->dentry = dentry; 837 nn->cld_net = cn; 838 return 0; 839 840 err_destroy_data: 841 rpc_destroy_pipe_data(cn->cn_pipe); 842 err: 843 kfree(cn); 844 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 845 ret); 846 return ret; 847 } 848 849 static void 850 nfsd4_remove_cld_pipe(struct net *net) 851 { 852 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 853 struct cld_net *cn = nn->cld_net; 854 855 nfsd4_cld_unregister_net(net, cn->cn_pipe); 856 rpc_destroy_pipe_data(cn->cn_pipe); 857 kfree(nn->cld_net); 858 nn->cld_net = NULL; 859 } 860 861 static struct cld_upcall * 862 alloc_cld_upcall(struct cld_net *cn) 863 { 864 struct cld_upcall *new, *tmp; 865 866 new = kzalloc(sizeof(*new), GFP_KERNEL); 867 if (!new) 868 return new; 869 870 /* FIXME: hard cap on number in flight? */ 871 restart_search: 872 spin_lock(&cn->cn_lock); 873 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 874 if (tmp->cu_msg.cm_xid == cn->cn_xid) { 875 cn->cn_xid++; 876 spin_unlock(&cn->cn_lock); 877 goto restart_search; 878 } 879 } 880 new->cu_task = current; 881 new->cu_msg.cm_vers = CLD_UPCALL_VERSION; 882 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); 883 new->cu_net = cn; 884 list_add(&new->cu_list, &cn->cn_list); 885 spin_unlock(&cn->cn_lock); 886 887 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid); 888 889 return new; 890 } 891 892 static void 893 free_cld_upcall(struct cld_upcall *victim) 894 { 895 struct cld_net *cn = victim->cu_net; 896 897 spin_lock(&cn->cn_lock); 898 list_del(&victim->cu_list); 899 spin_unlock(&cn->cn_lock); 900 kfree(victim); 901 } 902 903 /* Ask daemon to create a new record */ 904 static void 905 nfsd4_cld_create(struct nfs4_client *clp) 906 { 907 int ret; 908 struct cld_upcall *cup; 909 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 910 struct cld_net *cn = nn->cld_net; 911 912 /* Don't upcall if it's already stored */ 913 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 914 return; 915 916 cup = alloc_cld_upcall(cn); 917 if (!cup) { 918 ret = -ENOMEM; 919 goto out_err; 920 } 921 922 cup->cu_msg.cm_cmd = Cld_Create; 923 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 924 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 925 clp->cl_name.len); 926 927 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 928 if (!ret) { 929 ret = cup->cu_msg.cm_status; 930 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 931 } 932 933 free_cld_upcall(cup); 934 out_err: 935 if (ret) 936 printk(KERN_ERR "NFSD: Unable to create client " 937 "record on stable storage: %d\n", ret); 938 } 939 940 /* Ask daemon to create a new record */ 941 static void 942 nfsd4_cld_remove(struct nfs4_client *clp) 943 { 944 int ret; 945 struct cld_upcall *cup; 946 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 947 struct cld_net *cn = nn->cld_net; 948 949 /* Don't upcall if it's already removed */ 950 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 951 return; 952 953 cup = alloc_cld_upcall(cn); 954 if (!cup) { 955 ret = -ENOMEM; 956 goto out_err; 957 } 958 959 cup->cu_msg.cm_cmd = Cld_Remove; 960 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 961 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 962 clp->cl_name.len); 963 964 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 965 if (!ret) { 966 ret = cup->cu_msg.cm_status; 967 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 968 } 969 970 free_cld_upcall(cup); 971 out_err: 972 if (ret) 973 printk(KERN_ERR "NFSD: Unable to remove client " 974 "record from stable storage: %d\n", ret); 975 } 976 977 /* Check for presence of a record, and update its timestamp */ 978 static int 979 nfsd4_cld_check(struct nfs4_client *clp) 980 { 981 int ret; 982 struct cld_upcall *cup; 983 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 984 struct cld_net *cn = nn->cld_net; 985 986 /* Don't upcall if one was already stored during this grace pd */ 987 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 988 return 0; 989 990 cup = alloc_cld_upcall(cn); 991 if (!cup) { 992 printk(KERN_ERR "NFSD: Unable to check client record on " 993 "stable storage: %d\n", -ENOMEM); 994 return -ENOMEM; 995 } 996 997 cup->cu_msg.cm_cmd = Cld_Check; 998 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 999 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1000 clp->cl_name.len); 1001 1002 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1003 if (!ret) { 1004 ret = cup->cu_msg.cm_status; 1005 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1006 } 1007 1008 free_cld_upcall(cup); 1009 return ret; 1010 } 1011 1012 static void 1013 nfsd4_cld_grace_done(struct nfsd_net *nn, time_t boot_time) 1014 { 1015 int ret; 1016 struct cld_upcall *cup; 1017 struct cld_net *cn = nn->cld_net; 1018 1019 cup = alloc_cld_upcall(cn); 1020 if (!cup) { 1021 ret = -ENOMEM; 1022 goto out_err; 1023 } 1024 1025 cup->cu_msg.cm_cmd = Cld_GraceDone; 1026 cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time; 1027 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1028 if (!ret) 1029 ret = cup->cu_msg.cm_status; 1030 1031 free_cld_upcall(cup); 1032 out_err: 1033 if (ret) 1034 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1035 } 1036 1037 static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1038 .init = nfsd4_init_cld_pipe, 1039 .exit = nfsd4_remove_cld_pipe, 1040 .create = nfsd4_cld_create, 1041 .remove = nfsd4_cld_remove, 1042 .check = nfsd4_cld_check, 1043 .grace_done = nfsd4_cld_grace_done, 1044 }; 1045 1046 /* upcall via usermodehelper */ 1047 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; 1048 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), 1049 S_IRUGO|S_IWUSR); 1050 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 1051 1052 static bool cltrack_legacy_disable; 1053 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); 1054 MODULE_PARM_DESC(cltrack_legacy_disable, 1055 "Disable legacy recoverydir conversion. Default: false"); 1056 1057 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1058 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1059 1060 static char * 1061 nfsd4_cltrack_legacy_topdir(void) 1062 { 1063 int copied; 1064 size_t len; 1065 char *result; 1066 1067 if (cltrack_legacy_disable) 1068 return NULL; 1069 1070 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) + 1071 strlen(nfs4_recoverydir()) + 1; 1072 1073 result = kmalloc(len, GFP_KERNEL); 1074 if (!result) 1075 return result; 1076 1077 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s", 1078 nfs4_recoverydir()); 1079 if (copied >= len) { 1080 /* just return nothing if output was truncated */ 1081 kfree(result); 1082 return NULL; 1083 } 1084 1085 return result; 1086 } 1087 1088 static char * 1089 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name) 1090 { 1091 int copied; 1092 size_t len; 1093 char *result; 1094 1095 if (cltrack_legacy_disable) 1096 return NULL; 1097 1098 /* +1 is for '/' between "topdir" and "recdir" */ 1099 len = strlen(LEGACY_RECDIR_ENV_PREFIX) + 1100 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN; 1101 1102 result = kmalloc(len, GFP_KERNEL); 1103 if (!result) 1104 return result; 1105 1106 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/", 1107 nfs4_recoverydir()); 1108 if (copied > (len - HEXDIR_LEN)) { 1109 /* just return nothing if output will be truncated */ 1110 kfree(result); 1111 return NULL; 1112 } 1113 1114 copied = nfs4_make_rec_clidname(result + copied, name); 1115 if (copied) { 1116 kfree(result); 1117 return NULL; 1118 } 1119 1120 return result; 1121 } 1122 1123 static int 1124 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *legacy) 1125 { 1126 char *envp[2]; 1127 char *argv[4]; 1128 int ret; 1129 1130 if (unlikely(!cltrack_prog[0])) { 1131 dprintk("%s: cltrack_prog is disabled\n", __func__); 1132 return -EACCES; 1133 } 1134 1135 dprintk("%s: cmd: %s\n", __func__, cmd); 1136 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1137 dprintk("%s: legacy: %s\n", __func__, legacy ? legacy : "(null)"); 1138 1139 envp[0] = legacy; 1140 envp[1] = NULL; 1141 1142 argv[0] = (char *)cltrack_prog; 1143 argv[1] = cmd; 1144 argv[2] = arg; 1145 argv[3] = NULL; 1146 1147 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); 1148 /* 1149 * Disable the upcall mechanism if we're getting an ENOENT or EACCES 1150 * error. The admin can re-enable it on the fly by using sysfs 1151 * once the problem has been fixed. 1152 */ 1153 if (ret == -ENOENT || ret == -EACCES) { 1154 dprintk("NFSD: %s was not found or isn't executable (%d). " 1155 "Setting cltrack_prog to blank string!", 1156 cltrack_prog, ret); 1157 cltrack_prog[0] = '\0'; 1158 } 1159 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret); 1160 1161 return ret; 1162 } 1163 1164 static char * 1165 bin_to_hex_dup(const unsigned char *src, int srclen) 1166 { 1167 int i; 1168 char *buf, *hex; 1169 1170 /* +1 for terminating NULL */ 1171 buf = kmalloc((srclen * 2) + 1, GFP_KERNEL); 1172 if (!buf) 1173 return buf; 1174 1175 hex = buf; 1176 for (i = 0; i < srclen; i++) { 1177 sprintf(hex, "%2.2x", *src++); 1178 hex += 2; 1179 } 1180 return buf; 1181 } 1182 1183 static int 1184 nfsd4_umh_cltrack_init(struct net __attribute__((unused)) *net) 1185 { 1186 /* XXX: The usermode helper s not working in container yet. */ 1187 if (net != &init_net) { 1188 WARN(1, KERN_ERR "NFSD: attempt to initialize umh client " 1189 "tracking in a container!\n"); 1190 return -EINVAL; 1191 } 1192 return nfsd4_umh_cltrack_upcall("init", NULL, NULL); 1193 } 1194 1195 static void 1196 nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1197 { 1198 char *hexid; 1199 1200 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1201 if (!hexid) { 1202 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1203 return; 1204 } 1205 nfsd4_umh_cltrack_upcall("create", hexid, NULL); 1206 kfree(hexid); 1207 } 1208 1209 static void 1210 nfsd4_umh_cltrack_remove(struct nfs4_client *clp) 1211 { 1212 char *hexid; 1213 1214 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1215 if (!hexid) { 1216 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1217 return; 1218 } 1219 nfsd4_umh_cltrack_upcall("remove", hexid, NULL); 1220 kfree(hexid); 1221 } 1222 1223 static int 1224 nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1225 { 1226 int ret; 1227 char *hexid, *legacy; 1228 1229 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1230 if (!hexid) { 1231 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1232 return -ENOMEM; 1233 } 1234 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1235 ret = nfsd4_umh_cltrack_upcall("check", hexid, legacy); 1236 kfree(legacy); 1237 kfree(hexid); 1238 return ret; 1239 } 1240 1241 static void 1242 nfsd4_umh_cltrack_grace_done(struct nfsd_net __attribute__((unused)) *nn, 1243 time_t boot_time) 1244 { 1245 char *legacy; 1246 char timestr[22]; /* FIXME: better way to determine max size? */ 1247 1248 sprintf(timestr, "%ld", boot_time); 1249 legacy = nfsd4_cltrack_legacy_topdir(); 1250 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy); 1251 kfree(legacy); 1252 } 1253 1254 static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1255 .init = nfsd4_umh_cltrack_init, 1256 .exit = NULL, 1257 .create = nfsd4_umh_cltrack_create, 1258 .remove = nfsd4_umh_cltrack_remove, 1259 .check = nfsd4_umh_cltrack_check, 1260 .grace_done = nfsd4_umh_cltrack_grace_done, 1261 }; 1262 1263 int 1264 nfsd4_client_tracking_init(struct net *net) 1265 { 1266 int status; 1267 struct path path; 1268 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1269 1270 /* just run the init if it the method is already decided */ 1271 if (nn->client_tracking_ops) 1272 goto do_init; 1273 1274 /* 1275 * First, try a UMH upcall. It should succeed or fail quickly, so 1276 * there's little harm in trying that first. 1277 */ 1278 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 1279 status = nn->client_tracking_ops->init(net); 1280 if (!status) 1281 return status; 1282 1283 /* 1284 * See if the recoverydir exists and is a directory. If it is, 1285 * then use the legacy ops. 1286 */ 1287 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 1288 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 1289 if (!status) { 1290 status = S_ISDIR(path.dentry->d_inode->i_mode); 1291 path_put(&path); 1292 if (status) 1293 goto do_init; 1294 } 1295 1296 /* Finally, try to use nfsdcld */ 1297 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1298 printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be " 1299 "removed in 3.10. Please transition to using " 1300 "nfsdcltrack.\n"); 1301 do_init: 1302 status = nn->client_tracking_ops->init(net); 1303 if (status) { 1304 printk(KERN_WARNING "NFSD: Unable to initialize client " 1305 "recovery tracking! (%d)\n", status); 1306 nn->client_tracking_ops = NULL; 1307 } 1308 return status; 1309 } 1310 1311 void 1312 nfsd4_client_tracking_exit(struct net *net) 1313 { 1314 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1315 1316 if (nn->client_tracking_ops) { 1317 if (nn->client_tracking_ops->exit) 1318 nn->client_tracking_ops->exit(net); 1319 nn->client_tracking_ops = NULL; 1320 } 1321 } 1322 1323 void 1324 nfsd4_client_record_create(struct nfs4_client *clp) 1325 { 1326 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1327 1328 if (nn->client_tracking_ops) 1329 nn->client_tracking_ops->create(clp); 1330 } 1331 1332 void 1333 nfsd4_client_record_remove(struct nfs4_client *clp) 1334 { 1335 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1336 1337 if (nn->client_tracking_ops) 1338 nn->client_tracking_ops->remove(clp); 1339 } 1340 1341 int 1342 nfsd4_client_record_check(struct nfs4_client *clp) 1343 { 1344 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1345 1346 if (nn->client_tracking_ops) 1347 return nn->client_tracking_ops->check(clp); 1348 1349 return -EOPNOTSUPP; 1350 } 1351 1352 void 1353 nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time) 1354 { 1355 if (nn->client_tracking_ops) 1356 nn->client_tracking_ops->grace_done(nn, boot_time); 1357 } 1358 1359 static int 1360 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 1361 { 1362 struct super_block *sb = ptr; 1363 struct net *net = sb->s_fs_info; 1364 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1365 struct cld_net *cn = nn->cld_net; 1366 struct dentry *dentry; 1367 int ret = 0; 1368 1369 if (!try_module_get(THIS_MODULE)) 1370 return 0; 1371 1372 if (!cn) { 1373 module_put(THIS_MODULE); 1374 return 0; 1375 } 1376 1377 switch (event) { 1378 case RPC_PIPEFS_MOUNT: 1379 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); 1380 if (IS_ERR(dentry)) { 1381 ret = PTR_ERR(dentry); 1382 break; 1383 } 1384 cn->cn_pipe->dentry = dentry; 1385 break; 1386 case RPC_PIPEFS_UMOUNT: 1387 if (cn->cn_pipe->dentry) 1388 nfsd4_cld_unregister_sb(cn->cn_pipe); 1389 break; 1390 default: 1391 ret = -ENOTSUPP; 1392 break; 1393 } 1394 module_put(THIS_MODULE); 1395 return ret; 1396 } 1397 1398 static struct notifier_block nfsd4_cld_block = { 1399 .notifier_call = rpc_pipefs_event, 1400 }; 1401 1402 int 1403 register_cld_notifier(void) 1404 { 1405 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 1406 } 1407 1408 void 1409 unregister_cld_notifier(void) 1410 { 1411 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 1412 } 1413