aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-06-10 17:30:37 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-10 21:14:47 -0400
commit0e119b41b7f23e08799fa8b1c9c1360d7da75815 (patch)
treefc3ba1393a946cb83ce51b6194fa57fa35d32128
parentbc6e1ea32c26ead06063a882e802fff7ab6535c2 (diff)
rxrpc: Limit the listening backlog
Limit the socket incoming call backlog queue size so that a remote client can't pump in sufficient new calls that the server runs out of memory. Note that this is partially theoretical at the moment since whilst the number of calls is limited, the number of packets trying to set up new calls is not. This will be addressed in a later patch. If the caller of listen() specifies a backlog INT_MAX, then they get the current maximum; anything else greater than max_backlog or anything negative incurs EINVAL. The limit on the maximum queue size can be set by: echo N >/proc/sys/net/rxrpc/max_backlog where 4<=N<=32. Further, set the default backlog to 0, requiring listen() to be called before we start actually queueing new calls. Whilst this kind of is a change in the UAPI, the caller can't actually *accept* new calls anyway unless they've first called listen() to put the socket into the LISTENING state - thus the aforementioned new calls would otherwise just sit there, eating up kernel memory. (Note that sockets that don't have a non-zero service ID bound don't get incoming calls anyway.) Given that the default backlog is now 0, make the AFS filesystem call kernel_listen() to set the maximum backlog for itself. Possible improvements include: (1) Trimming a too-large backlog to max_backlog when listen is called. (2) Trimming the backlog value whenever the value is used so that changes to max_backlog are applied to an open socket automatically. Note that the AFS filesystem opens one socket and keeps it open for extended periods, so would miss out on changes to max_backlog. (3) Having a separate setting for the AFS filesystem. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--fs/afs/rxrpc.c34
-rw-r--r--net/rxrpc/af_rxrpc.c19
-rw-r--r--net/rxrpc/ar-internal.h1
-rw-r--r--net/rxrpc/misc.c6
-rw-r--r--net/rxrpc/sysctl.c10
5 files changed, 47 insertions, 23 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 63cd9f939f19..4832de84d52c 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -85,18 +85,14 @@ int afs_open_socket(void)
85 85
86 skb_queue_head_init(&afs_incoming_calls); 86 skb_queue_head_init(&afs_incoming_calls);
87 87
88 ret = -ENOMEM;
88 afs_async_calls = create_singlethread_workqueue("kafsd"); 89 afs_async_calls = create_singlethread_workqueue("kafsd");
89 if (!afs_async_calls) { 90 if (!afs_async_calls)
90 _leave(" = -ENOMEM [wq]"); 91 goto error_0;
91 return -ENOMEM;
92 }
93 92
94 ret = sock_create_kern(&init_net, AF_RXRPC, SOCK_DGRAM, PF_INET, &socket); 93 ret = sock_create_kern(&init_net, AF_RXRPC, SOCK_DGRAM, PF_INET, &socket);
95 if (ret < 0) { 94 if (ret < 0)
96 destroy_workqueue(afs_async_calls); 95 goto error_1;
97 _leave(" = %d [socket]", ret);
98 return ret;
99 }
100 96
101 socket->sk->sk_allocation = GFP_NOFS; 97 socket->sk->sk_allocation = GFP_NOFS;
102 98
@@ -111,18 +107,26 @@ int afs_open_socket(void)
111 sizeof(srx.transport.sin.sin_addr)); 107 sizeof(srx.transport.sin.sin_addr));
112 108
113 ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx)); 109 ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
114 if (ret < 0) { 110 if (ret < 0)
115 sock_release(socket); 111 goto error_2;
116 destroy_workqueue(afs_async_calls); 112
117 _leave(" = %d [bind]", ret); 113 ret = kernel_listen(socket, INT_MAX);
118 return ret; 114 if (ret < 0)
119 } 115 goto error_2;
120 116
121 rxrpc_kernel_intercept_rx_messages(socket, afs_rx_interceptor); 117 rxrpc_kernel_intercept_rx_messages(socket, afs_rx_interceptor);
122 118
123 afs_socket = socket; 119 afs_socket = socket;
124 _leave(" = 0"); 120 _leave(" = 0");
125 return 0; 121 return 0;
122
123error_2:
124 sock_release(socket);
125error_1:
126 destroy_workqueue(afs_async_calls);
127error_0:
128 _leave(" = %d", ret);
129 return ret;
126} 130}
127 131
128/* 132/*
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 38512a200db6..a1bcb0e17250 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -33,8 +33,6 @@ unsigned int rxrpc_debug; // = RXRPC_DEBUG_KPROTO;
33module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO); 33module_param_named(debug, rxrpc_debug, uint, S_IWUSR | S_IRUGO);
34MODULE_PARM_DESC(debug, "RxRPC debugging mask"); 34MODULE_PARM_DESC(debug, "RxRPC debugging mask");
35 35
36static int sysctl_rxrpc_max_qlen __read_mostly = 10;
37
38static struct proto rxrpc_proto; 36static struct proto rxrpc_proto;
39static const struct proto_ops rxrpc_rpc_ops; 37static const struct proto_ops rxrpc_rpc_ops;
40 38
@@ -191,6 +189,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
191{ 189{
192 struct sock *sk = sock->sk; 190 struct sock *sk = sock->sk;
193 struct rxrpc_sock *rx = rxrpc_sk(sk); 191 struct rxrpc_sock *rx = rxrpc_sk(sk);
192 unsigned int max;
194 int ret; 193 int ret;
195 194
196 _enter("%p,%d", rx, backlog); 195 _enter("%p,%d", rx, backlog);
@@ -201,17 +200,21 @@ static int rxrpc_listen(struct socket *sock, int backlog)
201 case RXRPC_UNBOUND: 200 case RXRPC_UNBOUND:
202 ret = -EADDRNOTAVAIL; 201 ret = -EADDRNOTAVAIL;
203 break; 202 break;
204 case RXRPC_CLIENT_UNBOUND:
205 case RXRPC_CLIENT_BOUND:
206 default:
207 ret = -EBUSY;
208 break;
209 case RXRPC_SERVER_BOUND: 203 case RXRPC_SERVER_BOUND:
210 ASSERT(rx->local != NULL); 204 ASSERT(rx->local != NULL);
205 max = READ_ONCE(rxrpc_max_backlog);
206 ret = -EINVAL;
207 if (backlog == INT_MAX)
208 backlog = max;
209 else if (backlog < 0 || backlog > max)
210 break;
211 sk->sk_max_ack_backlog = backlog; 211 sk->sk_max_ack_backlog = backlog;
212 rx->sk.sk_state = RXRPC_SERVER_LISTENING; 212 rx->sk.sk_state = RXRPC_SERVER_LISTENING;
213 ret = 0; 213 ret = 0;
214 break; 214 break;
215 default:
216 ret = -EBUSY;
217 break;
215 } 218 }
216 219
217 release_sock(&rx->sk); 220 release_sock(&rx->sk);
@@ -591,7 +594,7 @@ static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
591 sock_init_data(sock, sk); 594 sock_init_data(sock, sk);
592 sk->sk_state = RXRPC_UNBOUND; 595 sk->sk_state = RXRPC_UNBOUND;
593 sk->sk_write_space = rxrpc_write_space; 596 sk->sk_write_space = rxrpc_write_space;
594 sk->sk_max_ack_backlog = sysctl_rxrpc_max_qlen; 597 sk->sk_max_ack_backlog = 0;
595 sk->sk_destruct = rxrpc_sock_destructor; 598 sk->sk_destruct = rxrpc_sock_destructor;
596 599
597 rx = rxrpc_sk(sk); 600 rx = rxrpc_sk(sk);
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index b89dcdcbc65a..f715cca767cd 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -641,6 +641,7 @@ extern const struct rxrpc_security rxrpc_no_security;
641/* 641/*
642 * misc.c 642 * misc.c
643 */ 643 */
644extern unsigned int rxrpc_max_backlog __read_mostly;
644extern unsigned int rxrpc_requested_ack_delay; 645extern unsigned int rxrpc_requested_ack_delay;
645extern unsigned int rxrpc_soft_ack_delay; 646extern unsigned int rxrpc_soft_ack_delay;
646extern unsigned int rxrpc_idle_ack_delay; 647extern unsigned int rxrpc_idle_ack_delay;
diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c
index 1afe9876e79f..bdc5e42fe600 100644
--- a/net/rxrpc/misc.c
+++ b/net/rxrpc/misc.c
@@ -15,6 +15,12 @@
15#include "ar-internal.h" 15#include "ar-internal.h"
16 16
17/* 17/*
18 * The maximum listening backlog queue size that may be set on a socket by
19 * listen().
20 */
21unsigned int rxrpc_max_backlog __read_mostly = 10;
22
23/*
18 * How long to wait before scheduling ACK generation after seeing a 24 * How long to wait before scheduling ACK generation after seeing a
19 * packet with RXRPC_REQUEST_ACK set (in jiffies). 25 * packet with RXRPC_REQUEST_ACK set (in jiffies).
20 */ 26 */
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c
index d20ed575acf4..a99690a8a3da 100644
--- a/net/rxrpc/sysctl.c
+++ b/net/rxrpc/sysctl.c
@@ -18,6 +18,7 @@ static struct ctl_table_header *rxrpc_sysctl_reg_table;
18static const unsigned int zero = 0; 18static const unsigned int zero = 0;
19static const unsigned int one = 1; 19static const unsigned int one = 1;
20static const unsigned int four = 4; 20static const unsigned int four = 4;
21static const unsigned int thirtytwo = 32;
21static const unsigned int n_65535 = 65535; 22static const unsigned int n_65535 = 65535;
22static const unsigned int n_max_acks = RXRPC_MAXACKS; 23static const unsigned int n_max_acks = RXRPC_MAXACKS;
23 24
@@ -100,6 +101,15 @@ static struct ctl_table rxrpc_sysctl_table[] = {
100 101
101 /* Non-time values */ 102 /* Non-time values */
102 { 103 {
104 .procname = "max_backlog",
105 .data = &rxrpc_max_backlog,
106 .maxlen = sizeof(unsigned int),
107 .mode = 0644,
108 .proc_handler = proc_dointvec_minmax,
109 .extra1 = (void *)&four,
110 .extra2 = (void *)&thirtytwo,
111 },
112 {
103 .procname = "rx_window_size", 113 .procname = "rx_window_size",
104 .data = &rxrpc_rx_window_size, 114 .data = &rxrpc_rx_window_size,
105 .maxlen = sizeof(unsigned int), 115 .maxlen = sizeof(unsigned int),