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 <crypto/md5.h> 36 #include <crypto/sha2.h> 37 #include <linux/file.h> 38 #include <linux/slab.h> 39 #include <linux/namei.h> 40 #include <linux/sched.h> 41 #include <linux/fs.h> 42 #include <linux/module.h> 43 #include <net/net_namespace.h> 44 #include <linux/sunrpc/rpc_pipe_fs.h> 45 #include <linux/sunrpc/clnt.h> 46 #include <linux/nfsd/cld.h> 47 48 #include "nfsd.h" 49 #include "state.h" 50 #include "vfs.h" 51 #include "netns.h" 52 53 #define NFSDDBG_FACILITY NFSDDBG_PROC 54 55 /* Declarations */ 56 struct nfsd4_client_tracking_ops { 57 int (*init)(struct net *); 58 void (*exit)(struct net *); 59 void (*create)(struct nfs4_client *); 60 void (*remove)(struct nfs4_client *); 61 int (*check)(struct nfs4_client *); 62 void (*grace_done)(struct nfsd_net *); 63 uint8_t version; 64 size_t msglen; 65 }; 66 67 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops; 68 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2; 69 70 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 71 /* Globals */ 72 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 73 74 static int 75 nfs4_save_creds(const struct cred **original_creds) 76 { 77 struct cred *new; 78 79 new = prepare_creds(); 80 if (!new) 81 return -ENOMEM; 82 83 new->fsuid = GLOBAL_ROOT_UID; 84 new->fsgid = GLOBAL_ROOT_GID; 85 *original_creds = override_creds(new); 86 return 0; 87 } 88 89 static void 90 nfs4_reset_creds(const struct cred *original) 91 { 92 put_cred(revert_creds(original)); 93 } 94 95 static void 96 nfs4_make_rec_clidname(char dname[HEXDIR_LEN], const struct xdr_netobj *clname) 97 { 98 u8 digest[MD5_DIGEST_SIZE]; 99 100 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 101 clname->len, clname->data); 102 103 md5(clname->data, clname->len, digest); 104 105 static_assert(HEXDIR_LEN == 2 * MD5_DIGEST_SIZE + 1); 106 sprintf(dname, "%*phN", MD5_DIGEST_SIZE, digest); 107 } 108 109 static void 110 __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp, 111 char *dname, struct nfsd_net *nn) 112 { 113 struct xdr_netobj name = { .len = strlen(dname), .data = dname }; 114 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 115 struct nfs4_client_reclaim *crp; 116 117 crp = nfs4_client_to_reclaim(name, princhash, nn); 118 crp->cr_clp = clp; 119 } 120 121 static void 122 nfsd4_create_clid_dir(struct nfs4_client *clp) 123 { 124 const struct cred *original_cred; 125 char dname[HEXDIR_LEN]; 126 struct dentry *dir, *dentry; 127 int status; 128 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 129 130 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 131 return; 132 if (!nn->rec_file) 133 return; 134 135 nfs4_make_rec_clidname(dname, &clp->cl_name); 136 137 status = nfs4_save_creds(&original_cred); 138 if (status < 0) 139 return; 140 141 status = mnt_want_write_file(nn->rec_file); 142 if (status) 143 goto out_creds; 144 145 dir = nn->rec_file->f_path.dentry; 146 147 dentry = start_creating(&nop_mnt_idmap, dir, &QSTR(dname)); 148 if (IS_ERR(dentry)) { 149 status = PTR_ERR(dentry); 150 goto out; 151 } 152 if (d_really_is_positive(dentry)) 153 /* 154 * In the 4.1 case, where we're called from 155 * reclaim_complete(), records from the previous reboot 156 * may still be left, so this is OK. 157 * 158 * In the 4.0 case, we should never get here; but we may 159 * as well be forgiving and just succeed silently. 160 */ 161 goto out_end; 162 dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, 0700, NULL); 163 if (IS_ERR(dentry)) 164 status = PTR_ERR(dentry); 165 out_end: 166 end_creating(dentry); 167 out: 168 if (status == 0) { 169 if (nn->in_grace) 170 __nfsd4_create_reclaim_record_grace(clp, dname, nn); 171 vfs_fsync(nn->rec_file, 0); 172 } else { 173 printk(KERN_ERR "NFSD: failed to write recovery record" 174 " (err %d); please check that %s exists" 175 " and is writeable", status, 176 user_recovery_dirname); 177 } 178 mnt_drop_write_file(nn->rec_file); 179 out_creds: 180 nfs4_reset_creds(original_cred); 181 } 182 183 typedef int (recdir_func)(struct dentry *, char *, struct nfsd_net *); 184 185 struct name_list { 186 char name[HEXDIR_LEN]; 187 struct list_head list; 188 }; 189 190 struct nfs4_dir_ctx { 191 struct dir_context ctx; 192 struct list_head names; 193 }; 194 195 static bool 196 nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen, 197 loff_t offset, u64 ino, unsigned int d_type) 198 { 199 struct nfs4_dir_ctx *ctx = 200 container_of(__ctx, struct nfs4_dir_ctx, ctx); 201 struct name_list *entry; 202 203 if (namlen != HEXDIR_LEN - 1) 204 return true; 205 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL); 206 if (entry == NULL) 207 return false; 208 memcpy(entry->name, name, HEXDIR_LEN - 1); 209 entry->name[HEXDIR_LEN - 1] = '\0'; 210 list_add(&entry->list, &ctx->names); 211 return true; 212 } 213 214 static int 215 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 216 { 217 const struct cred *original_cred; 218 struct dentry *dir = nn->rec_file->f_path.dentry; 219 struct nfs4_dir_ctx ctx = { 220 .ctx.actor = nfsd4_build_namelist, 221 .names = LIST_HEAD_INIT(ctx.names) 222 }; 223 struct name_list *entry, *tmp; 224 int status; 225 226 status = nfs4_save_creds(&original_cred); 227 if (status < 0) 228 return status; 229 230 status = vfs_llseek(nn->rec_file, 0, SEEK_SET); 231 if (status < 0) { 232 nfs4_reset_creds(original_cred); 233 return status; 234 } 235 236 status = iterate_dir(nn->rec_file, &ctx.ctx); 237 238 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 239 if (!status) 240 status = f(dir, entry->name, nn); 241 242 list_del(&entry->list); 243 kfree(entry); 244 } 245 nfs4_reset_creds(original_cred); 246 247 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 248 dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name); 249 list_del(&entry->list); 250 kfree(entry); 251 } 252 return status; 253 } 254 255 static int 256 nfsd4_unlink_clid_dir(char *name, struct nfsd_net *nn) 257 { 258 struct dentry *dir, *dentry; 259 int status; 260 261 dprintk("NFSD: nfsd4_unlink_clid_dir. name %s\n", name); 262 263 dir = nn->rec_file->f_path.dentry; 264 dentry = start_removing(&nop_mnt_idmap, dir, &QSTR(name)); 265 if (IS_ERR(dentry)) 266 return PTR_ERR(dentry); 267 268 status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry, NULL); 269 end_removing(dentry); 270 return status; 271 } 272 273 static void 274 __nfsd4_remove_reclaim_record_grace(const char *dname, int len, 275 struct nfsd_net *nn) 276 { 277 struct xdr_netobj name; 278 struct nfs4_client_reclaim *crp; 279 280 name.data = kmemdup(dname, len, GFP_KERNEL); 281 if (!name.data) { 282 dprintk("%s: failed to allocate memory for name.data!\n", 283 __func__); 284 return; 285 } 286 name.len = len; 287 crp = nfsd4_find_reclaim_client(name, nn); 288 kfree(name.data); 289 if (crp) 290 nfs4_remove_reclaim_record(crp, nn); 291 } 292 293 static void 294 nfsd4_remove_clid_dir(struct nfs4_client *clp) 295 { 296 const struct cred *original_cred; 297 char dname[HEXDIR_LEN]; 298 int status; 299 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 300 301 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 302 return; 303 304 nfs4_make_rec_clidname(dname, &clp->cl_name); 305 306 status = mnt_want_write_file(nn->rec_file); 307 if (status) 308 goto out; 309 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 310 311 status = nfs4_save_creds(&original_cred); 312 if (status < 0) 313 goto out_drop_write; 314 315 status = nfsd4_unlink_clid_dir(dname, nn); 316 nfs4_reset_creds(original_cred); 317 if (status == 0) { 318 vfs_fsync(nn->rec_file, 0); 319 if (nn->in_grace) 320 __nfsd4_remove_reclaim_record_grace(dname, 321 HEXDIR_LEN, nn); 322 } 323 out_drop_write: 324 mnt_drop_write_file(nn->rec_file); 325 out: 326 if (status) 327 printk("NFSD: Failed to remove expired client state directory" 328 " %.*s\n", HEXDIR_LEN, dname); 329 } 330 331 static int 332 purge_old(struct dentry *parent, char *cname, struct nfsd_net *nn) 333 { 334 int status; 335 struct dentry *child; 336 struct xdr_netobj name; 337 338 if (strlen(cname) != HEXDIR_LEN - 1) { 339 printk("%s: illegal name %s in recovery directory\n", 340 __func__, cname); 341 /* Keep trying; maybe the others are OK: */ 342 return 0; 343 } 344 name.data = kstrdup(cname, GFP_KERNEL); 345 if (!name.data) { 346 dprintk("%s: failed to allocate memory for name.data!\n", 347 __func__); 348 goto out; 349 } 350 name.len = HEXDIR_LEN; 351 if (nfs4_has_reclaimed_state(name, nn)) 352 goto out_free; 353 354 inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); 355 child = lookup_one(&nop_mnt_idmap, &QSTR(cname), parent); 356 if (!IS_ERR(child)) { 357 status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child, NULL); 358 if (status) 359 printk("failed to remove client recovery directory %pd\n", 360 child); 361 dput(child); 362 } 363 inode_unlock(d_inode(parent)); 364 365 out_free: 366 kfree(name.data); 367 out: 368 /* Keep trying, success or failure: */ 369 return 0; 370 } 371 372 static void 373 nfsd4_recdir_purge_old(struct nfsd_net *nn) 374 { 375 int status; 376 377 nn->in_grace = false; 378 if (!nn->rec_file) 379 return; 380 status = mnt_want_write_file(nn->rec_file); 381 if (status) 382 goto out; 383 status = nfsd4_list_rec_dir(purge_old, nn); 384 if (status == 0) 385 vfs_fsync(nn->rec_file, 0); 386 mnt_drop_write_file(nn->rec_file); 387 out: 388 nfs4_release_reclaim(nn); 389 if (status) 390 printk("nfsd4: failed to purge old clients from recovery" 391 " directory %pD\n", nn->rec_file); 392 } 393 394 static int 395 load_recdir(struct dentry *parent, char *cname, struct nfsd_net *nn) 396 { 397 struct xdr_netobj name = { .len = HEXDIR_LEN, .data = cname }; 398 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 399 400 if (strlen(cname) != HEXDIR_LEN - 1) { 401 printk("%s: illegal name %s in recovery directory\n", 402 __func__, cname); 403 /* Keep trying; maybe the others are OK: */ 404 return 0; 405 } 406 nfs4_client_to_reclaim(name, princhash, nn); 407 return 0; 408 } 409 410 static int 411 nfsd4_recdir_load(struct net *net) { 412 int status; 413 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 414 415 if (!nn->rec_file) 416 return 0; 417 418 status = nfsd4_list_rec_dir(load_recdir, nn); 419 if (status) 420 printk("nfsd4: failed loading clients from recovery" 421 " directory %pD\n", nn->rec_file); 422 return status; 423 } 424 425 /* 426 * Hold reference to the recovery directory. 427 */ 428 429 static int 430 nfsd4_init_recdir(struct net *net) 431 { 432 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 433 const struct cred *original_cred; 434 int status; 435 436 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 437 user_recovery_dirname); 438 439 BUG_ON(nn->rec_file); 440 441 status = nfs4_save_creds(&original_cred); 442 if (status < 0) { 443 printk("NFSD: Unable to change credentials to find recovery" 444 " directory: error %d\n", 445 status); 446 return status; 447 } 448 449 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 450 if (IS_ERR(nn->rec_file)) { 451 printk("NFSD: unable to find recovery directory %s\n", 452 user_recovery_dirname); 453 status = PTR_ERR(nn->rec_file); 454 nn->rec_file = NULL; 455 } 456 457 nfs4_reset_creds(original_cred); 458 if (!status) 459 nn->in_grace = true; 460 return status; 461 } 462 463 static void 464 nfsd4_shutdown_recdir(struct net *net) 465 { 466 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 467 468 if (!nn->rec_file) 469 return; 470 fput(nn->rec_file); 471 nn->rec_file = NULL; 472 } 473 474 static int 475 nfs4_legacy_state_init(struct net *net) 476 { 477 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 478 int i; 479 480 nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, 481 sizeof(struct list_head), 482 GFP_KERNEL); 483 if (!nn->reclaim_str_hashtbl) 484 return -ENOMEM; 485 486 for (i = 0; i < CLIENT_HASH_SIZE; i++) 487 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 488 nn->reclaim_str_hashtbl_size = 0; 489 490 return 0; 491 } 492 493 static void 494 nfs4_legacy_state_shutdown(struct net *net) 495 { 496 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 497 498 kfree(nn->reclaim_str_hashtbl); 499 } 500 501 static int 502 nfsd4_load_reboot_recovery_data(struct net *net) 503 { 504 int status; 505 506 status = nfsd4_init_recdir(net); 507 if (status) 508 return status; 509 510 status = nfsd4_recdir_load(net); 511 if (status) 512 nfsd4_shutdown_recdir(net); 513 514 return status; 515 } 516 517 static int 518 nfsd4_legacy_tracking_init(struct net *net) 519 { 520 int status; 521 522 /* XXX: The legacy code won't work in a container */ 523 if (net != &init_net) { 524 pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\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 pr_info("NFSD: Using legacy client tracking operations.\n"); 536 return 0; 537 538 err: 539 nfs4_legacy_state_shutdown(net); 540 return status; 541 } 542 543 static void 544 nfsd4_legacy_tracking_exit(struct net *net) 545 { 546 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 547 548 nfs4_release_reclaim(nn); 549 nfsd4_shutdown_recdir(net); 550 nfs4_legacy_state_shutdown(net); 551 } 552 553 /* 554 * Change the NFSv4 recovery directory to recdir. 555 */ 556 int 557 nfs4_reset_recoverydir(char *recdir) 558 { 559 int status; 560 struct path path; 561 562 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 563 if (status) 564 return status; 565 status = -ENOTDIR; 566 if (d_is_dir(path.dentry)) { 567 strscpy(user_recovery_dirname, recdir, 568 sizeof(user_recovery_dirname)); 569 status = 0; 570 } 571 path_put(&path); 572 return status; 573 } 574 575 char * 576 nfs4_recoverydir(void) 577 { 578 return user_recovery_dirname; 579 } 580 581 static int 582 nfsd4_check_legacy_client(struct nfs4_client *clp) 583 { 584 char dname[HEXDIR_LEN]; 585 struct nfs4_client_reclaim *crp; 586 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 587 struct xdr_netobj name; 588 589 /* did we already find that this client is stable? */ 590 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 591 return 0; 592 593 nfs4_make_rec_clidname(dname, &clp->cl_name); 594 595 /* look for it in the reclaim hashtable otherwise */ 596 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 597 if (!name.data) { 598 dprintk("%s: failed to allocate memory for name.data!\n", 599 __func__); 600 goto out_enoent; 601 } 602 name.len = HEXDIR_LEN; 603 crp = nfsd4_find_reclaim_client(name, nn); 604 kfree(name.data); 605 if (crp) { 606 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 607 crp->cr_clp = clp; 608 return 0; 609 } 610 611 out_enoent: 612 return -ENOENT; 613 } 614 615 static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 616 .init = nfsd4_legacy_tracking_init, 617 .exit = nfsd4_legacy_tracking_exit, 618 .create = nfsd4_create_clid_dir, 619 .remove = nfsd4_remove_clid_dir, 620 .check = nfsd4_check_legacy_client, 621 .grace_done = nfsd4_recdir_purge_old, 622 .version = 1, 623 .msglen = 0, 624 }; 625 #endif /* CONFIG_NFSD_LEGACY_CLIENT_TRACKING */ 626 627 /* Globals */ 628 #define NFSD_PIPE_DIR "nfsd" 629 #define NFSD_CLD_PIPE "cld" 630 631 /* per-net-ns structure for holding cld upcall info */ 632 struct cld_net { 633 struct rpc_pipe *cn_pipe; 634 spinlock_t cn_lock; 635 struct list_head cn_list; 636 unsigned int cn_xid; 637 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 638 bool cn_has_legacy; 639 #endif 640 }; 641 642 struct cld_upcall { 643 struct list_head cu_list; 644 struct cld_net *cu_net; 645 struct completion cu_done; 646 union { 647 struct cld_msg_hdr cu_hdr; 648 struct cld_msg cu_msg; 649 struct cld_msg_v2 cu_msg_v2; 650 } cu_u; 651 }; 652 653 static int 654 __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 655 { 656 int ret; 657 struct rpc_pipe_msg msg; 658 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u); 659 660 memset(&msg, 0, sizeof(msg)); 661 msg.data = cmsg; 662 msg.len = nn->client_tracking_ops->msglen; 663 664 ret = rpc_queue_upcall(pipe, &msg); 665 if (ret < 0) { 666 goto out; 667 } 668 669 wait_for_completion(&cup->cu_done); 670 671 if (msg.errno < 0) 672 ret = msg.errno; 673 out: 674 return ret; 675 } 676 677 static int 678 cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 679 { 680 int ret; 681 682 /* 683 * -EAGAIN occurs when pipe is closed and reopened while there are 684 * upcalls queued. 685 */ 686 do { 687 ret = __cld_pipe_upcall(pipe, cmsg, nn); 688 } while (ret == -EAGAIN); 689 690 return ret; 691 } 692 693 static ssize_t 694 __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, 695 struct nfsd_net *nn) 696 { 697 uint8_t cmd, princhashlen; 698 struct xdr_netobj name, princhash = { .len = 0, .data = NULL }; 699 char *namecopy __free(kfree) = NULL; 700 char *princhashcopy __free(kfree) = NULL; 701 uint16_t namelen; 702 703 if (get_user(cmd, &cmsg->cm_cmd)) { 704 dprintk("%s: error when copying cmd from userspace", __func__); 705 return -EFAULT; 706 } 707 if (cmd == Cld_GraceStart) { 708 if (nn->client_tracking_ops->version >= 2) { 709 const struct cld_clntinfo __user *ci; 710 711 ci = &cmsg->cm_u.cm_clntinfo; 712 if (get_user(namelen, &ci->cc_name.cn_len)) 713 return -EFAULT; 714 if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) { 715 dprintk("%s: invalid namelen (%u)", __func__, namelen); 716 return -EINVAL; 717 } 718 namecopy = memdup_user(&ci->cc_name.cn_id, namelen); 719 if (IS_ERR(namecopy)) 720 return PTR_ERR(namecopy); 721 name.data = namecopy; 722 name.len = namelen; 723 get_user(princhashlen, &ci->cc_princhash.cp_len); 724 if (princhashlen > 0) { 725 princhashcopy = memdup_user( 726 &ci->cc_princhash.cp_data, 727 princhashlen); 728 if (IS_ERR(princhashcopy)) 729 return PTR_ERR(princhashcopy); 730 princhash.data = princhashcopy; 731 princhash.len = princhashlen; 732 } else 733 princhash.len = 0; 734 } else { 735 const struct cld_name __user *cnm; 736 737 cnm = &cmsg->cm_u.cm_name; 738 if (get_user(namelen, &cnm->cn_len)) 739 return -EFAULT; 740 if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) { 741 dprintk("%s: invalid namelen (%u)", __func__, namelen); 742 return -EINVAL; 743 } 744 namecopy = memdup_user(&cnm->cn_id, namelen); 745 if (IS_ERR(namecopy)) 746 return PTR_ERR(namecopy); 747 name.data = namecopy; 748 name.len = namelen; 749 } 750 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 751 if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) { 752 struct cld_net *cn = nn->cld_net; 753 754 name.len = name.len - 5; 755 name.data = name.data + 5; 756 cn->cn_has_legacy = true; 757 } 758 #endif 759 if (!nfs4_client_to_reclaim(name, princhash, nn)) 760 return -EFAULT; 761 return nn->client_tracking_ops->msglen; 762 } 763 return -EFAULT; 764 } 765 766 static ssize_t 767 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 768 { 769 struct cld_upcall *tmp, *cup; 770 struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src; 771 struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src; 772 uint32_t xid; 773 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info, 774 nfsd_net_id); 775 struct cld_net *cn = nn->cld_net; 776 int16_t status; 777 778 if (mlen != nn->client_tracking_ops->msglen) { 779 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, 780 nn->client_tracking_ops->msglen); 781 return -EINVAL; 782 } 783 784 /* copy just the xid so we can try to find that */ 785 if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) { 786 dprintk("%s: error when copying xid from userspace", __func__); 787 return -EFAULT; 788 } 789 790 /* 791 * copy the status so we know whether to remove the upcall from the 792 * list (for -EINPROGRESS, we just want to make sure the xid is 793 * valid, not remove the upcall from the list) 794 */ 795 if (get_user(status, &hdr->cm_status)) { 796 dprintk("%s: error when copying status from userspace", __func__); 797 return -EFAULT; 798 } 799 800 /* walk the list and find corresponding xid */ 801 cup = NULL; 802 spin_lock(&cn->cn_lock); 803 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 804 if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) { 805 cup = tmp; 806 if (status != -EINPROGRESS) 807 list_del_init(&cup->cu_list); 808 break; 809 } 810 } 811 spin_unlock(&cn->cn_lock); 812 813 /* couldn't find upcall? */ 814 if (!cup) { 815 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 816 return -EINVAL; 817 } 818 819 if (status == -EINPROGRESS) 820 return __cld_pipe_inprogress_downcall(cmsg, nn); 821 822 if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0) 823 return -EFAULT; 824 825 complete(&cup->cu_done); 826 return mlen; 827 } 828 829 static void 830 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 831 { 832 struct cld_msg *cmsg = msg->data; 833 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, 834 cu_u.cu_msg); 835 836 /* errno >= 0 means we got a downcall */ 837 if (msg->errno >= 0) 838 return; 839 840 complete(&cup->cu_done); 841 } 842 843 static const struct rpc_pipe_ops cld_upcall_ops = { 844 .upcall = rpc_pipe_generic_upcall, 845 .downcall = cld_pipe_downcall, 846 .destroy_msg = cld_pipe_destroy_msg, 847 }; 848 849 static int 850 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 851 { 852 struct dentry *dir; 853 int err; 854 855 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 856 if (dir == NULL) 857 return -ENOENT; 858 err = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 859 dput(dir); 860 return err; 861 } 862 863 static int 864 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 865 { 866 struct super_block *sb; 867 int err; 868 869 sb = rpc_get_sb_net(net); 870 if (!sb) 871 return 0; 872 err = nfsd4_cld_register_sb(sb, pipe); 873 rpc_put_sb_net(net); 874 return err; 875 } 876 877 static void 878 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 879 { 880 struct super_block *sb; 881 882 sb = rpc_get_sb_net(net); 883 if (sb) { 884 rpc_unlink(pipe); 885 rpc_put_sb_net(net); 886 } 887 } 888 889 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 890 static int 891 __nfsd4_init_cld_pipe(struct net *net) 892 { 893 int ret; 894 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 895 struct cld_net *cn; 896 897 if (nn->cld_net) 898 return 0; 899 900 cn = kzalloc(sizeof(*cn), GFP_KERNEL); 901 if (!cn) { 902 ret = -ENOMEM; 903 goto err; 904 } 905 906 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 907 if (IS_ERR(cn->cn_pipe)) { 908 ret = PTR_ERR(cn->cn_pipe); 909 goto err; 910 } 911 spin_lock_init(&cn->cn_lock); 912 INIT_LIST_HEAD(&cn->cn_list); 913 914 ret = nfsd4_cld_register_net(net, cn->cn_pipe); 915 if (unlikely(ret)) 916 goto err_destroy_data; 917 918 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 919 cn->cn_has_legacy = false; 920 #endif 921 nn->cld_net = cn; 922 return 0; 923 924 err_destroy_data: 925 rpc_destroy_pipe_data(cn->cn_pipe); 926 err: 927 kfree(cn); 928 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 929 ret); 930 return ret; 931 } 932 933 static int 934 nfsd4_init_cld_pipe(struct net *net) 935 { 936 int status; 937 938 status = __nfsd4_init_cld_pipe(net); 939 if (!status) 940 pr_info("NFSD: Using old nfsdcld client tracking operations.\n"); 941 return status; 942 } 943 944 static void 945 nfsd4_remove_cld_pipe(struct net *net) 946 { 947 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 948 struct cld_net *cn = nn->cld_net; 949 950 nfsd4_cld_unregister_net(net, cn->cn_pipe); 951 rpc_destroy_pipe_data(cn->cn_pipe); 952 kfree(nn->cld_net); 953 nn->cld_net = NULL; 954 } 955 956 static struct cld_upcall * 957 alloc_cld_upcall(struct nfsd_net *nn) 958 { 959 struct cld_upcall *new, *tmp; 960 struct cld_net *cn = nn->cld_net; 961 962 new = kzalloc(sizeof(*new), GFP_KERNEL); 963 if (!new) 964 return new; 965 966 /* FIXME: hard cap on number in flight? */ 967 restart_search: 968 spin_lock(&cn->cn_lock); 969 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 970 if (tmp->cu_u.cu_msg.cm_xid == cn->cn_xid) { 971 cn->cn_xid++; 972 spin_unlock(&cn->cn_lock); 973 goto restart_search; 974 } 975 } 976 init_completion(&new->cu_done); 977 new->cu_u.cu_msg.cm_vers = nn->client_tracking_ops->version; 978 put_unaligned(cn->cn_xid++, &new->cu_u.cu_msg.cm_xid); 979 new->cu_net = cn; 980 list_add(&new->cu_list, &cn->cn_list); 981 spin_unlock(&cn->cn_lock); 982 983 dprintk("%s: allocated xid %u\n", __func__, new->cu_u.cu_msg.cm_xid); 984 985 return new; 986 } 987 988 static void 989 free_cld_upcall(struct cld_upcall *victim) 990 { 991 struct cld_net *cn = victim->cu_net; 992 993 spin_lock(&cn->cn_lock); 994 list_del(&victim->cu_list); 995 spin_unlock(&cn->cn_lock); 996 kfree(victim); 997 } 998 999 /* Ask daemon to create a new record */ 1000 static void 1001 nfsd4_cld_create(struct nfs4_client *clp) 1002 { 1003 int ret; 1004 struct cld_upcall *cup; 1005 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1006 struct cld_net *cn = nn->cld_net; 1007 1008 /* Don't upcall if it's already stored */ 1009 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1010 return; 1011 1012 cup = alloc_cld_upcall(nn); 1013 if (!cup) { 1014 ret = -ENOMEM; 1015 goto out_err; 1016 } 1017 1018 cup->cu_u.cu_msg.cm_cmd = Cld_Create; 1019 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1020 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1021 clp->cl_name.len); 1022 1023 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1024 if (!ret) { 1025 ret = cup->cu_u.cu_msg.cm_status; 1026 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1027 } 1028 1029 free_cld_upcall(cup); 1030 out_err: 1031 if (ret) 1032 printk(KERN_ERR "NFSD: Unable to create client " 1033 "record on stable storage: %d\n", ret); 1034 } 1035 1036 /* Ask daemon to create a new record */ 1037 static void 1038 nfsd4_cld_create_v2(struct nfs4_client *clp) 1039 { 1040 int ret; 1041 struct cld_upcall *cup; 1042 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1043 struct cld_net *cn = nn->cld_net; 1044 struct cld_msg_v2 *cmsg; 1045 char *principal = NULL; 1046 1047 /* Don't upcall if it's already stored */ 1048 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1049 return; 1050 1051 cup = alloc_cld_upcall(nn); 1052 if (!cup) { 1053 ret = -ENOMEM; 1054 goto out_err; 1055 } 1056 1057 cmsg = &cup->cu_u.cu_msg_v2; 1058 cmsg->cm_cmd = Cld_Create; 1059 cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len; 1060 memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data, 1061 clp->cl_name.len); 1062 if (clp->cl_cred.cr_raw_principal) 1063 principal = clp->cl_cred.cr_raw_principal; 1064 else if (clp->cl_cred.cr_principal) 1065 principal = clp->cl_cred.cr_principal; 1066 if (principal) { 1067 sha256(principal, strlen(principal), 1068 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data); 1069 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = SHA256_DIGEST_SIZE; 1070 } else 1071 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0; 1072 1073 ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn); 1074 if (!ret) { 1075 ret = cmsg->cm_status; 1076 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1077 } 1078 1079 free_cld_upcall(cup); 1080 out_err: 1081 if (ret) 1082 pr_err("NFSD: Unable to create client record on stable storage: %d\n", 1083 ret); 1084 } 1085 1086 /* Ask daemon to create a new record */ 1087 static void 1088 nfsd4_cld_remove(struct nfs4_client *clp) 1089 { 1090 int ret; 1091 struct cld_upcall *cup; 1092 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1093 struct cld_net *cn = nn->cld_net; 1094 1095 /* Don't upcall if it's already removed */ 1096 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1097 return; 1098 1099 cup = alloc_cld_upcall(nn); 1100 if (!cup) { 1101 ret = -ENOMEM; 1102 goto out_err; 1103 } 1104 1105 cup->cu_u.cu_msg.cm_cmd = Cld_Remove; 1106 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1107 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1108 clp->cl_name.len); 1109 1110 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1111 if (!ret) { 1112 ret = cup->cu_u.cu_msg.cm_status; 1113 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1114 } 1115 1116 free_cld_upcall(cup); 1117 out_err: 1118 if (ret) 1119 printk(KERN_ERR "NFSD: Unable to remove client " 1120 "record from stable storage: %d\n", ret); 1121 } 1122 1123 /* 1124 * For older nfsdcld's that do not allow us to "slurp" the clients 1125 * from the tracking database during startup. 1126 * 1127 * Check for presence of a record, and update its timestamp 1128 */ 1129 static int 1130 nfsd4_cld_check_v0(struct nfs4_client *clp) 1131 { 1132 int ret; 1133 struct cld_upcall *cup; 1134 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1135 struct cld_net *cn = nn->cld_net; 1136 1137 /* Don't upcall if one was already stored during this grace pd */ 1138 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1139 return 0; 1140 1141 cup = alloc_cld_upcall(nn); 1142 if (!cup) { 1143 printk(KERN_ERR "NFSD: Unable to check client record on " 1144 "stable storage: %d\n", -ENOMEM); 1145 return -ENOMEM; 1146 } 1147 1148 cup->cu_u.cu_msg.cm_cmd = Cld_Check; 1149 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1150 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1151 clp->cl_name.len); 1152 1153 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1154 if (!ret) { 1155 ret = cup->cu_u.cu_msg.cm_status; 1156 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1157 } 1158 1159 free_cld_upcall(cup); 1160 return ret; 1161 } 1162 1163 /* 1164 * For newer nfsdcld's that allow us to "slurp" the clients 1165 * from the tracking database during startup. 1166 * 1167 * Check for presence of a record in the reclaim_str_hashtbl 1168 */ 1169 static int 1170 nfsd4_cld_check(struct nfs4_client *clp) 1171 { 1172 struct nfs4_client_reclaim *crp; 1173 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1174 1175 /* did we already find that this client is stable? */ 1176 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1177 return 0; 1178 1179 /* look for it in the reclaim hashtable otherwise */ 1180 crp = nfsd4_find_reclaim_client(clp->cl_name, nn); 1181 if (crp) 1182 goto found; 1183 1184 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1185 if (nn->cld_net->cn_has_legacy) { 1186 char dname[HEXDIR_LEN]; 1187 struct xdr_netobj name; 1188 1189 nfs4_make_rec_clidname(dname, &clp->cl_name); 1190 1191 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 1192 if (!name.data) { 1193 dprintk("%s: failed to allocate memory for name.data!\n", 1194 __func__); 1195 return -ENOENT; 1196 } 1197 name.len = HEXDIR_LEN; 1198 crp = nfsd4_find_reclaim_client(name, nn); 1199 kfree(name.data); 1200 if (crp) 1201 goto found; 1202 1203 } 1204 #endif 1205 return -ENOENT; 1206 found: 1207 crp->cr_clp = clp; 1208 return 0; 1209 } 1210 1211 static int 1212 nfsd4_cld_check_v2(struct nfs4_client *clp) 1213 { 1214 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1215 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1216 struct cld_net *cn = nn->cld_net; 1217 #endif 1218 struct nfs4_client_reclaim *crp; 1219 char *principal = NULL; 1220 1221 /* did we already find that this client is stable? */ 1222 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1223 return 0; 1224 1225 /* look for it in the reclaim hashtable otherwise */ 1226 crp = nfsd4_find_reclaim_client(clp->cl_name, nn); 1227 if (crp) 1228 goto found; 1229 1230 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1231 if (cn->cn_has_legacy) { 1232 struct xdr_netobj name; 1233 char dname[HEXDIR_LEN]; 1234 1235 nfs4_make_rec_clidname(dname, &clp->cl_name); 1236 1237 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 1238 if (!name.data) { 1239 dprintk("%s: failed to allocate memory for name.data\n", 1240 __func__); 1241 return -ENOENT; 1242 } 1243 name.len = HEXDIR_LEN; 1244 crp = nfsd4_find_reclaim_client(name, nn); 1245 kfree(name.data); 1246 if (crp) 1247 goto found; 1248 1249 } 1250 #endif 1251 return -ENOENT; 1252 found: 1253 if (crp->cr_princhash.len) { 1254 u8 digest[SHA256_DIGEST_SIZE]; 1255 1256 if (clp->cl_cred.cr_raw_principal) 1257 principal = clp->cl_cred.cr_raw_principal; 1258 else if (clp->cl_cred.cr_principal) 1259 principal = clp->cl_cred.cr_principal; 1260 if (principal == NULL) 1261 return -ENOENT; 1262 sha256(principal, strlen(principal), digest); 1263 if (memcmp(crp->cr_princhash.data, digest, 1264 crp->cr_princhash.len)) 1265 return -ENOENT; 1266 } 1267 crp->cr_clp = clp; 1268 return 0; 1269 } 1270 1271 static int 1272 nfsd4_cld_grace_start(struct nfsd_net *nn) 1273 { 1274 int ret; 1275 struct cld_upcall *cup; 1276 struct cld_net *cn = nn->cld_net; 1277 1278 cup = alloc_cld_upcall(nn); 1279 if (!cup) { 1280 ret = -ENOMEM; 1281 goto out_err; 1282 } 1283 1284 cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart; 1285 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1286 if (!ret) 1287 ret = cup->cu_u.cu_msg.cm_status; 1288 1289 free_cld_upcall(cup); 1290 out_err: 1291 if (ret) 1292 dprintk("%s: Unable to get clients from userspace: %d\n", 1293 __func__, ret); 1294 return ret; 1295 } 1296 1297 /* For older nfsdcld's that need cm_gracetime */ 1298 static void 1299 nfsd4_cld_grace_done_v0(struct nfsd_net *nn) 1300 { 1301 int ret; 1302 struct cld_upcall *cup; 1303 struct cld_net *cn = nn->cld_net; 1304 1305 cup = alloc_cld_upcall(nn); 1306 if (!cup) { 1307 ret = -ENOMEM; 1308 goto out_err; 1309 } 1310 1311 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1312 cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time; 1313 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1314 if (!ret) 1315 ret = cup->cu_u.cu_msg.cm_status; 1316 1317 free_cld_upcall(cup); 1318 out_err: 1319 if (ret) 1320 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1321 } 1322 1323 /* 1324 * For newer nfsdcld's that do not need cm_gracetime. We also need to call 1325 * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl. 1326 */ 1327 static void 1328 nfsd4_cld_grace_done(struct nfsd_net *nn) 1329 { 1330 int ret; 1331 struct cld_upcall *cup; 1332 struct cld_net *cn = nn->cld_net; 1333 1334 cup = alloc_cld_upcall(nn); 1335 if (!cup) { 1336 ret = -ENOMEM; 1337 goto out_err; 1338 } 1339 1340 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1341 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1342 if (!ret) 1343 ret = cup->cu_u.cu_msg.cm_status; 1344 1345 free_cld_upcall(cup); 1346 out_err: 1347 nfs4_release_reclaim(nn); 1348 if (ret) 1349 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1350 } 1351 1352 static int 1353 nfs4_cld_state_init(struct net *net) 1354 { 1355 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1356 int i; 1357 1358 nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE, 1359 sizeof(struct list_head), 1360 GFP_KERNEL); 1361 if (!nn->reclaim_str_hashtbl) 1362 return -ENOMEM; 1363 1364 for (i = 0; i < CLIENT_HASH_SIZE; i++) 1365 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 1366 nn->reclaim_str_hashtbl_size = 0; 1367 nn->track_reclaim_completes = true; 1368 atomic_set(&nn->nr_reclaim_complete, 0); 1369 1370 return 0; 1371 } 1372 1373 static void 1374 nfs4_cld_state_shutdown(struct net *net) 1375 { 1376 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1377 1378 nn->track_reclaim_completes = false; 1379 kfree(nn->reclaim_str_hashtbl); 1380 } 1381 1382 static bool 1383 cld_running(struct nfsd_net *nn) 1384 { 1385 struct cld_net *cn = nn->cld_net; 1386 struct rpc_pipe *pipe = cn->cn_pipe; 1387 1388 return pipe->nreaders || pipe->nwriters; 1389 } 1390 1391 static int 1392 nfsd4_cld_get_version(struct nfsd_net *nn) 1393 { 1394 int ret = 0; 1395 struct cld_upcall *cup; 1396 struct cld_net *cn = nn->cld_net; 1397 uint8_t version; 1398 1399 cup = alloc_cld_upcall(nn); 1400 if (!cup) { 1401 ret = -ENOMEM; 1402 goto out_err; 1403 } 1404 cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion; 1405 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1406 if (!ret) { 1407 ret = cup->cu_u.cu_msg.cm_status; 1408 if (ret) 1409 goto out_free; 1410 version = cup->cu_u.cu_msg.cm_u.cm_version; 1411 dprintk("%s: userspace returned version %u\n", 1412 __func__, version); 1413 if (version < 1) 1414 version = 1; 1415 else if (version > CLD_UPCALL_VERSION) 1416 version = CLD_UPCALL_VERSION; 1417 1418 switch (version) { 1419 case 1: 1420 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1421 break; 1422 case 2: 1423 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2; 1424 break; 1425 default: 1426 break; 1427 } 1428 } 1429 out_free: 1430 free_cld_upcall(cup); 1431 out_err: 1432 if (ret) 1433 dprintk("%s: Unable to get version from userspace: %d\n", 1434 __func__, ret); 1435 return ret; 1436 } 1437 1438 static int 1439 nfsd4_cld_tracking_init(struct net *net) 1440 { 1441 int status; 1442 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1443 bool running; 1444 int retries = 10; 1445 1446 status = nfs4_cld_state_init(net); 1447 if (status) 1448 return status; 1449 1450 status = __nfsd4_init_cld_pipe(net); 1451 if (status) 1452 goto err_shutdown; 1453 1454 /* 1455 * rpc pipe upcalls take 30 seconds to time out, so we don't want to 1456 * queue an upcall unless we know that nfsdcld is running (because we 1457 * want this to fail fast so that nfsd4_client_tracking_init() can try 1458 * the next client tracking method). nfsdcld should already be running 1459 * before nfsd is started, so the wait here is for nfsdcld to open the 1460 * pipefs file we just created. 1461 */ 1462 while (!(running = cld_running(nn)) && retries--) 1463 msleep(100); 1464 1465 if (!running) { 1466 status = -ETIMEDOUT; 1467 goto err_remove; 1468 } 1469 1470 status = nfsd4_cld_get_version(nn); 1471 if (status == -EOPNOTSUPP) 1472 pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n"); 1473 1474 status = nfsd4_cld_grace_start(nn); 1475 if (status) { 1476 if (status == -EOPNOTSUPP) 1477 pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n"); 1478 nfs4_release_reclaim(nn); 1479 goto err_remove; 1480 } else 1481 pr_info("NFSD: Using nfsdcld client tracking operations.\n"); 1482 return 0; 1483 1484 err_remove: 1485 nfsd4_remove_cld_pipe(net); 1486 err_shutdown: 1487 nfs4_cld_state_shutdown(net); 1488 return status; 1489 } 1490 1491 static void 1492 nfsd4_cld_tracking_exit(struct net *net) 1493 { 1494 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1495 1496 nfs4_release_reclaim(nn); 1497 nfsd4_remove_cld_pipe(net); 1498 nfs4_cld_state_shutdown(net); 1499 } 1500 1501 /* For older nfsdcld's */ 1502 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = { 1503 .init = nfsd4_init_cld_pipe, 1504 .exit = nfsd4_remove_cld_pipe, 1505 .create = nfsd4_cld_create, 1506 .remove = nfsd4_cld_remove, 1507 .check = nfsd4_cld_check_v0, 1508 .grace_done = nfsd4_cld_grace_done_v0, 1509 .version = 1, 1510 .msglen = sizeof(struct cld_msg), 1511 }; 1512 1513 /* For newer nfsdcld's */ 1514 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1515 .init = nfsd4_cld_tracking_init, 1516 .exit = nfsd4_cld_tracking_exit, 1517 .create = nfsd4_cld_create, 1518 .remove = nfsd4_cld_remove, 1519 .check = nfsd4_cld_check, 1520 .grace_done = nfsd4_cld_grace_done, 1521 .version = 1, 1522 .msglen = sizeof(struct cld_msg), 1523 }; 1524 1525 /* v2 create/check ops include the principal, if available */ 1526 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = { 1527 .init = nfsd4_cld_tracking_init, 1528 .exit = nfsd4_cld_tracking_exit, 1529 .create = nfsd4_cld_create_v2, 1530 .remove = nfsd4_cld_remove, 1531 .check = nfsd4_cld_check_v2, 1532 .grace_done = nfsd4_cld_grace_done, 1533 .version = 2, 1534 .msglen = sizeof(struct cld_msg_v2), 1535 }; 1536 1537 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1538 /* upcall via usermodehelper */ 1539 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; 1540 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), 1541 S_IRUGO|S_IWUSR); 1542 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 1543 1544 static bool cltrack_legacy_disable; 1545 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); 1546 MODULE_PARM_DESC(cltrack_legacy_disable, 1547 "Disable legacy recoverydir conversion. Default: false"); 1548 1549 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1550 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1551 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION=" 1552 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START=" 1553 1554 static char * 1555 nfsd4_cltrack_legacy_topdir(void) 1556 { 1557 int copied; 1558 size_t len; 1559 char *result; 1560 1561 if (cltrack_legacy_disable) 1562 return NULL; 1563 1564 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) + 1565 strlen(nfs4_recoverydir()) + 1; 1566 1567 result = kmalloc(len, GFP_KERNEL); 1568 if (!result) 1569 return result; 1570 1571 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s", 1572 nfs4_recoverydir()); 1573 if (copied >= len) { 1574 /* just return nothing if output was truncated */ 1575 kfree(result); 1576 return NULL; 1577 } 1578 1579 return result; 1580 } 1581 1582 static char * 1583 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name) 1584 { 1585 int copied; 1586 size_t len; 1587 char *result; 1588 1589 if (cltrack_legacy_disable) 1590 return NULL; 1591 1592 /* +1 is for '/' between "topdir" and "recdir" */ 1593 len = strlen(LEGACY_RECDIR_ENV_PREFIX) + 1594 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN; 1595 1596 result = kmalloc(len, GFP_KERNEL); 1597 if (!result) 1598 return result; 1599 1600 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/", 1601 nfs4_recoverydir()); 1602 if (copied > (len - HEXDIR_LEN)) { 1603 /* just return nothing if output will be truncated */ 1604 kfree(result); 1605 return NULL; 1606 } 1607 1608 nfs4_make_rec_clidname(result + copied, name); 1609 1610 return result; 1611 } 1612 1613 static char * 1614 nfsd4_cltrack_client_has_session(struct nfs4_client *clp) 1615 { 1616 int copied; 1617 size_t len; 1618 char *result; 1619 1620 /* prefix + Y/N character + terminating NULL */ 1621 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1; 1622 1623 result = kmalloc(len, GFP_KERNEL); 1624 if (!result) 1625 return result; 1626 1627 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c", 1628 clp->cl_minorversion ? 'Y' : 'N'); 1629 if (copied >= len) { 1630 /* just return nothing if output was truncated */ 1631 kfree(result); 1632 return NULL; 1633 } 1634 1635 return result; 1636 } 1637 1638 static char * 1639 nfsd4_cltrack_grace_start(time64_t grace_start) 1640 { 1641 int copied; 1642 size_t len; 1643 char *result; 1644 1645 /* prefix + max width of int64_t string + terminating NULL */ 1646 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1; 1647 1648 result = kmalloc(len, GFP_KERNEL); 1649 if (!result) 1650 return result; 1651 1652 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld", 1653 grace_start); 1654 if (copied >= len) { 1655 /* just return nothing if output was truncated */ 1656 kfree(result); 1657 return NULL; 1658 } 1659 1660 return result; 1661 } 1662 1663 static int 1664 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1) 1665 { 1666 char *envp[3]; 1667 char *argv[4]; 1668 int ret; 1669 1670 if (unlikely(!cltrack_prog[0])) { 1671 dprintk("%s: cltrack_prog is disabled\n", __func__); 1672 return -EACCES; 1673 } 1674 1675 dprintk("%s: cmd: %s\n", __func__, cmd); 1676 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1677 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)"); 1678 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)"); 1679 1680 envp[0] = env0; 1681 envp[1] = env1; 1682 envp[2] = NULL; 1683 1684 argv[0] = (char *)cltrack_prog; 1685 argv[1] = cmd; 1686 argv[2] = arg; 1687 argv[3] = NULL; 1688 1689 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); 1690 /* 1691 * Disable the upcall mechanism if we're getting an ENOENT or EACCES 1692 * error. The admin can re-enable it on the fly by using sysfs 1693 * once the problem has been fixed. 1694 */ 1695 if (ret == -ENOENT || ret == -EACCES) { 1696 dprintk("NFSD: %s was not found or isn't executable (%d). " 1697 "Setting cltrack_prog to blank string!", 1698 cltrack_prog, ret); 1699 cltrack_prog[0] = '\0'; 1700 } 1701 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret); 1702 1703 return ret; 1704 } 1705 1706 static char * 1707 bin_to_hex_dup(const unsigned char *src, int srclen) 1708 { 1709 char *buf; 1710 1711 /* +1 for terminating NULL */ 1712 buf = kzalloc((srclen * 2) + 1, GFP_KERNEL); 1713 if (!buf) 1714 return buf; 1715 1716 bin2hex(buf, src, srclen); 1717 return buf; 1718 } 1719 1720 static int 1721 nfsd4_umh_cltrack_init(struct net *net) 1722 { 1723 int ret; 1724 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1725 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1726 1727 /* XXX: The usermode helper s not working in container yet. */ 1728 if (net != &init_net) { 1729 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n"); 1730 kfree(grace_start); 1731 return -EINVAL; 1732 } 1733 1734 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); 1735 kfree(grace_start); 1736 if (!ret) 1737 pr_info("NFSD: Using UMH upcall client tracking operations.\n"); 1738 return ret; 1739 } 1740 1741 static void 1742 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp) 1743 { 1744 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK, 1745 TASK_UNINTERRUPTIBLE); 1746 } 1747 1748 static void 1749 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp) 1750 { 1751 clear_and_wake_up_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags); 1752 } 1753 1754 static void 1755 nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1756 { 1757 char *hexid, *has_session, *grace_start; 1758 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1759 1760 /* 1761 * With v4.0 clients, there's little difference in outcome between a 1762 * create and check operation, and we can end up calling into this 1763 * function multiple times per client (once for each openowner). So, 1764 * for v4.0 clients skip upcalling once the client has been recorded 1765 * on stable storage. 1766 * 1767 * For v4.1+ clients, the outcome of the two operations is different, 1768 * so we must ensure that we upcall for the create operation. v4.1+ 1769 * clients call this on RECLAIM_COMPLETE though, so we should only end 1770 * up doing a single create upcall per client. 1771 */ 1772 if (clp->cl_minorversion == 0 && 1773 test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1774 return; 1775 1776 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1777 if (!hexid) { 1778 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1779 return; 1780 } 1781 1782 has_session = nfsd4_cltrack_client_has_session(clp); 1783 grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1784 1785 nfsd4_cltrack_upcall_lock(clp); 1786 if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start)) 1787 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1788 nfsd4_cltrack_upcall_unlock(clp); 1789 1790 kfree(has_session); 1791 kfree(grace_start); 1792 kfree(hexid); 1793 } 1794 1795 static void 1796 nfsd4_umh_cltrack_remove(struct nfs4_client *clp) 1797 { 1798 char *hexid; 1799 1800 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1801 return; 1802 1803 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1804 if (!hexid) { 1805 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1806 return; 1807 } 1808 1809 nfsd4_cltrack_upcall_lock(clp); 1810 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) && 1811 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0) 1812 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1813 nfsd4_cltrack_upcall_unlock(clp); 1814 1815 kfree(hexid); 1816 } 1817 1818 static int 1819 nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1820 { 1821 int ret; 1822 char *hexid, *has_session, *legacy; 1823 1824 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1825 return 0; 1826 1827 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1828 if (!hexid) { 1829 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1830 return -ENOMEM; 1831 } 1832 1833 has_session = nfsd4_cltrack_client_has_session(clp); 1834 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1835 1836 nfsd4_cltrack_upcall_lock(clp); 1837 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) { 1838 ret = 0; 1839 } else { 1840 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy); 1841 if (ret == 0) 1842 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1843 } 1844 nfsd4_cltrack_upcall_unlock(clp); 1845 kfree(has_session); 1846 kfree(legacy); 1847 kfree(hexid); 1848 1849 return ret; 1850 } 1851 1852 static void 1853 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) 1854 { 1855 char *legacy; 1856 char timestr[22]; /* FIXME: better way to determine max size? */ 1857 1858 sprintf(timestr, "%lld", nn->boot_time); 1859 legacy = nfsd4_cltrack_legacy_topdir(); 1860 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL); 1861 kfree(legacy); 1862 } 1863 1864 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1865 .init = nfsd4_umh_cltrack_init, 1866 .exit = NULL, 1867 .create = nfsd4_umh_cltrack_create, 1868 .remove = nfsd4_umh_cltrack_remove, 1869 .check = nfsd4_umh_cltrack_check, 1870 .grace_done = nfsd4_umh_cltrack_grace_done, 1871 .version = 1, 1872 .msglen = 0, 1873 }; 1874 1875 static inline int check_for_legacy_methods(int status, struct net *net) 1876 { 1877 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1878 struct path path; 1879 1880 /* 1881 * Next, try the UMH upcall. 1882 */ 1883 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 1884 status = nn->client_tracking_ops->init(net); 1885 if (!status) 1886 return status; 1887 1888 /* 1889 * Finally, See if the recoverydir exists and is a directory. 1890 * If it is, then use the legacy ops. 1891 */ 1892 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 1893 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 1894 if (!status) { 1895 status = !d_is_dir(path.dentry); 1896 path_put(&path); 1897 if (status) 1898 return -ENOTDIR; 1899 } 1900 return status; 1901 } 1902 #else 1903 static inline int check_for_legacy_methods(int status, struct net *net) 1904 { 1905 return status; 1906 } 1907 #endif /* CONFIG_LEGACY_NFSD_CLIENT_TRACKING */ 1908 1909 int 1910 nfsd4_client_tracking_init(struct net *net) 1911 { 1912 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1913 int status; 1914 1915 /* just run the init if it the method is already decided */ 1916 if (nn->client_tracking_ops) 1917 goto do_init; 1918 1919 /* First, try to use nfsdcld */ 1920 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1921 status = nn->client_tracking_ops->init(net); 1922 if (!status) 1923 return status; 1924 if (status != -ETIMEDOUT) { 1925 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0; 1926 status = nn->client_tracking_ops->init(net); 1927 if (!status) 1928 return status; 1929 } 1930 1931 status = check_for_legacy_methods(status, net); 1932 if (status) 1933 goto out; 1934 do_init: 1935 status = nn->client_tracking_ops->init(net); 1936 out: 1937 if (status) { 1938 pr_warn("NFSD: Unable to initialize client recovery tracking! (%d)\n", status); 1939 pr_warn("NFSD: Is nfsdcld running? If not, enable CONFIG_NFSD_LEGACY_CLIENT_TRACKING.\n"); 1940 nn->client_tracking_ops = NULL; 1941 } 1942 return status; 1943 } 1944 1945 void 1946 nfsd4_client_tracking_exit(struct net *net) 1947 { 1948 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1949 1950 if (nn->client_tracking_ops) { 1951 if (nn->client_tracking_ops->exit) 1952 nn->client_tracking_ops->exit(net); 1953 nn->client_tracking_ops = NULL; 1954 } 1955 } 1956 1957 void 1958 nfsd4_client_record_create(struct nfs4_client *clp) 1959 { 1960 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1961 1962 if (nn->client_tracking_ops) 1963 nn->client_tracking_ops->create(clp); 1964 } 1965 1966 void 1967 nfsd4_client_record_remove(struct nfs4_client *clp) 1968 { 1969 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1970 1971 if (nn->client_tracking_ops) 1972 nn->client_tracking_ops->remove(clp); 1973 } 1974 1975 int 1976 nfsd4_client_record_check(struct nfs4_client *clp) 1977 { 1978 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1979 1980 if (nn->client_tracking_ops) 1981 return nn->client_tracking_ops->check(clp); 1982 1983 return -EOPNOTSUPP; 1984 } 1985 1986 void 1987 nfsd4_record_grace_done(struct nfsd_net *nn) 1988 { 1989 if (nn->client_tracking_ops) 1990 nn->client_tracking_ops->grace_done(nn); 1991 } 1992 1993 static int 1994 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 1995 { 1996 struct super_block *sb = ptr; 1997 struct net *net = sb->s_fs_info; 1998 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1999 struct cld_net *cn = nn->cld_net; 2000 int ret = 0; 2001 2002 if (!try_module_get(THIS_MODULE)) 2003 return 0; 2004 2005 if (!cn) { 2006 module_put(THIS_MODULE); 2007 return 0; 2008 } 2009 2010 switch (event) { 2011 case RPC_PIPEFS_MOUNT: 2012 ret = nfsd4_cld_register_sb(sb, cn->cn_pipe); 2013 break; 2014 case RPC_PIPEFS_UMOUNT: 2015 rpc_unlink(cn->cn_pipe); 2016 break; 2017 default: 2018 ret = -ENOTSUPP; 2019 break; 2020 } 2021 module_put(THIS_MODULE); 2022 return ret; 2023 } 2024 2025 static struct notifier_block nfsd4_cld_block = { 2026 .notifier_call = rpc_pipefs_event, 2027 }; 2028 2029 int 2030 register_cld_notifier(void) 2031 { 2032 WARN_ON(!nfsd_net_id); 2033 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 2034 } 2035 2036 void 2037 unregister_cld_notifier(void) 2038 { 2039 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 2040 } 2041