Skip to content

Commit dc85e9b

Browse files
[CDRIVER-5606] Fix unitiailized padding in mongoc_host_list_t (#1644)
* Fully initialize the host list struct in constructor If a mongoc_host_list_t struct is declared without an initializer, then initialized using any method, the `padding` member will remain uninitialized. Even if this member is unused, later attempts to copy the host list will attempt to perform an uninitialized read of that padding member. * Cleanup of _stream_run_hello and const correctness
1 parent 68456a9 commit dc85e9b

File tree

5 files changed

+68
-63
lines changed

5 files changed

+68
-63
lines changed

src/libmongoc/src/mongoc/mongoc-cluster-private.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,10 @@ mongoc_cluster_run_command_parts (mongoc_cluster_t *cluster,
212212
bson_error_t *error);
213213

214214
bool
215-
mongoc_cluster_run_command_private (mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error);
215+
mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
216+
const mongoc_cmd_t *cmd,
217+
bson_t *reply,
218+
bson_error_t *error);
216219

217220
void
218221
_mongoc_cluster_build_sasl_start (bson_t *cmd, const char *mechanism, const char *buf, uint32_t buflen);

src/libmongoc/src/mongoc/mongoc-cluster.c

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ _cluster_fetch_stream_pooled (mongoc_cluster_t *cluster,
8484
bson_error_t *error);
8585

8686
static bool
87-
mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error);
87+
mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error);
8888

8989
static void
9090
_bson_error_message_printf (bson_error_t *error, const char *format, ...) BSON_GNUC_PRINTF (2, 3);
@@ -235,7 +235,7 @@ static const int32_t message_header_length = 4u * sizeof (int32_t);
235235

236236
static bool
237237
_mongoc_cluster_run_command_opquery_send (
238-
mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, int32_t compressor_id, mcd_rpc_message *rpc, bson_error_t *error)
238+
mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, int32_t compressor_id, mcd_rpc_message *rpc, bson_error_t *error)
239239
{
240240
BSON_ASSERT_PARAM (cluster);
241241
BSON_ASSERT_PARAM (cmd);
@@ -319,7 +319,7 @@ _mongoc_cluster_run_command_opquery_send (
319319

320320
static bool
321321
_mongoc_cluster_run_command_opquery_recv (
322-
mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
322+
mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
323323
{
324324
BSON_ASSERT_PARAM (cluster);
325325
BSON_ASSERT_PARAM (cmd);
@@ -398,7 +398,7 @@ _mongoc_cluster_run_command_opquery_recv (
398398

399399
static bool
400400
mongoc_cluster_run_command_opquery (
401-
mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, int32_t compressor_id, bson_t *reply, bson_error_t *error)
401+
mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, int32_t compressor_id, bson_t *reply, bson_error_t *error)
402402
{
403403
BSON_ASSERT_PARAM (cluster);
404404
BSON_ASSERT_PARAM (cmd);
@@ -657,7 +657,10 @@ _should_use_op_msg (const mongoc_cluster_t *cluster)
657657
*/
658658

659659
bool
660-
mongoc_cluster_run_command_private (mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error)
660+
mongoc_cluster_run_command_private (mongoc_cluster_t *cluster,
661+
const mongoc_cmd_t *cmd,
662+
bson_t *reply,
663+
bson_error_t *error)
661664
{
662665
bool retval;
663666
const mongoc_server_stream_t *server_stream;
@@ -757,25 +760,17 @@ _stream_run_hello (mongoc_cluster_t *cluster,
757760
bson_t *speculative_auth_response /* OUT */,
758761
bson_error_t *error)
759762
{
760-
bson_t handshake_command; /* Initialized by dup_handshake below */
761-
mongoc_cmd_t hello_cmd;
762-
bson_t reply;
763-
int64_t start;
764-
int64_t rtt_msec;
765-
mongoc_server_description_t empty_sd;
766-
mongoc_server_description_t *ret_handshake_sd;
767-
mongoc_server_stream_t *server_stream;
768-
bool r;
769-
mongoc_ssl_opt_t *ssl_opts = NULL;
770763
mc_shared_tpld td = mc_tpld_take_ref (BSON_ASSERT_PTR_INLINE (cluster)->client->topology);
771764

772765
ENTRY;
773766

774767
BSON_ASSERT (stream);
775768

769+
bson_t handshake_command;
776770
_mongoc_topology_dup_handshake_cmd (cluster->client->topology, &handshake_command);
777771

778772
if (cluster->requires_auth && speculative_auth_response) {
773+
mongoc_ssl_opt_t *ssl_opts = NULL;
779774
#ifdef MONGOC_ENABLE_SSL
780775
ssl_opts = &cluster->client->ssl_opts;
781776
#endif
@@ -787,7 +782,7 @@ _stream_run_hello (mongoc_cluster_t *cluster,
787782
_mongoc_handshake_append_sasl_supported_mechs (cluster->uri, &handshake_command);
788783
}
789784

790-
start = bson_get_monotonic_time ();
785+
const int64_t start = bson_get_monotonic_time ();
791786
/* TODO CDRIVER-3654: do not use a mongoc_server_stream here.
792787
* Instead, use a plain stream. If a network error occurs, check the cluster
793788
* node's generation (which is the generation of the created connection) to
@@ -798,33 +793,40 @@ _stream_run_hello (mongoc_cluster_t *cluster,
798793
* Then _mongoc_cluster_stream_for_server also handles the error, and
799794
* invalidates again.
800795
*/
796+
mongoc_server_description_t empty_sd;
801797
mongoc_server_description_init (&empty_sd, address, server_id);
802-
server_stream = _mongoc_cluster_create_server_stream (td.ptr, &empty_sd, stream);
803-
798+
mongoc_server_stream_t *const server_stream = _mongoc_cluster_create_server_stream (td.ptr, &empty_sd, stream);
804799
mongoc_server_description_cleanup (&empty_sd);
805800

806-
/* Set up the shared parts of the mongo_cmd_t, which will later be converted
807-
to either an op_msg or op_query: */
808-
memset (&hello_cmd, 0, sizeof (hello_cmd));
809-
801+
mongoc_query_flags_t query_flags = MONGOC_QUERY_NONE;
810802
/* Use OP_QUERY for the handshake, unless the user has specified an
811803
* API version; the correct hello_cmd has already been selected: */
812804
if (!_should_use_op_msg (cluster)) {
813805
/* Complete OPCODE_QUERY setup: */
814-
hello_cmd.query_flags = MONGOC_QUERY_SECONDARY_OK;
806+
query_flags |= MONGOC_QUERY_SECONDARY_OK;
815807
} else {
816808
/* We're using OP_MSG, and require some additional doctoring: */
817809
bson_append_utf8 (&handshake_command, "$db", 3, "admin", 5);
818810
}
819811

820-
hello_cmd.db_name = "admin";
821-
hello_cmd.command = &handshake_command;
822-
hello_cmd.command_name = _mongoc_get_command_name (&handshake_command);
823-
hello_cmd.server_stream = server_stream;
824-
hello_cmd.is_acknowledged = true;
812+
/* Set up the shared parts of the mongo_cmd_t, which will later be converted
813+
to either an op_msg or op_query: */
814+
const mongoc_cmd_t hello_cmd = {
815+
.db_name = "admin",
816+
.command = &handshake_command,
817+
.command_name = _mongoc_get_command_name (&handshake_command),
818+
.server_stream = server_stream,
819+
.is_acknowledged = true,
820+
.query_flags = query_flags,
821+
};
825822

823+
bson_t reply;
824+
// The final resulting server description
825+
mongoc_server_description_t *ret_handshake_sd = NULL;
826826
if (!mongoc_cluster_run_command_private (cluster, &hello_cmd, &reply, error)) {
827+
// Command execution failed.
827828
if (negotiate_sasl_supported_mechs) {
829+
// Negotiating a new SASL mechanism
828830
bsonParse (reply,
829831
find (allOf (key ("ok"), isFalse), //
830832
do ({
@@ -836,39 +838,35 @@ _stream_run_hello (mongoc_cluster_t *cluster,
836838
error->code = MONGOC_ERROR_CLIENT_AUTHENTICATE;
837839
})));
838840
}
841+
} else {
842+
// "hello" succeeded
839843

840-
mongoc_server_stream_cleanup (server_stream);
841-
ret_handshake_sd = NULL;
842-
goto done;
843-
}
844-
845-
rtt_msec = (bson_get_monotonic_time () - start) / 1000;
846-
847-
ret_handshake_sd = BSON_ALIGNED_ALLOC0 (mongoc_server_description_t);
844+
// Round-trip time for the hello command
845+
const int64_t rtt_msec = (bson_get_monotonic_time () - start) / 1000;
848846

849-
mongoc_server_description_init (ret_handshake_sd, address, server_id);
850-
/* send the error from run_command IN to handle_hello */
851-
mongoc_server_description_handle_hello (ret_handshake_sd, &reply, rtt_msec, error);
847+
ret_handshake_sd = BSON_ALIGNED_ALLOC0 (mongoc_server_description_t);
848+
mongoc_server_description_init (ret_handshake_sd, address, server_id);
849+
/* send the error from run_command IN to handle_hello */
850+
mongoc_server_description_handle_hello (ret_handshake_sd, &reply, rtt_msec, error);
852851

853-
if (cluster->requires_auth && speculative_auth_response) {
854-
_mongoc_topology_scanner_parse_speculative_authentication (&reply, speculative_auth_response);
855-
}
852+
if (cluster->requires_auth && speculative_auth_response) {
853+
_mongoc_topology_scanner_parse_speculative_authentication (&reply, speculative_auth_response);
854+
}
856855

857-
/* Note: This call will render our copy of the topology description to be
858-
* stale */
859-
r = _mongoc_topology_update_from_handshake (cluster->client->topology, ret_handshake_sd);
860-
if (!r) {
861-
mongoc_server_description_reset (ret_handshake_sd);
862-
bson_set_error (&ret_handshake_sd->error,
863-
MONGOC_ERROR_STREAM,
864-
MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
865-
"\"%s\" removed from topology",
866-
address);
856+
/* Note: This call will render our copy of the topology description to be
857+
* stale */
858+
const bool update_okay = _mongoc_topology_update_from_handshake (cluster->client->topology, ret_handshake_sd);
859+
if (!update_okay) {
860+
mongoc_server_description_reset (ret_handshake_sd);
861+
bson_set_error (&ret_handshake_sd->error,
862+
MONGOC_ERROR_STREAM,
863+
MONGOC_ERROR_STREAM_NOT_ESTABLISHED,
864+
"\"%s\" removed from topology",
865+
address);
866+
}
867867
}
868868

869869
mongoc_server_stream_cleanup (server_stream);
870-
871-
done:
872870
bson_destroy (&handshake_command);
873871
bson_destroy (&reply);
874872
mc_tpld_drop_ref (&td);
@@ -3179,7 +3177,7 @@ mongoc_cluster_try_recv (mongoc_cluster_t *cluster,
31793177

31803178

31813179
static void
3182-
network_error_reply (bson_t *reply, mongoc_cmd_t *cmd)
3180+
network_error_reply (bson_t *reply, const mongoc_cmd_t *cmd)
31833181
{
31843182
bson_array_builder_t *labels;
31853183

@@ -3220,7 +3218,7 @@ network_error_reply (bson_t *reply, mongoc_cmd_t *cmd)
32203218

32213219
static bool
32223220
_mongoc_cluster_run_opmsg_send (
3223-
mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
3221+
mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
32243222
{
32253223
BSON_ASSERT_PARAM (cluster);
32263224
BSON_ASSERT_PARAM (cmd);
@@ -3313,7 +3311,7 @@ _mongoc_cluster_run_opmsg_send (
33133311

33143312
static bool
33153313
_mongoc_cluster_run_opmsg_recv (
3316-
mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
3314+
mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, mcd_rpc_message *rpc, bson_t *reply, bson_error_t *error)
33173315
{
33183316
BSON_ASSERT_PARAM (cluster);
33193317
BSON_ASSERT_PARAM (cmd);
@@ -3421,7 +3419,7 @@ _mongoc_cluster_run_opmsg_recv (
34213419
}
34223420

34233421
static bool
3424-
mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster, mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error)
3422+
mongoc_cluster_run_opmsg (mongoc_cluster_t *cluster, const mongoc_cmd_t *cmd, bson_t *reply, bson_error_t *error)
34253423
{
34263424
BSON_ASSERT_PARAM (cluster);
34273425
BSON_ASSERT_PARAM (cmd);

src/libmongoc/src/mongoc/mongoc-cmd-private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ bool
129129
mongoc_cmd_parts_assemble (mongoc_cmd_parts_t *parts, mongoc_server_stream_t *server_stream, bson_error_t *error);
130130

131131
bool
132-
mongoc_cmd_is_compressible (mongoc_cmd_t *cmd);
132+
mongoc_cmd_is_compressible (const mongoc_cmd_t *cmd);
133133

134134
void
135135
mongoc_cmd_parts_cleanup (mongoc_cmd_parts_t *op);

src/libmongoc/src/mongoc/mongoc-cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ mongoc_cmd_parts_cleanup (mongoc_cmd_parts_t *parts)
948948
}
949949

950950
bool
951-
mongoc_cmd_is_compressible (mongoc_cmd_t *cmd)
951+
mongoc_cmd_is_compressible (const mongoc_cmd_t *cmd)
952952
{
953953
BSON_ASSERT (cmd);
954954
BSON_ASSERT (cmd->command_name);

src/libmongoc/src/mongoc/mongoc-host-list.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,13 @@ _mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *link_,
302302
uint16_t port,
303303
bson_error_t *error)
304304
{
305+
BSON_ASSERT (host);
306+
BSON_ASSERT (link_);
305307
size_t host_len = strlen (host);
306-
link_->port = port;
308+
*link_ = (mongoc_host_list_t){
309+
.next = NULL,
310+
.port = port,
311+
};
307312

308313
if (host_len == 0) {
309314
bson_set_error (error, MONGOC_ERROR_STREAM, MONGOC_ERROR_STREAM_NAME_RESOLUTION, "Empty hostname in URI");
@@ -357,7 +362,6 @@ _mongoc_host_list_from_hostport_with_err (mongoc_host_list_t *link_,
357362
BSON_ASSERT ((size_t) req < sizeof link_->host_and_port);
358363
}
359364

360-
link_->next = NULL;
361365
return true;
362366
}
363367

0 commit comments

Comments
 (0)