Discussion:
[freetds] Segmentation fault when trying to connect to a listening TCP port for another service
Ramiro Morales
2013-08-20 23:46:17 UTC
Permalink
Hi all,

As reported on pymssql issue 108
(https://code.google.com/p/pymssql/issues/detail?id=108)

The original reported experienced it under Windows. IT also kills the
Python interpreter process under Linux.

Taking pymssql/Python and Windows out of the picture. With tsql:

$ tsql -H <MySQL server IP address> -p 3306
Segmentation fault

Running tsql under gdb to get the location:

$ TDVER=7.1 gdb --args tsql -H <MySQL server IP address> -p 3306
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from tsql...done.
(gdb) run
Starting program: tsql -H 172.17.2.15 -p 3306
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"

Program received signal SIGSEGV, Segmentation fault.
tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
584 memcpy(tds->in_buf, header, 8);

(gdb) bt
#0 tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
#1 0x000000000040f651 in tds8_do_login (connection=0x63e860,
tds=0x63e3e0) at login.c:1024
#2 tds_connect (tds=tds at entry=0x63e3e0,
connection=connection at entry=0x63e860,
p_oserr=p_oserr at entry=0x7fffffffddec) at login.c:456
#3 0x000000000040ffa6 in tds_connect_and_login
(tds=tds at entry=0x63e3e0, connection=connection at entry=0x63e860) at
login.c:506
#4 0x0000000000403858 in main (argc=<optimized out>, argv=<optimized
out>) at tsql.c:771

(gdb) print tds->in_buf
$1 = (unsigned char *) 0x0

(gdb) print header
$1 = "?\000\000\000\n5.0"

It doesn't happen with every remote service (e.g. with SSH it simply times out).

A patch (for the 0.91 branch):

diff --git a/src/tds/net.c b/src/tds/net.c
index 48426bb..1281613 100644
--- a/src/tds/net.c
+++ b/src/tds/net.c
@@ -579,9 +579,11 @@ tds_read_packet(TDSSOCKET * tds)
tds->in_buf_max = len;
}

- /* Clean out the in_buf so we don't use old stuff by mistake */
- memset(tds->in_buf, 0, tds->in_buf_max);
- memcpy(tds->in_buf, header, 8);
+ if (tds->in_buf) {
+ /* Clean out the in_buf so we don't use old stuff by mistake */
+ memset(tds->in_buf, 0, tds->in_buf_max);
+ memcpy(tds->in_buf, header, 8);
+ }

/* Now get exactly how many bytes the server told us to get */
have = 8;


With it I now get:

$ tsql -H <MySQL server IP address> -p 3306
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Error 20002 (severity 9):
Adaptive Server connection failed
There was a problem connecting to the server
$

Regards,
--
Ramiro Morales
@ramiromorales
Frediano Ziglio
2013-08-21 08:16:07 UTC
Permalink
Yes, could work.

The problem is that in 0.91 in_buf_max is initialized with 0 while in_buf
is NULL. This means that trying to receive any packet should trigger an
allocation. This does not happen if header contains a length of 0. In this
case nothing is allocated but libTDS assume in_buf is sufficient to
contains an header (which is 8 bytes). Another solution is to check if len
is <8 and close connection and return error. This cause length has to be at
least 8. The issue with your solution is that code continue and assume in
case len == 0 that an empty packet was read. In this case it leads in_len
and in_pos to 8 which could lead to future problems (in_len and in_pos are
offset in in_buf but in this case in_buf is NULL). 0.92 (where this code is
completely different) test for len, in src/tds/packet.c:

...
/* normal packet */
if (packet->pos >= 8) {
len = TDS_GET_A2BE(&packet->buf[2]);
if (len < 8)
goto Severe_Error;
if (packet->len < len) {
...

As buffer is always NULL in this case I don't see any security escalation
(only a DoS which is still security problem!).

Frediano


2013/8/21 Ramiro Morales <cramm0 at gmail.com>
Post by Ramiro Morales
Hi all,
As reported on pymssql issue 108
(https://code.google.com/p/pymssql/issues/detail?id=108)
The original reported experienced it under Windows. IT also kills the
Python interpreter process under Linux.
$ tsql -H <MySQL server IP address> -p 3306
Segmentation fault
$ TDVER=7.1 gdb --args tsql -H <MySQL server IP address> -p 3306
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from tsql...done.
(gdb) run
Starting program: tsql -H 172.17.2.15 -p 3306
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Program received signal SIGSEGV, Segmentation fault.
tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
584 memcpy(tds->in_buf, header, 8);
(gdb) bt
#0 tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
#1 0x000000000040f651 in tds8_do_login (connection=0x63e860,
tds=0x63e3e0) at login.c:1024
#2 tds_connect (tds=tds at entry=0x63e3e0,
connection=connection at entry=0x63e860,
p_oserr=p_oserr at entry=0x7fffffffddec) at login.c:456
#3 0x000000000040ffa6 in tds_connect_and_login
(tds=tds at entry=0x63e3e0, connection=connection at entry=0x63e860) at
login.c:506
#4 0x0000000000403858 in main (argc=<optimized out>, argv=<optimized
out>) at tsql.c:771
(gdb) print tds->in_buf
$1 = (unsigned char *) 0x0
(gdb) print header
$1 = "?\000\000\000\n5.0"
It doesn't happen with every remote service (e.g. with SSH it simply times out).
diff --git a/src/tds/net.c b/src/tds/net.c
index 48426bb..1281613 100644
--- a/src/tds/net.c
+++ b/src/tds/net.c
@@ -579,9 +579,11 @@ tds_read_packet(TDSSOCKET * tds)
tds->in_buf_max = len;
}
- /* Clean out the in_buf so we don't use old stuff by mistake */
- memset(tds->in_buf, 0, tds->in_buf_max);
- memcpy(tds->in_buf, header, 8);
+ if (tds->in_buf) {
+ /* Clean out the in_buf so we don't use old stuff by mistake */
+ memset(tds->in_buf, 0, tds->in_buf_max);
+ memcpy(tds->in_buf, header, 8);
+ }
/* Now get exactly how many bytes the server told us to get */
have = 8;
$ tsql -H <MySQL server IP address> -p 3306
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Adaptive Server connection failed
There was a problem connecting to the server
$
Regards,
--
Ramiro Morales
@ramiromorales
_______________________________________________
FreeTDS mailing list
FreeTDS at lists.ibiblio.org
http://lists.ibiblio.org/mailman/listinfo/freetds
Frediano Ziglio
2013-08-21 20:55:47 UTC
Permalink
Patch at
http://gitorious.org/freetds/freetds/commit/748aa264f71aeca777b026f62ff3ce015c7aa682

Tests at http://freetds.sourceforge.net/ show no regressions.

We should probably send some mail to get change included in packages.

Frediano



2013/8/21 Ramiro Morales <cramm0 at gmail.com>
Post by Ramiro Morales
Hi all,
As reported on pymssql issue 108
(https://code.google.com/p/pymssql/issues/detail?id=108)
The original reported experienced it under Windows. IT also kills the
Python interpreter process under Linux.
$ tsql -H <MySQL server IP address> -p 3306
Segmentation fault
$ TDVER=7.1 gdb --args tsql -H <MySQL server IP address> -p 3306
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from tsql...done.
(gdb) run
Starting program: tsql -H 172.17.2.15 -p 3306
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Program received signal SIGSEGV, Segmentation fault.
tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
584 memcpy(tds->in_buf, header, 8);
(gdb) bt
#0 tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
#1 0x000000000040f651 in tds8_do_login (connection=0x63e860,
tds=0x63e3e0) at login.c:1024
#2 tds_connect (tds=tds at entry=0x63e3e0,
connection=connection at entry=0x63e860,
p_oserr=p_oserr at entry=0x7fffffffddec) at login.c:456
#3 0x000000000040ffa6 in tds_connect_and_login
(tds=tds at entry=0x63e3e0, connection=connection at entry=0x63e860) at
login.c:506
#4 0x0000000000403858 in main (argc=<optimized out>, argv=<optimized
out>) at tsql.c:771
(gdb) print tds->in_buf
$1 = (unsigned char *) 0x0
(gdb) print header
$1 = "?\000\000\000\n5.0"
It doesn't happen with every remote service (e.g. with SSH it simply times out).
diff --git a/src/tds/net.c b/src/tds/net.c
index 48426bb..1281613 100644
--- a/src/tds/net.c
+++ b/src/tds/net.c
@@ -579,9 +579,11 @@ tds_read_packet(TDSSOCKET * tds)
tds->in_buf_max = len;
}
- /* Clean out the in_buf so we don't use old stuff by mistake */
- memset(tds->in_buf, 0, tds->in_buf_max);
- memcpy(tds->in_buf, header, 8);
+ if (tds->in_buf) {
+ /* Clean out the in_buf so we don't use old stuff by mistake */
+ memset(tds->in_buf, 0, tds->in_buf_max);
+ memcpy(tds->in_buf, header, 8);
+ }
/* Now get exactly how many bytes the server told us to get */
have = 8;
$ tsql -H <MySQL server IP address> -p 3306
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Adaptive Server connection failed
There was a problem connecting to the server
$
Regards,
--
Ramiro Morales
@ramiromorales
_______________________________________________
FreeTDS mailing list
FreeTDS at lists.ibiblio.org
http://lists.ibiblio.org/mailman/listinfo/freetds
Frediano Ziglio
2013-08-21 21:31:17 UTC
Permalink
Reported at https://bugzilla.redhat.com/show_bug.cgi?id=999696.
I'll report to Ubuntu too.


2013/8/21 Frediano Ziglio <freddy77 at gmail.com>
Post by Frediano Ziglio
Patch at
http://gitorious.org/freetds/freetds/commit/748aa264f71aeca777b026f62ff3ce015c7aa682
Tests at http://freetds.sourceforge.net/ show no regressions.
We should probably send some mail to get change included in packages.
Frediano
2013/8/21 Ramiro Morales <cramm0 at gmail.com>
Post by Ramiro Morales
Hi all,
As reported on pymssql issue 108
(https://code.google.com/p/pymssql/issues/detail?id=108)
The original reported experienced it under Windows. IT also kills the
Python interpreter process under Linux.
$ tsql -H <MySQL server IP address> -p 3306
Segmentation fault
$ TDVER=7.1 gdb --args tsql -H <MySQL server IP address> -p 3306
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <
http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from tsql...done.
(gdb) run
Starting program: tsql -H 172.17.2.15 -p 3306
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Program received signal SIGSEGV, Segmentation fault.
tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
584 memcpy(tds->in_buf, header, 8);
(gdb) bt
#0 tds_read_packet (tds=tds at entry=0x63e3e0) at net.c:584
#1 0x000000000040f651 in tds8_do_login (connection=0x63e860,
tds=0x63e3e0) at login.c:1024
#2 tds_connect (tds=tds at entry=0x63e3e0,
connection=connection at entry=0x63e860,
p_oserr=p_oserr at entry=0x7fffffffddec) at login.c:456
#3 0x000000000040ffa6 in tds_connect_and_login
(tds=tds at entry=0x63e3e0, connection=connection at entry=0x63e860) at
login.c:506
#4 0x0000000000403858 in main (argc=<optimized out>, argv=<optimized
out>) at tsql.c:771
(gdb) print tds->in_buf
$1 = (unsigned char *) 0x0
(gdb) print header
$1 = "?\000\000\000\n5.0"
It doesn't happen with every remote service (e.g. with SSH it simply times out).
diff --git a/src/tds/net.c b/src/tds/net.c
index 48426bb..1281613 100644
--- a/src/tds/net.c
+++ b/src/tds/net.c
@@ -579,9 +579,11 @@ tds_read_packet(TDSSOCKET * tds)
tds->in_buf_max = len;
}
- /* Clean out the in_buf so we don't use old stuff by mistake */
- memset(tds->in_buf, 0, tds->in_buf_max);
- memcpy(tds->in_buf, header, 8);
+ if (tds->in_buf) {
+ /* Clean out the in_buf so we don't use old stuff by mistake */
+ memset(tds->in_buf, 0, tds->in_buf_max);
+ memcpy(tds->in_buf, header, 8);
+ }
/* Now get exactly how many bytes the server told us to get */
have = 8;
$ tsql -H <MySQL server IP address> -p 3306
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Adaptive Server connection failed
There was a problem connecting to the server
$
Regards,
--
Ramiro Morales
@ramiromorales
_______________________________________________
FreeTDS mailing list
FreeTDS at lists.ibiblio.org
http://lists.ibiblio.org/mailman/listinfo/freetds
Ramiro Morales
2013-08-22 18:26:49 UTC
Permalink
Post by Frediano Ziglio
Patch at
http://gitorious.org/freetds/freetds/commit/748aa264f71aeca777b026f62ff3ce015c7aa682
Tests at http://freetds.sourceforge.net/ show no regressions.
Just tested and this can confirm it solves the issue.
Thanks Frediano, for the fix and for FreeTDS.
--
Ramiro Morales
@ramiromorales
Loading...