Commit 23288376 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] Fix NFS locking over TCP

The 2.5.x RPC code is currently broken in that it demands that all
tasks that call xprt_create_proto() in order to open a TCP socket must
have CAP_NET_BIND_SERVICE capabilities, and must bind to a privileged
port.

This breaks the NLM locking code and its use of the call_bind() RPC
portmapper lookup feature.

This patch allows the built-in portmapper client to use unbound TCP
sockets if the user does not have the necessary capabilities.
parent 63a5ba42
......@@ -146,6 +146,7 @@ struct rpc_xprt {
unsigned long sockstate; /* Socket state */
unsigned char shutdown : 1, /* being shut down */
nocong : 1, /* no congestion control */
resvport : 1, /* use a reserved port */
stream : 1; /* TCP */
/*
......
......@@ -89,7 +89,7 @@ static void xprt_disconnect(struct rpc_xprt *);
static void xprt_conn_status(struct rpc_task *task);
static struct rpc_xprt * xprt_setup(int proto, struct sockaddr_in *ap,
struct rpc_timeout *to);
static struct socket *xprt_create_socket(int, struct rpc_timeout *);
static struct socket *xprt_create_socket(int, struct rpc_timeout *, int);
static void xprt_bind_socket(struct rpc_xprt *, struct socket *);
static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
......@@ -442,7 +442,7 @@ xprt_connect(struct rpc_task *task)
* Start by resetting any existing state.
*/
xprt_close(xprt);
if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout))) {
if (!(sock = xprt_create_socket(xprt->prot, &xprt->timeout, xprt->resvport))) {
/* couldn't create socket or bind to reserved port;
* this is likely a permanent error, so cause an abort */
task->tk_status = -EIO;
......@@ -1490,7 +1490,7 @@ xprt_sock_setbufsize(struct rpc_xprt *xprt)
* and connect stream sockets.
*/
static struct socket *
xprt_create_socket(int proto, struct rpc_timeout *to)
xprt_create_socket(int proto, struct rpc_timeout *to, int resvport)
{
struct socket *sock;
int type, err;
......@@ -1506,7 +1506,7 @@ xprt_create_socket(int proto, struct rpc_timeout *to)
}
/* If the caller has the capability, bind to a reserved port */
if (capable(CAP_NET_BIND_SERVICE) && xprt_bindresvport(sock) < 0) {
if (resvport && xprt_bindresvport(sock) < 0) {
printk("RPC: can't bind to reserved port.\n");
goto failed;
}
......@@ -1528,29 +1528,25 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
xprt = xprt_setup(proto, sap, to);
if (!xprt)
goto out;
goto out_bad;
xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
if (!xprt->stream) {
struct socket *sock = xprt_create_socket(proto, to);
if (sock)
xprt_bind_socket(xprt, sock);
else {
rpc_free(xprt);
xprt = NULL;
}
} else
/*
* Don't allow a TCP service user unless they have
* enough capability to bind a reserved port.
*/
if (!capable(CAP_NET_BIND_SERVICE)) {
rpc_free(xprt);
xprt = NULL;
}
struct socket *sock;
sock = xprt_create_socket(proto, to, xprt->resvport);
if (!sock)
goto out_bad;
xprt_bind_socket(xprt, sock);
}
out:
dprintk("RPC: xprt_create_proto created xprt %p\n", xprt);
return xprt;
out_bad:
dprintk("RPC: xprt_create_proto failed\n");
if (xprt)
rpc_free(xprt);
return NULL;
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment