Commit 786615bc1ce84150ded80daea6bd9f6297f48e73

Authored by Trond Myklebust
1 parent 00326ed644

SUNRPC: If the rpcbind channel is disconnected, fail the call to unregister

If rpcbind causes our connection to the AF_LOCAL socket to close after
we've registered a service, then we want to be careful about reconnecting
since the mount namespace may have changed.

By simply refusing to reconnect the AF_LOCAL socket in the case of
unregister, we avoid the need to somehow save the mount namespace. While
this may lead to some services not unregistering properly, it should
be safe.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Nix <nix@esperi.org.uk>
Cc: Jeff Layton <jlayton@redhat.com>
Cc: stable@vger.kernel.org # 3.9.x

Showing 4 changed files with 33 additions and 13 deletions Side-by-side Diff

include/linux/sunrpc/sched.h
... ... @@ -121,6 +121,7 @@
121 121 #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */
122 122 #define RPC_TASK_SENT 0x0800 /* message was sent */
123 123 #define RPC_TASK_TIMEOUT 0x1000 /* fail with ETIMEDOUT on timeout */
  124 +#define RPC_TASK_NOCONNECT 0x2000 /* return ENOTCONN if not connected */
124 125  
125 126 #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC)
126 127 #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
... ... @@ -1660,6 +1660,10 @@
1660 1660 task->tk_action = call_connect_status;
1661 1661 if (task->tk_status < 0)
1662 1662 return;
  1663 + if (task->tk_flags & RPC_TASK_NOCONNECT) {
  1664 + rpc_exit(task, -ENOTCONN);
  1665 + return;
  1666 + }
1663 1667 xprt_connect(task);
1664 1668 }
1665 1669 }
... ... @@ -23,6 +23,7 @@
23 23 struct rpc_clnt *rpcb_local_clnt4;
24 24 spinlock_t rpcb_clnt_lock;
25 25 unsigned int rpcb_users;
  26 + unsigned int rpcb_is_af_local : 1;
26 27  
27 28 struct mutex gssp_lock;
28 29 wait_queue_head_t gssp_wq;
net/sunrpc/rpcb_clnt.c
... ... @@ -204,13 +204,15 @@
204 204 }
205 205  
206 206 static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
207   - struct rpc_clnt *clnt4)
  207 + struct rpc_clnt *clnt4,
  208 + bool is_af_local)
208 209 {
209 210 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
210 211  
211 212 /* Protected by rpcb_create_local_mutex */
212 213 sn->rpcb_local_clnt = clnt;
213 214 sn->rpcb_local_clnt4 = clnt4;
  215 + sn->rpcb_is_af_local = is_af_local ? 1 : 0;
214 216 smp_wmb();
215 217 sn->rpcb_users = 1;
216 218 dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: "
... ... @@ -271,7 +273,7 @@
271 273 clnt4 = NULL;
272 274 }
273 275  
274   - rpcb_set_local(net, clnt, clnt4);
  276 + rpcb_set_local(net, clnt, clnt4, true);
275 277  
276 278 out:
277 279 return result;
... ... @@ -323,7 +325,7 @@
323 325 clnt4 = NULL;
324 326 }
325 327  
326   - rpcb_set_local(net, clnt, clnt4);
  328 + rpcb_set_local(net, clnt, clnt4, false);
327 329  
328 330 out:
329 331 return result;
330 332  
331 333  
332 334  
... ... @@ -384,13 +386,16 @@
384 386 return rpc_create(&args);
385 387 }
386 388  
387   -static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg)
  389 +static int rpcb_register_call(struct sunrpc_net *sn, struct rpc_clnt *clnt, struct rpc_message *msg, bool is_set)
388 390 {
389   - int result, error = 0;
  391 + int flags = RPC_TASK_NOCONNECT;
  392 + int error, result = 0;
390 393  
  394 + if (is_set || !sn->rpcb_is_af_local)
  395 + flags = RPC_TASK_SOFTCONN;
391 396 msg->rpc_resp = &result;
392 397  
393   - error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN);
  398 + error = rpc_call_sync(clnt, msg, flags);
394 399 if (error < 0) {
395 400 dprintk("RPC: failed to contact local rpcbind "
396 401 "server (errno %d).\n", -error);
397 402  
398 403  
399 404  
... ... @@ -447,16 +452,19 @@
447 452 .rpc_argp = &map,
448 453 };
449 454 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
  455 + bool is_set = false;
450 456  
451 457 dprintk("RPC: %sregistering (%u, %u, %d, %u) with local "
452 458 "rpcbind\n", (port ? "" : "un"),
453 459 prog, vers, prot, port);
454 460  
455 461 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_UNSET];
456   - if (port)
  462 + if (port != 0) {
457 463 msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET];
  464 + is_set = true;
  465 + }
458 466  
459   - return rpcb_register_call(sn->rpcb_local_clnt, &msg);
  467 + return rpcb_register_call(sn, sn->rpcb_local_clnt, &msg, is_set);
460 468 }
461 469  
462 470 /*
... ... @@ -469,6 +477,7 @@
469 477 const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
470 478 struct rpcbind_args *map = msg->rpc_argp;
471 479 unsigned short port = ntohs(sin->sin_port);
  480 + bool is_set = false;
472 481 int result;
473 482  
474 483 map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
475 484  
476 485  
... ... @@ -479,10 +488,12 @@
479 488 map->r_addr, map->r_netid);
480 489  
481 490 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
482   - if (port)
  491 + if (port != 0) {
483 492 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
  493 + is_set = true;
  494 + }
484 495  
485   - result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
  496 + result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
486 497 kfree(map->r_addr);
487 498 return result;
488 499 }
... ... @@ -497,6 +508,7 @@
497 508 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
498 509 struct rpcbind_args *map = msg->rpc_argp;
499 510 unsigned short port = ntohs(sin6->sin6_port);
  511 + bool is_set = false;
500 512 int result;
501 513  
502 514 map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL);
503 515  
504 516  
... ... @@ -507,10 +519,12 @@
507 519 map->r_addr, map->r_netid);
508 520  
509 521 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
510   - if (port)
  522 + if (port != 0) {
511 523 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET];
  524 + is_set = true;
  525 + }
512 526  
513   - result = rpcb_register_call(sn->rpcb_local_clnt4, msg);
  527 + result = rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, is_set);
514 528 kfree(map->r_addr);
515 529 return result;
516 530 }
... ... @@ -527,7 +541,7 @@
527 541 map->r_addr = "";
528 542 msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET];
529 543  
530   - return rpcb_register_call(sn->rpcb_local_clnt4, msg);
  544 + return rpcb_register_call(sn, sn->rpcb_local_clnt4, msg, false);
531 545 }
532 546  
533 547 /**