diff options
author | Alexey Kodanev <alexey.kodanev@oracle.com> | 2015-03-11 07:29:17 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-11 21:25:13 -0400 |
commit | b1cb59cf2efe7971d3d72a7b963d09a512d994c9 (patch) | |
tree | a751b241287689004faf9e1d4d6a970c2d0b173c /net | |
parent | d578e18ce93f5d33a7120fd57c453e22a4c0fc37 (diff) |
net: sysctl_net_core: check SNDBUF and RCVBUF for min length
sysctl has sysctl.net.core.rmem_*/wmem_* parameters which can be
set to incorrect values. Given that 'struct sk_buff' allocates from
rcvbuf, incorrectly set buffer length could result to memory
allocation failures. For example, set them as follows:
# sysctl net.core.rmem_default=64
net.core.wmem_default = 64
# sysctl net.core.wmem_default=64
net.core.wmem_default = 64
# ping localhost -s 1024 -i 0 > /dev/null
This could result to the following failure:
skbuff: skb_over_panic: text:ffffffff81628db4 len:-32 put:-32
head:ffff88003a1cc200 data:ffff88003a1cc200 tail:0xffffffe0 end:0xc0 dev:<NULL>
kernel BUG at net/core/skbuff.c:102!
invalid opcode: 0000 [#1] SMP
...
task: ffff88003b7f5550 ti: ffff88003ae88000 task.ti: ffff88003ae88000
RIP: 0010:[<ffffffff8155fbd1>] [<ffffffff8155fbd1>] skb_put+0xa1/0xb0
RSP: 0018:ffff88003ae8bc68 EFLAGS: 00010296
RAX: 000000000000008d RBX: 00000000ffffffe0 RCX: 0000000000000000
RDX: ffff88003fdcf598 RSI: ffff88003fdcd9c8 RDI: ffff88003fdcd9c8
RBP: ffff88003ae8bc88 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000001 R11: 00000000000002b2 R12: 0000000000000000
R13: 0000000000000000 R14: ffff88003d3f7300 R15: ffff88000012a900
FS: 00007fa0e2b4a840(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000d0f7e0 CR3: 000000003b8fb000 CR4: 00000000000006f0
Stack:
ffff88003a1cc200 00000000ffffffe0 00000000000000c0 ffffffff818cab1d
ffff88003ae8bd68 ffffffff81628db4 ffff88003ae8bd48 ffff88003b7f5550
ffff880031a09408 ffff88003b7f5550 ffff88000012aa48 ffff88000012ab00
Call Trace:
[<ffffffff81628db4>] unix_stream_sendmsg+0x2c4/0x470
[<ffffffff81556f56>] sock_write_iter+0x146/0x160
[<ffffffff811d9612>] new_sync_write+0x92/0xd0
[<ffffffff811d9cd6>] vfs_write+0xd6/0x180
[<ffffffff811da499>] SyS_write+0x59/0xd0
[<ffffffff81651532>] system_call_fastpath+0x12/0x17
Code: 00 00 48 89 44 24 10 8b 87 c8 00 00 00 48 89 44 24 08 48 8b 87 d8 00
00 00 48 c7 c7 30 db 91 81 48 89 04 24 31 c0 e8 4f a8 0e 00 <0f> 0b
eb fe 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 48 83
RIP [<ffffffff8155fbd1>] skb_put+0xa1/0xb0
RSP <ffff88003ae8bc68>
Kernel panic - not syncing: Fatal exception
Moreover, the possible minimum is 1, so we can get another kernel panic:
...
BUG: unable to handle kernel paging request at ffff88013caee5c0
IP: [<ffffffff815604cf>] __alloc_skb+0x12f/0x1f0
...
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/sysctl_net_core.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 433424804284..8ce351ffceb1 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -25,6 +25,8 @@ | |||
25 | static int zero = 0; | 25 | static int zero = 0; |
26 | static int one = 1; | 26 | static int one = 1; |
27 | static int ushort_max = USHRT_MAX; | 27 | static int ushort_max = USHRT_MAX; |
28 | static int min_sndbuf = SOCK_MIN_SNDBUF; | ||
29 | static int min_rcvbuf = SOCK_MIN_RCVBUF; | ||
28 | 30 | ||
29 | static int net_msg_warn; /* Unused, but still a sysctl */ | 31 | static int net_msg_warn; /* Unused, but still a sysctl */ |
30 | 32 | ||
@@ -237,7 +239,7 @@ static struct ctl_table net_core_table[] = { | |||
237 | .maxlen = sizeof(int), | 239 | .maxlen = sizeof(int), |
238 | .mode = 0644, | 240 | .mode = 0644, |
239 | .proc_handler = proc_dointvec_minmax, | 241 | .proc_handler = proc_dointvec_minmax, |
240 | .extra1 = &one, | 242 | .extra1 = &min_sndbuf, |
241 | }, | 243 | }, |
242 | { | 244 | { |
243 | .procname = "rmem_max", | 245 | .procname = "rmem_max", |
@@ -245,7 +247,7 @@ static struct ctl_table net_core_table[] = { | |||
245 | .maxlen = sizeof(int), | 247 | .maxlen = sizeof(int), |
246 | .mode = 0644, | 248 | .mode = 0644, |
247 | .proc_handler = proc_dointvec_minmax, | 249 | .proc_handler = proc_dointvec_minmax, |
248 | .extra1 = &one, | 250 | .extra1 = &min_rcvbuf, |
249 | }, | 251 | }, |
250 | { | 252 | { |
251 | .procname = "wmem_default", | 253 | .procname = "wmem_default", |
@@ -253,7 +255,7 @@ static struct ctl_table net_core_table[] = { | |||
253 | .maxlen = sizeof(int), | 255 | .maxlen = sizeof(int), |
254 | .mode = 0644, | 256 | .mode = 0644, |
255 | .proc_handler = proc_dointvec_minmax, | 257 | .proc_handler = proc_dointvec_minmax, |
256 | .extra1 = &one, | 258 | .extra1 = &min_sndbuf, |
257 | }, | 259 | }, |
258 | { | 260 | { |
259 | .procname = "rmem_default", | 261 | .procname = "rmem_default", |
@@ -261,7 +263,7 @@ static struct ctl_table net_core_table[] = { | |||
261 | .maxlen = sizeof(int), | 263 | .maxlen = sizeof(int), |
262 | .mode = 0644, | 264 | .mode = 0644, |
263 | .proc_handler = proc_dointvec_minmax, | 265 | .proc_handler = proc_dointvec_minmax, |
264 | .extra1 = &one, | 266 | .extra1 = &min_rcvbuf, |
265 | }, | 267 | }, |
266 | { | 268 | { |
267 | .procname = "dev_weight", | 269 | .procname = "dev_weight", |