History

SUNRPC: Do not dereference non-socket transports in sysfs

Do not cast the struct xprt to a sock_xprt unless we know it is a UDP or TCP transport. Otherwise the call to lock the mutex will scribble over whatever structure is actually there. This has been seen to cause hard system lockups when the underlying transport was RDMA.

Trond Myklebust committed 4 years ago

Commit 421ab1b1 parent 1d15d124 files · +54 −31Browse files

Unified · Split

4 files
  1. include/linux/sunrpc/xprt.h +3 −0
  2. include/linux/sunrpc/xprtsock.h +0 −1
  3. net/sunrpc/sysfs.c +27 −28
  4. net/sunrpc/xprtsock.c +24 −2
include/linux/sunrpc/xprt.h+3−0
@@ -139,6 +139,9 @@ struct rpc_xprt_ops { · 138 unmodified lines
139139 void (*rpcbind)(struct rpc_task *task);
140140 void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
141141 void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
142+ int (*get_srcaddr)(struct rpc_xprt *xprt, char *buf,
143+ size_t buflen);
144+ unsigned short (*get_srcport)(struct rpc_xprt *xprt);
142145 int (*buf_alloc)(struct rpc_task *task);
143146 void (*buf_free)(struct rpc_task *task);
144147 void (*prepare_request)(struct rpc_rqst *req);
include/linux/sunrpc/xprtsock.h+0−1
@@ -10,7 +10,6 @@ · 9 unmodified lines
1010
1111 int init_socket_xprt(void);
1212 void cleanup_socket_xprt(void);
13−unsigned short get_srcport(struct rpc_xprt *);
1413
1514 #define RPC_MIN_RESVPORT (1U)
1615 #define RPC_MAX_RESVPORT (65535U)
net/sunrpc/sysfs.c+27−28
@@ -97,7 +97,7 @@ static ssize_t rpc_sysfs_xprt_dstaddr_show(struct kobject *kobj, · 96 unmodified lines
9797 return 0;
9898 ret = sprintf(buf, "%s\n", xprt->address_strings[RPC_DISPLAY_ADDR]);
9999 xprt_put(xprt);
100− return ret + 1;
100+ return ret;
101101 }
102102
103103 static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj,
@@ -105,33 +105,31 @@ static ssize_t rpc_sysfs_xprt_srcaddr_show(struct kobject *kobj, · 1 unmodified line
105105 char *buf)
106106 {
107107 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
108− struct sockaddr_storage saddr;
109− struct sock_xprt *sock;
110− ssize_t ret = -1;
108+ size_t buflen = PAGE_SIZE;
109+ ssize_t ret = -ENOTSOCK;
111110
112111 if (!xprt || !xprt_connected(xprt)) {
113− xprt_put(xprt);
114− return -ENOTCONN;
112+ ret = -ENOTCONN;
113+ } else if (xprt->ops->get_srcaddr) {
114+ ret = xprt->ops->get_srcaddr(xprt, buf, buflen);
115+ if (ret > 0) {
116+ if (ret < buflen - 1) {
117+ buf[ret] = '\n';
118+ ret++;
119+ buf[ret] = '\0';
120+ }
121+ }
115122 }
116−
117− sock = container_of(xprt, struct sock_xprt, xprt);
118− mutex_lock(&sock->recv_mutex);
119− if (sock->sock == NULL ||
120− kernel_getsockname(sock->sock, (struct sockaddr *)&saddr) < 0)
121− goto out;
122−
123− ret = sprintf(buf, "%pISc\n", &saddr);
124−out:
125− mutex_unlock(&sock->recv_mutex);
126123 xprt_put(xprt);
127− return ret + 1;
124+ return ret;
128125 }
129126
130127 static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj,
131− struct kobj_attribute *attr,
132− char *buf)
128+ struct kobj_attribute *attr, char *buf)
133129 {
134130 struct rpc_xprt *xprt = rpc_sysfs_xprt_kobj_get_xprt(kobj);
131+ unsigned short srcport = 0;
132+ size_t buflen = PAGE_SIZE;
135133 ssize_t ret;
136134
137135 if (!xprt || !xprt_connected(xprt)) {
@@ -139,7 +137,11 @@ static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj, · 1 unmodified line
139137 return -ENOTCONN;
140138 }
141139
142− ret = sprintf(buf, "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
140+ if (xprt->ops->get_srcport)
141+ srcport = xprt->ops->get_srcport(xprt);
142+
143+ ret = snprintf(buf, buflen,
144+ "last_used=%lu\ncur_cong=%lu\ncong_win=%lu\n"
143145 "max_num_slots=%u\nmin_num_slots=%u\nnum_reqs=%u\n"
144146 "binding_q_len=%u\nsending_q_len=%u\npending_q_len=%u\n"
145147 "backlog_q_len=%u\nmain_xprt=%d\nsrc_port=%u\n"
@@ -147,14 +149,11 @@ static ssize_t rpc_sysfs_xprt_info_show(struct kobject *kobj, · 1 unmodified line
147149 xprt->last_used, xprt->cong, xprt->cwnd, xprt->max_reqs,
148150 xprt->min_reqs, xprt->num_reqs, xprt->binding.qlen,
149151 xprt->sending.qlen, xprt->pending.qlen,
150− xprt->backlog.qlen, xprt->main,
151− (xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
152− get_srcport(xprt) : 0,
152+ xprt->backlog.qlen, xprt->main, srcport,
153153 atomic_long_read(&xprt->queuelen),
154− (xprt->xprt_class->ident == XPRT_TRANSPORT_TCP) ?
155− xprt->address_strings[RPC_DISPLAY_PORT] : "0");
154+ xprt->address_strings[RPC_DISPLAY_PORT]);
156155 xprt_put(xprt);
157− return ret + 1;
156+ return ret;
158157 }
159158
160159 static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj,
@@ -201,7 +200,7 @@ static ssize_t rpc_sysfs_xprt_state_show(struct kobject *kobj, · 40 unmodified lines
201200 }
202201
203202 xprt_put(xprt);
204− return ret + 1;
203+ return ret;
205204 }
206205
207206 static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj,
@@ -220,7 +219,7 @@ static ssize_t rpc_sysfs_xprt_switch_info_show(struct kobject *kobj, · 12 unmodified lines
220219 xprt_switch->xps_nunique_destaddr_xprts,
221220 atomic_long_read(&xprt_switch->xps_queuelen));
222221 xprt_switch_put(xprt_switch);
223− return ret + 1;
222+ return ret;
224223 }
225224
226225 static ssize_t rpc_sysfs_xprt_dstaddr_store(struct kobject *kobj,
net/sunrpc/xprtsock.c+24−2
@@ -1638,7 +1638,7 @@ static int xs_get_srcport(struct sock_xprt *transport) · 1637 unmodified lines
16381638 return port;
16391639 }
16401640
1641−unsigned short get_srcport(struct rpc_xprt *xprt)
1641+static unsigned short xs_sock_srcport(struct rpc_xprt *xprt)
16421642 {
16431643 struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
16441644 unsigned short ret = 0;
@@ -1648,7 +1648,25 @@ unsigned short get_srcport(struct rpc_xprt *xprt) · 3 unmodified lines
16481648 mutex_unlock(&sock->recv_mutex);
16491649 return ret;
16501650 }
1651−EXPORT_SYMBOL(get_srcport);
1651+
1652+static int xs_sock_srcaddr(struct rpc_xprt *xprt, char *buf, size_t buflen)
1653+{
1654+ struct sock_xprt *sock = container_of(xprt, struct sock_xprt, xprt);
1655+ union {
1656+ struct sockaddr sa;
1657+ struct sockaddr_storage st;
1658+ } saddr;
1659+ int ret = -ENOTCONN;
1660+
1661+ mutex_lock(&sock->recv_mutex);
1662+ if (sock->sock) {
1663+ ret = kernel_getsockname(sock->sock, &saddr.sa);
1664+ if (ret >= 0)
1665+ ret = snprintf(buf, buflen, "%pISc", &saddr.sa);
1666+ }
1667+ mutex_unlock(&sock->recv_mutex);
1668+ return ret;
1669+}
16521670
16531671 static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
16541672 {
@@ -2622,6 +2640,8 @@ static const struct rpc_xprt_ops xs_udp_ops = { · 967 unmodified lines
26222640 .rpcbind = rpcb_getport_async,
26232641 .set_port = xs_set_port,
26242642 .connect = xs_connect,
2643+ .get_srcaddr = xs_sock_srcaddr,
2644+ .get_srcport = xs_sock_srcport,
26252645 .buf_alloc = rpc_malloc,
26262646 .buf_free = rpc_free,
26272647 .send_request = xs_udp_send_request,
@@ -2644,6 +2664,8 @@ static const struct rpc_xprt_ops xs_tcp_ops = { · 16 unmodified lines
26442664 .rpcbind = rpcb_getport_async,
26452665 .set_port = xs_set_port,
26462666 .connect = xs_connect,
2667+ .get_srcaddr = xs_sock_srcaddr,
2668+ .get_srcport = xs_sock_srcport,
26472669 .buf_alloc = rpc_malloc,
26482670 .buf_free = rpc_free,
26492671 .prepare_request = xs_stream_prepare_request,