Uploaded image for project: 'WiredTiger'
  1. WiredTiger
  2. WT-1991

Use-after-free in __session_open_cursor after allocation failure

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • WT2.7.0
    • Affects Version/s: None
    • Component/s: None

      While simulating out-of-memory conditions in __wt_calloc, I triggered a use-after-free error in __session_open_cursor.

      Sequence of events:

      1. __session_open_cursor calls __wt_open_cursor with the cursor pointer set to NULL (line 357)
      2. __wt_open_cursor partially succeeds, but has to return early because __wt_strdup() has an allocation failure (line 318). This causes the cursor to be closed and the pointer value to be freed.
      3. Back in __session_open_cursor, the err block is jumped to and the freed memory is accessed because the pointer is non-NULL (line 365)

      Relevant code excerpted:

      int
      __wt_open_cursor(WT_SESSION_IMPL *session,
          const char *uri, WT_CURSOR *owner, const char *cfg[], WT_CURSOR **cursorp)
      {
      	WT_COLGROUP *colgroup;
      	WT_DATA_SOURCE *dsrc;
      	WT_DECL_RET;
      
      	*cursorp = NULL;
      
      [ ..... snip ..... ]
      
      316  	if ((*cursorp)->uri == NULL &&
      317  	    (ret = __wt_strdup(session, uri, &(*cursorp)->uri)) != 0)
      318  		WT_TRET((*cursorp)->close(*cursorp));
      
      	return (ret);
      }
      
      static int
      __session_open_cursor(WT_SESSION *wt_session,
          const char *uri, WT_CURSOR *to_dup, const char *config, WT_CURSOR **cursorp)
      {
      	WT_CURSOR *cursor;
      	WT_DECL_RET;
      	WT_SESSION_IMPL *session;
      
      	cursor = *cursorp = NULL;
      
      [ ..... snip ..... ]
      
      357  	WT_ERR(__wt_open_cursor(session, uri, NULL, cfg, &cursor));
      358  	if (to_dup != NULL)
      359  		WT_ERR(__wt_cursor_dup_position(to_dup, cursor));
      360
      361  	*cursorp = cursor;
      
      363  	if (0) {
      364  err:        if (cursor != NULL)
      365                   WT_TRET(cursor->close(cursor));
      	}
      

      ASan report:

       ==9690== ERROR: AddressSanitizer: heap-use-after-free on address 0x603a001b2f50 at pc 0x2f5681e bp 0x7f3b572792f0 sp 0x7f3b572792e8
       READ of size 8 at 0x603a001b2f50 thread T105
       
       #0 0x2f5681d in __session_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:365
       #1 0x206e8c8 in mongo::WiredTigerSession::getCursor(std::string const&, unsigned long, bool) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp:69
       #2 0x206d16c in mongo::WiredTigerCursor::WiredTigerCursor(std::string const&, unsigned long, bool, mongo::OperationContext*) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp:403
       #3 0x205b360 in mongo::WiredTigerRecordStore::findRecord(mongo::OperationContext*, mongo::RecordId const&, mongo::RecordData*) const /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp:549
       #4 0x1f43738 in mongo::KVCatalog::_findEntry(mongo::OperationContext*, mongo::StringData, mongo::RecordId*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:227
       #5 0x1f439e3 in mongo::KVCatalog::getMetaData(mongo::OperationContext*, mongo::StringData) /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:242
       #6 0x1f4cfcd in mongo::KVCollectionCatalogEntry::_getMetaData(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp:174
       #7 0x1f17654 in mongo::BSONCollectionCatalogEntry::getCollectionOptions(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/bson_collection_catalog_entry.cpp:39
       #8 0x185fee9 in mongo::mr::State::prepTempCollection() /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:405
       #9 0x186e757 in mongo::mr::MapReduceFinishCommand::run(mongo::OperationContext*, std::string const&, mongo::BSONObj&, int, std::string&, mongo::BSONObjBuilder&) /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:1596
       #10 0x190bf2b in mongo::Command::run(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1316
       #11 0x190b53f in mongo::Command::execCommand(mongo::OperationContext*, mongo::Command*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1266
       #12 0x180e691 in mongo::runCommands(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/commands.cpp:495
       #13 0x1aba2c0 in mongo::(anonymous namespace)::receivedRpc(mongo::OperationContext*, mongo::Client&, mongo::DbResponse&, mongo::Message&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:291
       #14 0x1abb8e6 in mongo::assembleResponse(mongo::OperationContext*, mongo::Message&, mongo::DbResponse&, mongo::HostAndPort const&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:509
       #15 0x15b9862 in mongo::MyMessageHandler::process(mongo::Message&, mongo::AbstractMessagingPort*) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:167
       #16 0x2332e85 in mongo::PortMessageServer::handleIncomingMsg(void*) /home/s/code/mongo/mongo/src/mongo/util/net/message_server_port.cpp:229
       #17 0x7f3b9b596b97 (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x18b97)
       #18 0x7f3b9a73c181 in start_thread /build/buildd/eglibc-2.19/nptl/pthread_create.c:312
       #19 0x7f3b9a46947c in clone /build/buildd/eglibc-2.19/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:111
       
       0x603a001b2f50 is located 144 bytes inside of 688-byte region [0x603a001b2ec0,0x603a001b3170)
       freed by thread T105 here:
       #0 0x7f3b9b59333a in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x1533a)
       #1 0x2ee51a7 in __wt_free_int /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/os_posix/os_alloc.c:262
       #2 0x2e7f56a in __wt_cursor_close /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_std.c:478
       #3 0x2e4d721 in __curfile_close /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_file.c:380
       #4 0x2f55d7b in __wt_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:318
       #5 0x2e8bfa6 in __wt_curtable_open /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_table.c:879
       #6 0x2f55261 in __wt_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:247
       #7 0x2f56763 in __session_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:357
       #8 0x206e8c8 in mongo::WiredTigerSession::getCursor(std::string const&, unsigned long, bool) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp:69
       #9 0x206d16c in mongo::WiredTigerCursor::WiredTigerCursor(std::string const&, unsigned long, bool, mongo::OperationContext*) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp:403
       #10 0x205b360 in mongo::WiredTigerRecordStore::findRecord(mongo::OperationContext*, mongo::RecordId const&, mongo::RecordData*) const /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp:549
       #11 0x1f43738 in mongo::KVCatalog::_findEntry(mongo::OperationContext*, mongo::StringData, mongo::RecordId*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:227
       #12 0x1f439e3 in mongo::KVCatalog::getMetaData(mongo::OperationContext*, mongo::StringData) /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:242
       #13 0x1f4cfcd in mongo::KVCollectionCatalogEntry::_getMetaData(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp:174
       #14 0x1f17654 in mongo::BSONCollectionCatalogEntry::getCollectionOptions(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/bson_collection_catalog_entry.cpp:39
       #15 0x185fee9 in mongo::mr::State::prepTempCollection() /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:405
       #16 0x186e757 in mongo::mr::MapReduceFinishCommand::run(mongo::OperationContext*, std::string const&, mongo::BSONObj&, int, std::string&, mongo::BSONObjBuilder&) /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:1596
       #17 0x190bf2b in mongo::Command::run(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1316
       #18 0x190b53f in mongo::Command::execCommand(mongo::OperationContext*, mongo::Command*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1266
       #19 0x180e691 in mongo::runCommands(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/commands.cpp:495
       #20 0x1aba2c0 in mongo::(anonymous namespace)::receivedRpc(mongo::OperationContext*, mongo::Client&, mongo::DbResponse&, mongo::Message&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:291
       #21 0x1abb8e6 in mongo::assembleResponse(mongo::OperationContext*, mongo::Message&, mongo::DbResponse&, mongo::HostAndPort const&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:509
       #22 0x15b9862 in mongo::MyMessageHandler::process(mongo::Message&, mongo::AbstractMessagingPort*) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:167
       #23 0x2332e85 in mongo::PortMessageServer::handleIncomingMsg(void*) /home/s/code/mongo/mongo/src/mongo/util/net/message_server_port.cpp:229
       #24 0x7f3b9b596b97 (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x18b97)
       
       previously allocated by thread T105 here:
       #0 0x7f3b9b5934e5 in calloc (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x154e5)
       #1 0x2ee4380 in __wt_calloc /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/os_posix/os_alloc.c:64
       #2 0x2e4d977 in __wt_curfile_create /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_file.c:427
       #3 0x2e4ea42 in __wt_curfile_open /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_file.c:526
       #4 0x2f5585e in __wt_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:281
       #5 0x2e8bfa6 in __wt_curtable_open /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/cursor/cur_table.c:879
       #6 0x2f55261 in __wt_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:247
       #7 0x2f56763 in __session_open_cursor /home/s/code/mongo/mongo/src/third_party/wiredtiger/src/session/session_api.c:357
       #8 0x206e8c8 in mongo::WiredTigerSession::getCursor(std::string const&, unsigned long, bool) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_session_cache.cpp:69
       #9 0x206d16c in mongo::WiredTigerCursor::WiredTigerCursor(std::string const&, unsigned long, bool, mongo::OperationContext*) /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_recovery_unit.cpp:403
       #10 0x205b360 in mongo::WiredTigerRecordStore::findRecord(mongo::OperationContext*, mongo::RecordId const&, mongo::RecordData*) const /home/s/code/mongo/mongo/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp:549
       #11 0x1f43738 in mongo::KVCatalog::_findEntry(mongo::OperationContext*, mongo::StringData, mongo::RecordId*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:227
       #12 0x1f439e3 in mongo::KVCatalog::getMetaData(mongo::OperationContext*, mongo::StringData) /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_catalog.cpp:242
       #13 0x1f4cfcd in mongo::KVCollectionCatalogEntry::_getMetaData(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/kv/kv_collection_catalog_entry.cpp:174
       #14 0x1f17654 in mongo::BSONCollectionCatalogEntry::getCollectionOptions(mongo::OperationContext*) const /home/s/code/mongo/mongo/src/mongo/db/storage/bson_collection_catalog_entry.cpp:39
       #15 0x185fee9 in mongo::mr::State::prepTempCollection() /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:405
       #16 0x186e757 in mongo::mr::MapReduceFinishCommand::run(mongo::OperationContext*, std::string const&, mongo::BSONObj&, int, std::string&, mongo::BSONObjBuilder&) /home/s/code/mongo/mongo/src/mongo/db/commands/mr.cpp:1596
       #17 0x190bf2b in mongo::Command::run(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1316
       #18 0x190b53f in mongo::Command::execCommand(mongo::OperationContext*, mongo::Command*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/dbcommands.cpp:1266
       #19 0x180e691 in mongo::runCommands(mongo::OperationContext*, mongo::rpc::RequestInterface const&, mongo::rpc::ReplyBuilderInterface*) /home/s/code/mongo/mongo/src/mongo/db/commands.cpp:495
       #20 0x1aba2c0 in mongo::(anonymous namespace)::receivedRpc(mongo::OperationContext*, mongo::Client&, mongo::DbResponse&, mongo::Message&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:291
       #21 0x1abb8e6 in mongo::assembleResponse(mongo::OperationContext*, mongo::Message&, mongo::DbResponse&, mongo::HostAndPort const&) /home/s/code/mongo/mongo/src/mongo/db/instance.cpp:509
       #22 0x15b9862 in mongo::MyMessageHandler::process(mongo::Message&, mongo::AbstractMessagingPort*) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:167
       #23 0x2332e85 in mongo::PortMessageServer::handleIncomingMsg(void*) /home/s/code/mongo/mongo/src/mongo/util/net/message_server_port.cpp:229
       #24 0x7f3b9b596b97 (/usr/lib/x86_64-linux-gnu/libasan.so.0+0x18b97)
       
       Thread T105 created by T0 here:
       #0 0x7f3b9b588b5b in __interceptor_pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.0+0xab5b)
       #1 0x2332575 in mongo::PortMessageServer::accepted(std::shared_ptr<mongo::Socket>, long long) /home/s/code/mongo/mongo/src/mongo/util/net/message_server_port.cpp:148
       #2 0x2327b16 in mongo::Listener::initAndListen() /home/s/code/mongo/mongo/src/mongo/util/net/listen.cpp:351
       #3 0x2332895 in mongo::PortMessageServer::run() /home/s/code/mongo/mongo/src/mongo/util/net/message_server_port.cpp:176
       #4 0x15af712 in mongo::_initAndListen(int) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:589
       #5 0x15afb33 in mongo::initAndListen(int) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:594
       #6 0x15b1304 in mongoDbMain(int, char**, char**) /home/s/code/mongo/mongo/src/mongo/db/db.cpp:823
       #7 0x15afedd in main /home/s/code/mongo/mongo/src/mongo/db/db.cpp:639
       #8 0x7f3b9a390ec4 in __libc_start_main /build/buildd/eglibc-2.19/csu/libc-start.c:287
      

      Version: 6c49d69bbae5d8807fc205dbca12eecf1a60258b

            Assignee:
            keith.bostic@mongodb.com Keith Bostic (Inactive)
            Reporter:
            kamran.khan Kamran K.
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: