summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcmiller@zippy.cornsilk.net <>2006-10-09 18:28:06 -0400
committercmiller@zippy.cornsilk.net <>2006-10-09 18:28:06 -0400
commit4812d81eabe2c2eeb2818e78e35365a84a44763e (patch)
tree1c006a0b771d0d2c43b7ee794ab93d6fc8de48ae
parent72ad606ece804432c04987137542e79890115263 (diff)
downloadmariadb-git-4812d81eabe2c2eeb2818e78e35365a84a44763e.tar.gz
Bug#17583: mysql drops connection when stdout is not writable
When the client program had its stdout file descriptor closed by the calling shell, after some amount of work (enough to fill a socket buffer) the server would complain about a packet error and then disconnect the client. This is a serious security problem. If stdout is closed before the mysql is exec()d, then the first socket() call allocates file number 1 to communicate with the server. Subsequent write()s to that file number (as when printing results that come back from the database) go back to the server instead in the command channel. So, one should be able to craft data which, upon being selected back from the server to the client, and injected into the command stream become valid MySQL protocol to do something nasty when sent /back/ to the server. The solution is to close explicitly the file descriptor that we *printf() to, so that the libc layer and the OS layer both agree that the file is closed.
-rw-r--r--BitKeeper/etc/collapsed1
-rw-r--r--client/mysql.cc15
-rw-r--r--mysql-test/r/mysql_client.result14
-rw-r--r--mysql-test/t/mysql_client.test19
4 files changed, 49 insertions, 0 deletions
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed
new file mode 100644
index 00000000000..60be7fa5dc6
--- /dev/null
+++ b/BitKeeper/etc/collapsed
@@ -0,0 +1 @@
+452a92d0-31-8wSzSfZi165fcGcXPA
diff --git a/client/mysql.cc b/client/mysql.cc
index f9ca9d4f829..12fa2b56ebf 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -372,6 +372,21 @@ int main(int argc,char *argv[])
else
status.add_to_history=1;
status.exit_status=1;
+
+ {
+ /*
+ The file descriptor-layer may be out-of-sync with the file-number layer,
+ so we make sure that "stdout" is really open. If its file is closed then
+ explicitly close the FD layer.
+ */
+ int stdout_fileno_copy;
+ stdout_fileno_copy= dup(fileno(stdout)); /* Okay if fileno fails. */
+ if (stdout_fileno_copy == -1)
+ fclose(stdout);
+ else
+ close(stdout_fileno_copy); /* Clean up dup(). */
+ }
+
load_defaults("my",load_default_groups,&argc,&argv);
defaults_argv=argv;
if (get_options(argc, (char **) argv))
diff --git a/mysql-test/r/mysql_client.result b/mysql-test/r/mysql_client.result
index 87d09428ff6..5375deb250d 100644
--- a/mysql-test/r/mysql_client.result
+++ b/mysql-test/r/mysql_client.result
@@ -2,3 +2,17 @@
1
ERROR 1064 (42000) at line 3: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
ERROR at line 1: USE must be followed by a database name
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+select count(*) from t17583;
+count(*)
+1280
+drop table t17583;
+End of 4.1 tests.
diff --git a/mysql-test/t/mysql_client.test b/mysql-test/t/mysql_client.test
index b382357dacf..2a7f4a935bb 100644
--- a/mysql-test/t/mysql_client.test
+++ b/mysql-test/t/mysql_client.test
@@ -33,3 +33,22 @@
#
--exec echo 'help' | $MYSQL > $MYSQLTEST_VARDIR/tmp/bug20328.tmp
--exec echo 'help ' | $MYSQL > $MYSQLTEST_VARDIR/tmp/bug20328.tmp
+
+#
+# Bug#17583: mysql drops connection when stdout is not writable
+#
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+# Close to the minimal data needed to exercise bug.
+select count(*) from t17583;
+--exec echo "select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; " |$MYSQL test >&-
+drop table t17583;
+
+--echo End of 4.1 tests.