mirror of
https://github.com/gentoo-mirror/gentoo.git
synced 2026-08-05 12:38:09 -07:00
dev-db/mysql: backport vulnerability fix
Bug: https://bugs.gentoo.org/977642 Signed-off-by: Alfred Wingate <parona@protonmail.com> Part-of: https://codeberg.org/gentoo/gentoo/pulls/1186 Signed-off-by: Sam James <sam@gentoo.org>
This commit is contained in:
committed by
Sam James
parent
48d6b84bf3
commit
50ca7ead2a
199
dev-db/mysql/files/mysql-8.0.46-CVE-2026-46863.patch
Normal file
199
dev-db/mysql/files/mysql-8.0.46-CVE-2026-46863.patch
Normal file
@@ -0,0 +1,199 @@
|
||||
https://bugs.gentoo.org/977642
|
||||
|
||||
From 33d66d22d8bf9c86af307307004ed43850face5f Mon Sep 17 00:00:00 2001
|
||||
From: Harin Vadodaria <harin.vadodaria@oracle.com>
|
||||
Date: Mon, 1 Jun 2026 10:15:59 +0200
|
||||
Subject: [PATCH 1/2] Bug#39116965: MySQL Out-of-Bounds Read
|
||||
|
||||
Description:
|
||||
Connection attribute parsing read a length-encoded size field before
|
||||
checking that the complete field was present in the packet.
|
||||
|
||||
Fix:
|
||||
A size check was added before reading the field. Debug coverage was
|
||||
added for short length-encoded attribute packets during
|
||||
pre-authentication.
|
||||
|
||||
Change-Id: Ia90e387a219556bb040a26853946c022f73de730
|
||||
--- a/sql/auth/sql_authentication.cc
|
||||
+++ b/sql/auth/sql_authentication.cc
|
||||
@@ -2262,9 +2262,20 @@ static bool read_client_connect_attrs(THD *thd, char **ptr,
|
||||
size_t length, length_length;
|
||||
char *ptr_save;
|
||||
|
||||
- /* not enough bytes to hold the length */
|
||||
+ /* Need one byte to determine the length-encoded field size. */
|
||||
if (*max_bytes_available < 1) return true;
|
||||
|
||||
+ uchar *pos = (uchar *)*ptr;
|
||||
+ DBUG_EXECUTE_IF("connect_attrs_too_short_3", *pos = 252;
|
||||
+ *max_bytes_available = 2;);
|
||||
+ DBUG_EXECUTE_IF("connect_attrs_too_short_4", *pos = 253;
|
||||
+ *max_bytes_available = 3;);
|
||||
+ DBUG_EXECUTE_IF("connect_attrs_too_short_9", *pos = 254;
|
||||
+ *max_bytes_available = 8;);
|
||||
+
|
||||
+ const size_t required_length = (size_t)net_field_length_size(pos);
|
||||
+ if (*max_bytes_available < required_length) return true;
|
||||
+
|
||||
/* read the length */
|
||||
ptr_save = *ptr;
|
||||
length = static_cast<size_t>(net_field_length_ll((uchar **)ptr));
|
||||
--
|
||||
2.54.0
|
||||
|
||||
|
||||
From 2747a03d7a522a4f880df5c978f2e5c1db17b119 Mon Sep 17 00:00:00 2001
|
||||
From: Lukasz Kotula <lukasz.kotula@oracle.com>
|
||||
Date: Fri, 17 Apr 2026 09:12:57 +0200
|
||||
Subject: [PATCH 2/2] Bug#39204635 - Unauthenticated repeated X Protocol TLS
|
||||
upgrade crashes MySQL Router
|
||||
|
||||
Description
|
||||
For X Protocol routing with `client_ssl_mode=PREFERRED` and
|
||||
`server_ssl_mode=AS_CLIENT`, a client can send
|
||||
`CON_CAPABILITIES_SET(tls=true)` after TLS is already active.
|
||||
|
||||
Router accepted this second TLS capability request and re-entered
|
||||
the TLS upgrade path. During `tls_accept_finalize()`, the server-side
|
||||
TLS channel could already be initialized, which led to a `logic_error`
|
||||
and connection termination.
|
||||
|
||||
Fix
|
||||
===
|
||||
Reject repeated TLS capability upgrades when client-side TLS is already
|
||||
active. For a second `tls=true` capability request, Router now returns
|
||||
error 5001 (`Capability prepare failed for 'tls'`) and continues normal
|
||||
session handling.
|
||||
|
||||
Change-Id: Ifaaa93eeec1019160c7a6db50daa7e1af8f383c5
|
||||
--- a/router/src/routing/src/x_connection.cc
|
||||
+++ b/router/src/routing/src/x_connection.cc
|
||||
@@ -1471,6 +1471,7 @@ void MysqlRoutingXConnection::client_cap_set() {
|
||||
|
||||
if (switch_to_tls) {
|
||||
bool continue_with_tls{false};
|
||||
+
|
||||
switch (source_ssl_mode()) {
|
||||
case SslMode::kDisabled: {
|
||||
continue_with_tls = false;
|
||||
@@ -1525,6 +1526,11 @@ void MysqlRoutingXConnection::client_cap_set() {
|
||||
discard_current_msg(src_channel, src_protocol);
|
||||
std::vector<uint8_t> out_buf;
|
||||
|
||||
+ // The client tries to activate TLS when it is already enabled.
|
||||
+ if (continue_with_tls && src_channel->ssl()) {
|
||||
+ continue_with_tls = false;
|
||||
+ }
|
||||
+
|
||||
if (!continue_with_tls) {
|
||||
#ifdef DEBUG_IO
|
||||
std::cerr << __LINE__ << ": "
|
||||
--- a/router/tests/component/test_routing.cc
|
||||
+++ b/router/tests/component/test_routing.cc
|
||||
@@ -122,6 +122,23 @@ static xcl::XError make_x_connection(XProtocolSession &session,
|
||||
password.c_str(), "");
|
||||
}
|
||||
|
||||
+static xcl::XError make_x_raw_connection(
|
||||
+ XProtocolSession &session, const std::string &host, const uint16_t port,
|
||||
+ int64_t connect_timeout = 10000 /*10s*/) {
|
||||
+ session = xcl::create_session();
|
||||
+ xcl::XError err = setup_x_session(session, connect_timeout, "PREFERRED");
|
||||
+ if (err) return err;
|
||||
+
|
||||
+ return session->get_protocol().get_connection().connect(
|
||||
+ host, port, xcl::Internet_protocol::Any);
|
||||
+}
|
||||
+
|
||||
+static std::string format_xerror(const xcl::XError &e) {
|
||||
+ if (!e) return "no-error";
|
||||
+
|
||||
+ return "(code:" + std::to_string(e.error()) + ", message:" + e.what() + ")";
|
||||
+}
|
||||
+
|
||||
TEST_F(RouterRoutingTest, RoutingOk) {
|
||||
const auto server_port = port_pool_.get_next_available();
|
||||
const auto router_port = port_pool_.get_next_available();
|
||||
@@ -1882,6 +1899,78 @@ static size_t xproto_frame_encode(const T &msg, uint8_t msg_type,
|
||||
return msg.SerializeToCodedStream(&codecouts);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * @test Verify that repeated TLS activation requests are properly rejected
|
||||
+ * and do not crash the Router.
|
||||
+ */
|
||||
+TEST_F(RouterRoutingTest, XProtocolRepeatedTlsUpgrade) {
|
||||
+ const auto server_classic_port = port_pool_.get_next_available();
|
||||
+ const auto server_x_port = port_pool_.get_next_available();
|
||||
+ const auto router_x_rw_port = port_pool_.get_next_available();
|
||||
+
|
||||
+ const std::string json_stmts = get_data_dir().join("bootstrap_gr.js").str();
|
||||
+
|
||||
+ launch_mysql_server_mock(json_stmts, server_classic_port, EXIT_SUCCESS, false,
|
||||
+ /*http_port*/ 0, server_x_port, /*module_prefix*/ "",
|
||||
+ /*bind_address*/ "127.0.0.1",
|
||||
+ /*wait_for_notify_ready*/ std::chrono::seconds(30),
|
||||
+ /*enable_ssl*/ true);
|
||||
+
|
||||
+ const std::string routing_x_section = get_static_routing_section(
|
||||
+ "x", router_x_rw_port, "", {server_x_port}, "x");
|
||||
+
|
||||
+ TempDirectory conf_dir("conf");
|
||||
+ const std::string ssl_conf =
|
||||
+ "client_ssl_mode=PREFERRED\n"
|
||||
+ "server_ssl_mode=AS_CLIENT\n"
|
||||
+ "client_ssl_key=" SSL_TEST_DATA_DIR
|
||||
+ "/server-key-sha512.pem\n"
|
||||
+ "client_ssl_cert=" SSL_TEST_DATA_DIR "/server-cert-sha512.pem";
|
||||
+ std::string conf_file =
|
||||
+ create_config_file(conf_dir.name(), routing_x_section, nullptr,
|
||||
+ "mysqlrouter.conf", ssl_conf, true);
|
||||
+
|
||||
+ launch_router({"-c", conf_file});
|
||||
+
|
||||
+ Mysqlx::Connection::CapabilitiesSet switch_tls_msg;
|
||||
+ auto *cap = switch_tls_msg.mutable_capabilities()->add_capabilities();
|
||||
+ cap->set_name("tls");
|
||||
+ auto *cap_value = cap->mutable_value();
|
||||
+ cap_value->set_type(Mysqlx::Datatypes::Any_Type::Any_Type_SCALAR);
|
||||
+ auto *cap_scalar = cap_value->mutable_scalar();
|
||||
+ cap_scalar->set_type(Mysqlx::Datatypes::Scalar_Type::Scalar_Type_V_BOOL);
|
||||
+ cap_scalar->set_v_bool(true);
|
||||
+
|
||||
+ XProtocolSession x_session;
|
||||
+ const auto x_connect_error =
|
||||
+ make_x_raw_connection(x_session, "127.0.0.1", router_x_rw_port);
|
||||
+ ASSERT_FALSE(x_connect_error) << format_xerror(x_connect_error);
|
||||
+
|
||||
+ const auto x_cap_set_error =
|
||||
+ x_session.get()->get_protocol().execute_set_capability(switch_tls_msg);
|
||||
+ ASSERT_FALSE(x_cap_set_error) << format_xerror(x_cap_set_error);
|
||||
+
|
||||
+ const auto x_tls_error =
|
||||
+ x_session.get()->get_protocol().get_connection().activate_tls();
|
||||
+
|
||||
+ ASSERT_FALSE(x_tls_error) << format_xerror(x_tls_error);
|
||||
+
|
||||
+ const auto x_cap_set2_error =
|
||||
+ x_session.get()->get_protocol().execute_set_capability(switch_tls_msg);
|
||||
+ ASSERT_EQ(x_cap_set2_error.error(), 5001) << format_xerror(x_cap_set2_error);
|
||||
+
|
||||
+ const auto x_login_error =
|
||||
+ x_session.get()->get_protocol().execute_authenticate("root", "fake-pass",
|
||||
+ "", "SHA256_MEMORY");
|
||||
+ ASSERT_FALSE(x_login_error) << format_xerror(x_login_error);
|
||||
+
|
||||
+ // Router should still accept a fresh X Protocol connection after the loop.
|
||||
+ XProtocolSession x_session2;
|
||||
+ const auto res = make_x_connection(x_session2, "127.0.0.1", router_x_rw_port,
|
||||
+ "root", "fake-pass");
|
||||
+ EXPECT_THAT(res.error(), ::testing::AnyOf(0, 3159));
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* @test Check that if the x protocol client sends CONCLOSE message the Router
|
||||
* replies with OK{bye!} message.
|
||||
--
|
||||
2.54.0
|
||||
|
||||
1323
dev-db/mysql/mysql-8.0.46-r1.ebuild
Normal file
1323
dev-db/mysql/mysql-8.0.46-r1.ebuild
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user