Skip to contentSkip to conversation

: NULL pointer dereference in sctp_auth_asoc_set_default_hmac

PATCH In review Joshua Kinard 3 participants 8 messages Apr 16, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 : NULL pointer dereference in sctp_auth_asoc_set_default_hmac

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id=2016

If anyone's got other ideas to try out, let me know, thanks!

Signature · 9 lines
Joshua Kinard
Gentoo/MIPS
[email protected]
4096R/D25D95E3 2011-03-28

"The past tempts us, the present confuses us, the future frightens us.  And
our lives slip away, moment by moment, lost in that vast, terrible in-between."

--Emperor Turhan, Centauri Republic
net/sctp/auth.c +1 -1
index 683c7d1..2244508 100644
@@ -618,7 +618,7 @@ void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc,
 			continue;
 
 		/* If this TFM has been allocated, use this id */
-		if (ep->auth_hmacs[id]) {
+		if (ep->auth_hmacs && ep->auth_hmacs[id]) {
 			asoc->default_hmac_id = id;
 			break;
 		}
#1 lore raw

Hi Joshua,

Quoted 17 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if
statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Quoted 3 lines

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

I presume at this point, it's net->sctp.auth_enable = 1 as we test for it here before calling sctp_auth_asoc_set_default_hmac():

	case SCTP_PARAM_HMAC_ALGO:
		if (!net->sctp.auth_enable)
			goto fall_through;

Could it be that upon sctp_endpoint_init() time in your case, sctp.auth_enable was still reset to 0, but you've set it between sctp_endpoint_init() time and before invocation of sctp_auth_asoc_set_default_hmac() to 1, so that this code path will suddenly be taken, causing the NULL ptr deref?

Quoted 11 lines

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

...

Quoted 8 lines

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Same symptoms?

Do you have a test pcap though?

Quoted 4 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

#2 lore raw
In reply to Joshua Kinard
Quoted 31 lines · Daniel Borkmann

Hi Joshua,

Quoted 17 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if
statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Quoted 3 lines

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

I presume at this point, it's net->sctp.auth_enable = 1 as we test for it here before calling sctp_auth_asoc_set_default_hmac():

    case SCTP_PARAM_HMAC_ALGO:
        if (!net->sctp.auth_enable)
            goto fall_through;
Quoted 6 lines

Could it be that upon sctp_endpoint_init() time in your case, sctp.auth_enable was still reset to 0, but you've set it between sctp_endpoint_init() time and before invocation of sctp_auth_asoc_set_default_hmac() to 1, so that this code path will suddenly be taken, causing the NULL ptr deref?

I am not real certain. I am not setting net.sctp.auth_enable in any code, but literally executing "sysctl -w net.sctp.auth_enable=1" on the command line, then switching to another box's shell in a different window and then attempting an "ssh -z ..." connection (-z is the arg the SCTP patch adds to force the SCTP protocol). That is what triggers the oops. So that sysctl flag should be set to 1 long before I even switch windows.

As long as net.sctp.auth_enable=0 when I ssh over SCTP, the oops doesn't trigger. I am not ruling out a bug in the ssh SCTP patch either, as it could malform the packet in a subtle way. WireShark reports nothing wrong, however.

Quoted 16 lines
Quoted 11 lines

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

...

Quoted 4 lines

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

Quoted 9 lines
Quoted 4 lines

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Same symptoms?

Do you have a test pcap though?

I have a PCAP file from both cases, but I haven't tried injecting that specific packet into the NIC of the affected machine to see if that will trigger the oops. I'll install tcpreplay on it and see if that does trigger the same issue for the ssh session.

Here's the Oops report off of my MIPS box. It's the same as on the AMD64 machine, I just couldn't get a clean serial capture off the console port there:

Oops[#1]:

CPU: 0 PID: 0 Comm: swapper Not tainted 3.14.1-mipsgit-20140415 #1
task: ffffffff8056ce80 ti: ffffffff8055c000 task.ti: ffffffff8055c000
$ 0   : 0000000000000000 ffffffff9401fce0 0000000000000001 0000000000000001
$ 4   : 980000005fbd6020 980000005534a0b4 0000000000000008 0000000000000001
$ 8   : 980000005fb97ca0 0000000000000000 0000000000000001 e467ef67cb335f9d
$12   : 00000000000000c1 000000000000000f 0000000000000000 ffffffffa3ab0e7f
$16   : 980000005534a064 0000000000000020 0000000000000001 980000005f6680e0
$20   : 980000005f668180 980000005534a0b4 980000005fbd6020 980000005f668180
$24   : 0000000000000004 ffffffff8043dac4
$28   : ffffffff8055c000 ffffffff8055f7b0 00000000000f4240 ffffffff8042b300
Hi    : 0000000000000002
Lo    : 0000000000000000
epc   : ffffffff8043c4e8 sctp_auth_asoc_set_default_hmac+0x68/0x80
    Not tainted
ra    : ffffffff8042b300 sctp_process_init+0x5e0/0x8a4
Status: 9401fce3        KX SX UX KERNEL EXL IE
Cause : 00000008
BadVA : 0000000000000008
PrId  : 00002733 (RM7000)
Process swapper (pid: 0, threadinfoÿffffff8055c000, taskÿffffff8056ce80,
tls00000000000000)
Stack : 980000005fbd6080 ffffffff8043107c 980000005fbd6080 980000005fbd6080
          980000005fb97d00 980000005dc14060 980000005fb97d08 ffffffff80431a14
          ffffffff80592ea0 980000005fb97ca0 980000005f6680e0 ffffffff8055f8a0
          980000005fbd6020 980000005fb97ca0 0000000000000000 980000005fb97ca0
          ffffffff8043b970 0000000000000020 ffffffff8049d030 ffffffff8042188c
          ffffffff8050ec58 0000000000000000 0000000100000000 0000000000000000
          0000000000000001 0000000000000000 ffffffff80592ea0 0000000000000000
          980000005f6680e0 ffffffff804228c8 0000000000000000 0000000000000000
          0000000000000000 0000000000000000 0000000000000000 0000000000000000
          0000000000000000 0000000000000000 0000000000000000 0000000000000000
          ...
Call Trace:
[<ffffffff8043c4e8>] sctp_auth_asoc_set_default_hmac+0x68/0x80
[<ffffffff8042b300>] sctp_process_init+0x5e0/0x8a4
[<ffffffff8042188c>] sctp_sf_do_5_1B_init+0x234/0x34c
[<ffffffff804228c8>] sctp_do_sm+0xb4/0x1e8
[<ffffffff80425a08>] sctp_endpoint_bh_rcv+0x1c4/0x214
[<ffffffff8043af68>] sctp_rcv+0x588/0x630
[<ffffffff8043e8e8>] sctp6_rcv+0x10/0x24
[<ffffffff803acb50>] ip6_input+0x2c0/0x440
[<ffffffff8030fc00>] __netif_receive_skb_core+0x4a8/0x564
[<ffffffff80310650>] process_backlog+0xb4/0x18c
[<ffffffff80313cbc>] net_rx_action+0x12c/0x210
[<ffffffff80034254>] __do_softirq+0x17c/0x2ac
[<ffffffff800345e0>] irq_exit+0x54/0xb0
[<ffffffff800075a4>] ret_from_irq+0x0/0x4
[<ffffffff800090ec>] rm7k_wait_irqoff+0x24/0x48
[<ffffffff8005e388>] cpu_startup_entry+0xc0/0x148
[<ffffffff805a88b0>] start_kernel+0x37c/0x398
Code: dd0900b8  000330f8  0126302d <dcc60000> 50c0fff1  0047182a  a48306a0
03e00008  00000000
---[ end trace b530b0551467f2fd ]---
Kernel panic - not syncing: Fatal exception in interrupt
Signature · 9 lines
Joshua Kinard
Gentoo/MIPS
[email protected]
4096R/D25D95E3 2011-03-28

"The past tempts us, the present confuses us, the future frightens us.  And
our lives slip away, moment by moment, lost in that vast, terrible in-between."

--Emperor Turhan, Centauri Republic
#3 lore raw
In reply to Joshua Kinard
Quoted 42 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Quoted 5 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

Which kernel are you running? Does it have this commit in it?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?idïb842c45e667332774196bd5a1d539d048159cc

Without that, I could see how a bug might happen...

-vlad

#4 lore raw
In reply to Joshua Kinard
Quoted 50 lines · Vlad Yasevich
Quoted 42 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Quoted 5 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

Quoted 6 lines

Which kernel are you running? Does it have this commit in it?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?idïb842c45e667332774196bd5a1d539d048159cc

Without that, I could see how a bug might happen...

-vlad

For my MIPS machine (SGI O2), 3.14.1, built off of a linux-mips git pull. For the amd64 VM, 3.14 from Gentoo's sources. I tested reversing that patch on one of my kernel trees, and it's reversible, so it's definitely included.

I haven't tried stepping through the kernel w/ kgdb yet. The MIPS machine runs headless, and breaking into kdb to set a breakpoint, then resuming kills ssh some how (still responds to pings, but won't connect), and ttyS0 gets stuck trying to talk to a remote gdb session. The amd64 VM spikes my host system's CPU when it enters the debugger, so I can't run that for too long of a time. I suppose I could enable telnet on the mips box and see if that's still usable after setting the breakpoint.

If someone wants to try and reproduce it:
1. Compile OpenSSH w/ the patch from their bugzilla #2016 (use the latest copy I uploaded for 6.6p1), making sure to enable SCTP via --with-sctp on both a client and server machine.
2. Start sshd w/ at least "Transport all" in sshd_config (the SCTP patch adds this config directive) or via the command line.
3. On sshd machine, sysctl -w net.sctp.auth_enable=1.
4. On client, ssh -z <server>, and watch the bada boom.

If there's a specific function I should go look at or pepper w/ printk() statements, let me know. Not fully familiar w/ the call chain that the SCTP stack uses when it receives an INIT chunk. If it's something bad in the INIT chunk sent by the ssh client machine, shouldn't be too hard to manually walk the functions and deduce how the code is interpreting things.

--J

#5 lore raw
In reply to Joshua Kinard
Quoted 54 lines · Joshua Kinard
Quoted 53 lines · Vlad Yasevich
Quoted 42 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Quoted 5 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

Which kernel are you running? Does it have this commit in it?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?idïb842c45e667332774196bd5a1d539d048159cc

Quoted 8 lines
Quoted 3 lines

Without that, I could see how a bug might happen...

-vlad

For my MIPS machine (SGI O2), 3.14.1, built off of a linux-mips git pull. For the amd64 VM, 3.14 from Gentoo's sources. I tested reversing that patch on one of my kernel trees, and it's reversible, so it's definitely included.

Dan and I talked and the problem is that you are starting sshd fist and then changing auth capability. Restart sshd after you change the sysctl and you should be OK.

I'll try to audit the paths and cook up a patch that plugs this hole.

Thanks
-vlad

Quoted 25 lines

I haven't tried stepping through the kernel w/ kgdb yet. The MIPS machine runs headless, and breaking into kdb to set a breakpoint, then resuming kills ssh some how (still responds to pings, but won't connect), and ttyS0 gets stuck trying to talk to a remote gdb session. The amd64 VM spikes my host system's CPU when it enters the debugger, so I can't run that for too long of a time. I suppose I could enable telnet on the mips box and see if that's still usable after setting the breakpoint.

If someone wants to try and reproduce it:
1. Compile OpenSSH w/ the patch from their bugzilla #2016 (use the latest copy I uploaded for 6.6p1), making sure to enable SCTP via --with-sctp on both a client and server machine.
2. Start sshd w/ at least "Transport all" in sshd_config (the SCTP patch adds this config directive) or via the command line.
3. On sshd machine, sysctl -w net.sctp.auth_enable=1.
4. On client, ssh -z <server>, and watch the bada boom.

If there's a specific function I should go look at or pepper w/ printk() statements, let me know. Not fully familiar w/ the call chain that the SCTP stack uses when it receives an INIT chunk. If it's something bad in the INIT chunk sent by the ssh client machine, shouldn't be too hard to manually walk the functions and deduce how the code is interpreting things.

--J

#6 lore raw
In reply to Joshua Kinard
Quoted 70 lines · Joshua Kinard
Quoted 50 lines · Vlad Yasevich
Quoted 42 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if
statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark, but nothing stands out.

Quoted 5 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

Quoted 6 lines

Which kernel are you running? Does it have this commit in it?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?idïb842c45e667332774196bd5a1d539d048159cc

Without that, I could see how a bug might happen...

-vlad

For my MIPS machine (SGI O2), 3.14.1, built off of a linux-mips git pull. For the amd64 VM, 3.14 from Gentoo's sources. I tested reversing that patch on one of my kernel trees, and it's reversible, so it's definitely included.

I haven't tried stepping through the kernel w/ kgdb yet. The MIPS machine runs headless, and breaking into kdb to set a breakpoint, then resuming kills ssh some how (still responds to pings, but won't connect), and ttyS0 gets stuck trying to talk to a remote gdb session. The amd64 VM spikes my host system's CPU when it enters the debugger, so I can't run that for too long of a time. I suppose I could enable telnet on the mips box and see if that's still usable after setting the breakpoint.

Quoted 7 lines

If someone wants to try and reproduce it:
1. Compile OpenSSH w/ the patch from their bugzilla #2016 (use the latest copy I uploaded for 6.6p1), making sure to enable SCTP via --with-sctp on both a client and server machine.
2. Start sshd w/ at least "Transport all" in sshd_config (the SCTP patch adds this config directive) or via the command line.
3. On sshd machine, sysctl -w net.sctp.auth_enable=1.

Could you give it a try and do *first* the sysctl -w net.sctp.auth_enable=1 on server side and after that start the sshd instance? We definitely need to fix that, but it seems ep is created on server side at time of auth_enable=0 and you're setting if *afterwards* to 1. Looks this needs to be made immutable during ep life-time.

Quoted 14 lines

4. On client, ssh -z <server>, and watch the bada boom.

If there's a specific function I should go look at or pepper w/ printk() statements, let me know. Not fully familiar w/ the call chain that the SCTP stack uses when it receives an INIT chunk. If it's something bad in the INIT chunk sent by the ssh client machine, shouldn't be too hard to manually walk the functions and deduce how the code is interpreting things.

--J
--
To unsubscribe from this list: send the line "unsubscribe linux-sctp" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw
In reply to Joshua Kinard
Quoted 82 lines · Daniel Borkmann
Quoted 73 lines · Joshua Kinard
Quoted 52 lines · Vlad Yasevich
Quoted 44 lines · Joshua Kinard

Hi linux-sctp,

I stumbled into a NULL pointer dereference on amd64 and mips when receiving an INIT chunk containing the HMAC Algorithm Parameter (0x8004) when net.sctp.auth_enable = 1.

From some quick debugging I did, even if net.sctp.auth_enable = 1, the if
statement on line 448 in net/sctp/auth.c::sctp_auth_init_hmacs() checks net->sctp.auth_enable and gets '0' back, which causes ep->auth_hmacs to get set to NULL:

448 if (!net->sctp.auth_enable) {
449 ep->auth_hmacs = NULL;
450 return 0;
451 }

Later, the if statement on line 621 in net/sctp/auth.c::sctp_auth_asoc_set_default_hmac() attempts to access ep->auth_hmacs without first checking for NULL, which triggers the oops:

620 /* If this TFM has been allocated, use this id */
621 if (ep->auth_hmacs[id]) {
622 asoc->default_hmac_id = id;
623 break;
624 }

I am not sure why net->sctp.auth_enable is initially returning '0' when it's
set in sysctl, and verified in /proc/sys/net/sctp/auth_enable. Adding a check for NULL on ep->auth_hmacs in the if statement stops the oops from happening, though I am not sure if this is the correct fix.

Another thing I noticed, is that I cannot trigger the Oops from the SCTP/DTLS samples on this page:
http://sctp.fh-muenster.de/dtls-samples.html

But if I patch OpenSSH with the SCTP patch below, that does trigger it on the sshd server machine as soon as I issue 'ssh -z user@host ...'. I've looked at both INIT chunks sent out by the respective programs in Wireshark,
but nothing stands out.

Quoted 5 lines

OpenSSH SCTP:
https://bugzilla.mindrot.org/show_bug.cgi?id 16

If anyone's got other ideas to try out, let me know, thanks!

Quoted 7 lines

Which kernel are you running? Does it have this commit in it?
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?idïb842c45e667332774196bd5a1d539d048159cc

Without that, I could see how a bug might happen...

-vlad

For my MIPS machine (SGI O2), 3.14.1, built off of a linux-mips git pull. For the amd64 VM, 3.14 from Gentoo's sources. I tested reversing that patch on one of my kernel trees, and it's reversible, so it's definitely included.

I haven't tried stepping through the kernel w/ kgdb yet. The MIPS machine runs headless, and breaking into kdb to set a breakpoint, then resuming kills ssh some how (still responds to pings, but won't connect), and ttyS0 gets stuck trying to talk to a remote gdb session. The amd64 VM spikes my host system's CPU when it enters the debugger, so I can't run that for too long of a time. I suppose I could enable telnet on the mips box and see if that's still usable after setting the breakpoint.

Quoted 7 lines

If someone wants to try and reproduce it:
1. Compile OpenSSH w/ the patch from their bugzilla #2016 (use the latest copy I uploaded for 6.6p1), making sure to enable SCTP via --with-sctp on both a client and server machine.
2. Start sshd w/ at least "Transport all" in sshd_config (the SCTP patch adds this config directive) or via the command line.
3. On sshd machine, sysctl -w net.sctp.auth_enable=1.

Quoted 5 lines

Could you give it a try and do *first* the sysctl -w net.sctp.auth_enable=1 on server side and after that start the sshd instance? We definitely need to fix that, but it seems ep is created on server side at time of auth_enable=0 and you're setting if *afterwards* to 1. Looks this needs to be made immutable during ep life-time.

Confirmed, this fixes it. I shut sshd down, set the sysctl flag, and then restarted it. No oops. Also, no oops if I do it in reverse. I.e., auth_enable=1, set to 0, without restarting sshd. So I guess making it immutable at some point after the after the system is booted looks like the way to go (I assume so it can be set in sysctl.conf, before the network is brought up).

Quoted 9 lines
Quoted 9 lines

4. On client, ssh -z <server>, and watch the bada boom.

If there's a specific function I should go look at or pepper w/ printk() statements, let me know. Not fully familiar w/ the call chain that the SCTP stack uses when it receives an INIT chunk. If it's something bad in the INIT chunk sent by the ssh client machine, shouldn't be too hard to manually walk the functions and deduce how the code is interpreting things.

--J