[Pkg-mongodb-maintainers] [pkg-mongodb] 311/394: Backport potential information leak security fix
Apollon Oikonomopoulos
apoikos at moszumanska.debian.org
Wed Sep 21 13:59:50 UTC 2016
This is an automated email from the git hooks/post-receive script.
apoikos pushed a commit to branch master
in repository pkg-mongodb.
commit 6765ebc6f86fd55741c485471c49ce07390fe1c4
Author: Laszlo Boszormenyi (GCS) <gcs at debian.org>
Date: Tue Jun 30 16:04:04 2015 +0000
Backport potential information leak security fix
---
debian/changelog | 6 +
.../9105b69e1ded5b7d0d384d574103b0ee6bbb6122.patch | 801 +++++++++++++++++++++
.../cefb0ef38f050b73b2bf8211add55f3749753e0a.patch | 28 +
debian/patches/series | 2 +
4 files changed, 837 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 95dd2f2..b4e5674 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+mongodb (1:2.4.10-4) unstable; urgency=high
+
+ * Backport potential information leak security fix from 2.4.11 .
+
+ -- Laszlo Boszormenyi (GCS) <gcs at debian.org> Mon, 10 Nov 2014 18:24:57 +0000
+
mongodb (1:2.4.10-3) unstable; urgency=medium
* Enable systemd unit file (closes: #767211).
diff --git a/debian/patches/9105b69e1ded5b7d0d384d574103b0ee6bbb6122.patch b/debian/patches/9105b69e1ded5b7d0d384d574103b0ee6bbb6122.patch
new file mode 100644
index 0000000..6476e86
--- /dev/null
+++ b/debian/patches/9105b69e1ded5b7d0d384d574103b0ee6bbb6122.patch
@@ -0,0 +1,801 @@
+From 9105b69e1ded5b7d0d384d574103b0ee6bbb6122 Mon Sep 17 00:00:00 2001
+From: Mark Benvenuto <mark.benvenuto at mongodb.com>
+Date: Mon, 11 Aug 2014 18:48:46 -0400
+Subject: [PATCH] SERVER-14268: Backport from 2.6 to 2.4
+
+---
+ src/mongo/db/SConscript | 11 +++
+ src/mongo/db/dbmessage.cpp | 134 ++++++++++++++++++++++++++++++++
+ src/mongo/db/dbmessage.h | 155 ++++++++++++-------------------------
+ src/mongo/db/dbmessage_test.cpp | 143 ++++++++++++++++++++++++++++++++++
+ src/mongo/db/instance.cpp | 65 +++++++++-------
+ src/mongo/s/cursors.cpp | 11 +--
+ src/mongo/s/request.cpp | 3 +-
+ src/mongo/s/strategy_shard.cpp | 11 ++-
+ src/mongo/s/writeback_listener.cpp | 2 +-
+ src/mongo/tools/sniffer.cpp | 6 +-
+ src/mongo/util/net/message.h | 10 ++-
+ 11 files changed, 401 insertions(+), 150 deletions(-)
+ create mode 100644 src/mongo/db/dbmessage_test.cpp
+
+diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
+index 2d3a4f6..8ac7897 100644
+--- a/src/mongo/db/SConscript
++++ b/src/mongo/db/SConscript
+@@ -13,3 +13,14 @@ env.StaticLibrary('common', ['field_ref.cpp'],
+ '$BUILD_DIR/mongo/foundation'])
+
+ env.CppUnitTest('field_ref_test', ['field_ref_test.cpp'], LIBDEPS=['common'])
++
++env.CppUnitTest(
++ target="dbmessage_test",
++ source=[
++ "dbmessage_test.cpp"
++ ],
++ LIBDEPS=[
++ "common",
++ "$BUILD_DIR/mongo/clientdriver",
++ ],
++)
+diff --git a/src/mongo/db/dbmessage.cpp b/src/mongo/db/dbmessage.cpp
+index 3f1e866..aebe88b 100644
+--- a/src/mongo/db/dbmessage.cpp
++++ b/src/mongo/db/dbmessage.cpp
+@@ -52,6 +52,140 @@ namespace mongo {
+ return ss.str();
+ }
+
++ DbMessage::DbMessage(const Message& msg) : _msg(msg), _nsStart(NULL), _mark(NULL), _nsLen(0) {
++ // for received messages, Message has only one buffer
++ _theEnd = _msg.singleData()->_data + _msg.singleData()->dataLen();
++ _nextjsobj = _msg.singleData()->_data;
++
++ _reserved = readAndAdvance<int>();
++
++ // Read packet for NS
++ if (messageShouldHaveNs()) {
++
++ // Limit = buffer size of message -
++ // (first int4 in message which is either flags or a zero constant)
++ size_t limit = _msg.singleData()->dataLen() - sizeof(int);
++
++ _nsStart = _nextjsobj;
++ _nsLen = strnlen(_nsStart, limit);
++
++ // Validate there is room for a null byte in the buffer
++ // Strings can be zero length
++ uassert(18633, "Failed to parse ns string", _nsLen <= (limit - 1));
++
++ _nextjsobj += _nsLen + 1; // skip namespace + null
++ }
++ }
++
++ const char * DbMessage::getns() const {
++ verify(messageShouldHaveNs());
++ return _nsStart;
++ }
++
++ long long DbMessage::getInt64(int offsetBytes) const {
++ verify(messageShouldHaveNs());
++ const char* p = _nsStart + _nsLen + 1;
++ checkReadOffset<long long>(p, offsetBytes);
++
++ return ((reinterpret_cast<const long long*>(p + offsetBytes)))[0];
++ }
++
++ int DbMessage::getQueryNToReturn() const {
++ verify(messageShouldHaveNs());
++ const char* p = _nsStart + _nsLen + 1;
++ checkRead<int>(p, 2);
++
++ return ((reinterpret_cast<const int*>(p)))[1];
++ }
++
++
++ int DbMessage::getFlags() const {
++ verify(messageShouldHaveNs());
++ const char* p = _nsStart + _nsLen + 1;
++ checkRead<int>(p, 1);
++
++ return ((reinterpret_cast<const int*>(p)))[0];
++ }
++
++ void DbMessage::setFlags(int value) {
++ verify(messageShouldHaveNs());
++ char* p = const_cast<char*>(_nsStart) + _nsLen + 1;
++ checkRead<int>(p, 1);
++
++ ((reinterpret_cast<int*>(p)))[0] = value;
++ }
++
++
++ int DbMessage::pullInt() {
++ return readAndAdvance<int>();
++ }
++
++ long long DbMessage::pullInt64() {
++ return readAndAdvance<long long>();
++ }
++
++ const long long* DbMessage::getArray(size_t count) const {
++ checkRead<long long>(_nextjsobj, count);
++ return reinterpret_cast<const long long*>(_nextjsobj);
++ }
++
++ BSONObj DbMessage::nextJsObj() {
++ massert(10304,
++ "Client Error: Remaining data too small for BSON object",
++ _nextjsobj != NULL && _theEnd - _nextjsobj >= 5);
++
++ if (cmdLine.objcheck) {
++ Status status = validateBSON(_nextjsobj, _theEnd - _nextjsobj);
++ massert(10307,
++ str::stream() << "Client Error: bad object in message: " << status.reason(),
++ status.isOK());
++ }
++
++ BSONObj js(_nextjsobj);
++ verify(js.objsize() >= 5);
++ verify(js.objsize() <= (_theEnd - _nextjsobj));
++
++ _nextjsobj += js.objsize();
++ if (_nextjsobj >= _theEnd)
++ _nextjsobj = NULL;
++ return js;
++ }
++
++ void DbMessage::markReset(const char * toMark) {
++ if (toMark == NULL) {
++ toMark = _mark;
++ }
++
++ verify(toMark);
++ _nextjsobj = toMark;
++ }
++
++ template<typename T>
++ void DbMessage::checkRead(const char* start, size_t count) const {
++ if ((_theEnd - start) < static_cast<int>(sizeof(T) * count)) {
++ uassert(18634, "Not enough data to read", false);
++ }
++ }
++
++ template<typename T>
++ void DbMessage::checkReadOffset(const char* start, size_t offset) const {
++ if ((_theEnd - start) < static_cast<int>(offset + sizeof(T))) {
++ uassert(18626, "Not enough data to read", false);
++ }
++ }
++
++ template<typename T>
++ T DbMessage::read() const {
++ checkRead<T>(_nextjsobj, 1);
++
++ return *(reinterpret_cast<const T*>(_nextjsobj));
++ }
++
++ template<typename T> T DbMessage::readAndAdvance() {
++ T t = read<T>();
++ _nextjsobj += sizeof(T);
++ return t;
++ }
+
+ void replyToQuery(int queryResultFlags,
+ AbstractMessagingPort* p, Message& requestMsg,
+diff --git a/src/mongo/db/dbmessage.h b/src/mongo/db/dbmessage.h
+index aeb9313..50658dd 100644
+--- a/src/mongo/db/dbmessage.h
++++ b/src/mongo/db/dbmessage.h
+@@ -110,138 +110,83 @@ namespace mongo {
+ See http://dochub.mongodb.org/core/mongowireprotocol
+ */
+ class DbMessage {
++ // Assume sizeof(int) == 4 bytes
++ BOOST_STATIC_ASSERT(sizeof(int) == 4);
++
+ public:
+- DbMessage(const Message& _m) : m(_m) , mark(0) {
+- // for received messages, Message has only one buffer
+- theEnd = _m.singleData()->_data + _m.header()->dataLen();
+- char *r = _m.singleData()->_data;
+- reserved = (int *) r;
+- data = r + 4;
+- nextjsobj = data;
++ // Note: DbMessage constructor reads the first 4 bytes and stores it in reserved
++ DbMessage(const Message& msg);
++
++ // Indicates whether this message is expected to have a ns
++ // or in the case of dbMsg, a string in the same place as ns
++ bool messageShouldHaveNs() const {
++ return (_msg.operation() >= dbMsg) && (_msg.operation() <= dbDelete);
+ }
+
+- /** the 32 bit field before the ns
++ /** the 32 bit field before the ns
+ * track all bit usage here as its cross op
+ * 0: InsertOption_ContinueOnError
+ * 1: fromWriteback
+ */
+- int& reservedField() { return *reserved; }
++ int reservedField() const { return _reserved; }
++ void setReservedField(int value) { _reserved = value; }
+
+- const char * getns() const {
+- return data;
+- }
+- void getns(Namespace& ns) const {
+- ns = data;
+- }
++ const char * getns() const;
++ int getQueryNToReturn() const;
+
+- const char * afterNS() const {
+- return data + strlen( data ) + 1;
+- }
++ int getFlags() const;
++ void setFlags(int value);
+
+- int getInt( int num ) const {
+- const int * foo = (const int*)afterNS();
+- return foo[num];
+- }
++ long long getInt64(int offsetBytes) const;
+
+- int getQueryNToReturn() const {
+- return getInt( 1 );
+- }
++ int pullInt();
++ long long pullInt64();
++ const long long* getArray(size_t count) const;
+
+- /**
+- * get an int64 at specified offsetBytes after ns
+- */
+- long long getInt64( int offsetBytes ) const {
+- const char * x = afterNS();
+- x += offsetBytes;
+- const long long * ll = (const long long*)x;
+- return ll[0];
++ /* for insert and update msgs */
++ bool moreJSObjs() const {
++ return _nextjsobj != 0;
+ }
+
+- void resetPull() { nextjsobj = data; }
+- int pullInt() const { return pullInt(); }
+- int& pullInt() {
+- if ( nextjsobj == data )
+- nextjsobj += strlen(data) + 1; // skip namespace
+- int& i = *((int *)nextjsobj);
+- nextjsobj += 4;
+- return i;
+- }
+- long long pullInt64() const {
+- return pullInt64();
+- }
+- long long &pullInt64() {
+- if ( nextjsobj == data )
+- nextjsobj += strlen(data) + 1; // skip namespace
+- long long &i = *((long long *)nextjsobj);
+- nextjsobj += 8;
+- return i;
+- }
++ BSONObj nextJsObj();
+
+- OID* getOID() const {
+- return (OID *) (data + strlen(data) + 1); // skip namespace
+- }
++ const Message& msg() const { return _msg; }
+
+- void getQueryStuff(const char *&query, int& ntoreturn) {
+- int *i = (int *) (data + strlen(data) + 1);
+- ntoreturn = *i;
+- i++;
+- query = (const char *) i;
++ const char * markGet() const {
++ return _nextjsobj;
+ }
+
+- /* for insert and update msgs */
+- bool moreJSObjs() const {
+- return nextjsobj != 0;
++ void markSet() {
++ _mark = _nextjsobj;
+ }
+- BSONObj nextJsObj() {
+- if ( nextjsobj == data ) {
+- nextjsobj += strlen(data) + 1; // skip namespace
+- massert( 13066 , "Message contains no documents", theEnd > nextjsobj );
+- }
+- massert( 10304,
+- "Client Error: Remaining data too small for BSON object",
+- theEnd - nextjsobj >= 5 );
+-
+- if ( cmdLine.objcheck ) {
+- Status status = validateBSON( nextjsobj, theEnd - nextjsobj );
+- massert( 10307,
+- str::stream() << "Client Error: bad object in message: " << status.reason(),
+- status.isOK() );
+- }
+
+- BSONObj js(nextjsobj);
+- verify( js.objsize() >= 5 );
+- verify( js.objsize() < ( theEnd - data ) );
++ void markReset(const char * toMark = NULL);
+
+- nextjsobj += js.objsize();
+- if ( nextjsobj >= theEnd )
+- nextjsobj = 0;
+- return js;
+- }
++ private:
++ // Check if we have enough data to read
++ template<typename T>
++ void checkRead(const char* start, size_t count = 0) const;
+
+- const Message& msg() const { return m; }
++ template<typename T>
++ void checkReadOffset(const char* start, size_t offset) const;
+
+- const char * markGet() {
+- return nextjsobj;
+- }
++ // Read some type without advancing our position
++ template<typename T>
++ T read() const;
+
+- void markSet() {
+- mark = nextjsobj;
+- }
++ // Read some type, and advance our position
++ template<typename T> T readAndAdvance();
+
+- void markReset( const char * toMark = 0) {
+- if( toMark == 0 ) toMark = mark;
+- verify( toMark );
+- nextjsobj = toMark;
+- }
++ const Message& _msg;
++ int _reserved; // flags or zero depending on packet, starts the packet
+
+- private:
+- const Message& m;
+- int* reserved;
+- const char *data;
+- const char *nextjsobj;
+- const char *theEnd;
++ const char* _nsStart; // start of namespace string, +4 from message start
++ const char* _nextjsobj; // current position reading packet
++ const char* _theEnd; // end of packet
++
++ const char* _mark;
+
+- const char * mark;
++ unsigned int _nsLen;
+ };
+
+
+diff --git a/src/mongo/db/dbmessage_test.cpp b/src/mongo/db/dbmessage_test.cpp
+new file mode 100644
+index 0000000..867a52d
+--- /dev/null
++++ b/src/mongo/db/dbmessage_test.cpp
+@@ -0,0 +1,143 @@
++/**
++ * Copyright (C) 2014 MongoDB Inc.
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Affero General Public License, version 3,
++ * as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Affero General Public License for more details.
++ *
++ * You should have received a copy of the GNU Affero General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ *
++ * As a special exception, the copyright holders give permission to link the
++ * code of portions of this program with the OpenSSL library under certain
++ * conditions as described in each individual source file and distribute
++ * linked combinations including the program with the OpenSSL library. You
++ * must comply with the GNU Affero General Public License in all respects
++ * for all of the code used other than as permitted herein. If you modify
++ * file(s) with this exception, you may extend this exception to your
++ * version of the file(s), but you are not obligated to do so. If you do not
++ * wish to do so, delete this exception statement from your version. If you
++ * delete this exception statement from all source files in the program,
++ * then also delete it in the license file.
++ */
++
++#include <string>
++
++#include "mongo/bson/util/builder.h"
++#include "mongo/db/dbmessage.h"
++#include "mongo/unittest/unittest.h"
++
++namespace mongo {
++ using std::string;
++
++ // Test if the reserved field is short of 4 bytes
++ TEST(DBMessage1, ShortFlags) {
++ BufBuilder b;
++ string ns("test");
++
++ b.appendChar( 1 );
++
++ Message toSend;
++ toSend.setData( dbDelete , b.buf() , b.len() );
++
++ ASSERT_THROWS(DbMessage d1(toSend), UserException);
++ }
++
++ // Test a short NS missing a trailing null
++ TEST(DBMessage1, BadNS) {
++ BufBuilder b;
++
++ b.appendNum( static_cast<int>(1) );
++ b.appendChar( 'b' );
++ b.appendChar( 'a' );
++ b.appendChar( 'd' );
++ // Forget to append \0
++
++ Message toSend;
++ toSend.setData( dbDelete , b.buf() , b.len() );
++
++ ASSERT_THROWS(DbMessage d1(toSend), UserException);
++ }
++
++ // Test a valid kill message and try an extra pull
++ TEST(DBMessage1, GoodKill) {
++ BufBuilder b;
++
++ b.appendNum( static_cast<int>(1) );
++ b.appendNum( static_cast<int>(3) );
++
++ Message toSend;
++ toSend.setData( dbKillCursors , b.buf() , b.len() );
++
++ DbMessage d1(toSend);
++ ASSERT_EQUALS(3, d1.pullInt());
++
++ ASSERT_THROWS(d1.pullInt(), UserException);
++ }
++
++ // Try a bad read of a type too large
++ TEST(DBMessage1, GoodKill2) {
++ BufBuilder b;
++
++ b.appendNum( static_cast<int>(1) );
++ b.appendNum( static_cast<int>(3) );
++
++ Message toSend;
++ toSend.setData( dbKillCursors , b.buf() , b.len() );
++
++ DbMessage d1(toSend);
++ ASSERT_THROWS(d1.pullInt64(), UserException);
++ }
++
++ // Test a basic good insert, and an extra read
++ TEST(DBMessage1, GoodInsert) {
++ BufBuilder b;
++ string ns("test");
++
++ b.appendNum( static_cast<int>(1) );
++ b.appendStr(ns);
++ b.appendNum( static_cast<int>(3) );
++ b.appendNum( static_cast<int>(39) );
++
++ Message toSend;
++ toSend.setData( dbInsert , b.buf() , b.len() );
++
++ DbMessage d1(toSend);
++ ASSERT_EQUALS(3, d1.pullInt());
++ ASSERT_EQUALS(39, d1.pullInt());
++ ASSERT_THROWS(d1.pullInt(), UserException);
++ }
++
++ // Test a basic good insert, and an extra read
++ TEST(DBMessage1, GoodInsert2) {
++ BufBuilder b;
++ string ns("test");
++
++ b.appendNum( static_cast<int>(1) );
++ b.appendStr(ns);
++ b.appendNum( static_cast<int>(3) );
++ b.appendNum( static_cast<int>(39) );
++
++ BSONObj bo = BSON( "ts" << 0 );
++ bo.appendSelfToBufBuilder( b );
++
++ Message toSend;
++ toSend.setData( dbInsert , b.buf() , b.len() );
++
++ DbMessage d1(toSend);
++ ASSERT_EQUALS(3, d1.pullInt());
++
++
++ ASSERT_EQUALS(39, d1.pullInt());
++ BSONObj bo2 = d1.nextJsObj();
++ ASSERT_THROWS(d1.nextJsObj(), MsgAssertionException);
++ }
++
++
++
++} // mongo namespace
+diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
+index cf3d084..c4fb9f7 100644
+--- a/src/mongo/db/instance.cpp
++++ b/src/mongo/db/instance.cpp
+@@ -339,10 +339,13 @@ namespace mongo {
+ // before we lock...
+ int op = m.operation();
+ bool isCommand = false;
+- const char *ns = m.singleData()->_data + 4;
++
++ DbMessage dbmsg(m);
+
+ if ( op == dbQuery ) {
+- if( strstr(ns, ".$cmd") ) {
++ const char *ns = dbmsg.getns();
++
++ if (strstr(ns, ".$cmd")) {
+ isCommand = true;
+ opwrite(m);
+ if( strstr(ns, ".$cmd.sys.") ) {
+@@ -406,7 +409,8 @@ namespace mongo {
+ }
+ else if ( op == dbMsg ) {
+ // deprecated - replaced by commands
+- char *p = m.singleData()->_data;
++ const char *p = dbmsg.getns();
++
+ int len = strlen(p);
+ if ( len > 400 )
+ out() << curTimeMillis64() % 10000 <<
+@@ -423,8 +427,6 @@ namespace mongo {
+ }
+ else {
+ try {
+- const NamespaceString nsString( ns );
+-
+ // The following operations all require authorization.
+ // dbInsert, dbUpdate and dbDelete can be easily pre-authorized,
+ // here, but dbKillCursors cannot.
+@@ -433,28 +435,36 @@ namespace mongo {
+ logThreshold = 10;
+ receivedKillCursors(m);
+ }
+- else if ( !nsString.isValid() ) {
+- // Only killCursors doesn't care about namespaces
+- uassert( 16257, str::stream() << "Invalid ns [" << ns << "]", false );
+- }
+- else if ( op == dbInsert ) {
+- receivedInsert(m, currentOp);
+- }
+- else if ( op == dbUpdate ) {
+- receivedUpdate(m, currentOp);
+- }
+- else if ( op == dbDelete ) {
+- receivedDelete(m, currentOp);
+- }
+- else {
++ else if (op != dbInsert && op != dbUpdate && op != dbDelete) {
+ mongo::log() << " operation isn't supported: " << op << endl;
+ currentOp.done();
+ shouldLog = true;
+ }
+- }
+- catch ( UserException& ue ) {
+- tlog(3) << " Caught Assertion in " << opToString(op) << ", continuing "
+- << ue.toString() << endl;
++ else {
++ const char* ns = dbmsg.getns();
++ const NamespaceString nsString(ns);
++
++ if (!nsString.isValid()) {
++ uassert(16257, str::stream() << "Invalid ns [" << ns << "]", false);
++ }
++ else if (op == dbInsert) {
++ receivedInsert(m, currentOp);
++ }
++ else if (op == dbUpdate) {
++ receivedUpdate(m, currentOp);
++ }
++ else if (op == dbDelete) {
++ receivedDelete(m, currentOp);
++ }
++ else {
++ fassertFailed(18625);
++ }
++ }
++ }
++ catch (const UserException& ue) {
++ setLastError(ue.getCode(), ue.getInfo().msg.c_str());
++ LOG(3) << " Caught Assertion in " << opToString(op) << ", continuing "
++ << ue.toString() << endl;
+ debug.exceptionInfo = ue.getInfo();
+ }
+ catch ( AssertionException& e ) {
+@@ -492,9 +502,8 @@ namespace mongo {
+ } /* assembleResponse() */
+
+ void receivedKillCursors(Message& m) {
+- int *x = (int *) m.singleData()->_data;
+- x++; // reserved
+- int n = *x++;
++ DbMessage dbmessage(m);
++ int n = dbmessage.pullInt();
+
+ uassert( 13659 , "sent 0 cursors to kill" , n != 0 );
+ massert( 13658 , str::stream() << "bad kill cursors size: " << m.dataSize() , m.dataSize() == 8 + ( 8 * n ) );
+@@ -505,7 +514,9 @@ namespace mongo {
+ verify( n < 30000 );
+ }
+
+- int found = ClientCursor::eraseIfAuthorized(n, (long long *) x);
++ const long long* cursorArray = dbmessage.getArray(n);
++
++ int found = ClientCursor::eraseIfAuthorized(n, (long long *)cursorArray);
+
+ if ( logLevel > 0 || found != n ) {
+ LOG( found == n ? 1 : 0 ) << "killcursors: found " << found << " of " << n << endl;
+diff --git a/src/mongo/s/cursors.cpp b/src/mongo/s/cursors.cpp
+index 4e904e3..4cec5a6 100644
+--- a/src/mongo/s/cursors.cpp
++++ b/src/mongo/s/cursors.cpp
+@@ -270,19 +270,20 @@ namespace mongo {
+ }
+
+ void CursorCache::gotKillCursors(Message& m ) {
+- int *x = (int *) m.singleData()->_data;
+- x++; // reserved
+- int n = *x++;
++ DbMessage dbmessage(m);
++ int n = dbmessage.pullInt();
+
+ if ( n > 2000 ) {
+ LOG( n < 30000 ? LL_WARNING : LL_ERROR ) << "receivedKillCursors, n=" << n << endl;
+ }
+
+-
+ uassert( 13286 , "sent 0 cursors to kill" , n >= 1 );
+ uassert( 13287 , "too many cursors to kill" , n < 30000 );
++ massert( 18632 , str::stream() << "bad kill cursors size: " << m.dataSize(),
++ m.dataSize() == 8 + ( 8 * n ) );
++
+
+- long long * cursors = (long long *)x;
++ const long long* cursors = dbmessage.getArray(n);
+ AuthorizationManager* authManager =
+ ClientBasic::getCurrent()->getAuthorizationManager();
+ for ( int i=0; i<n; i++ ) {
+diff --git a/src/mongo/s/request.cpp b/src/mongo/s/request.cpp
+index ed9527d..033ed14 100644
+--- a/src/mongo/s/request.cpp
++++ b/src/mongo/s/request.cpp
+@@ -37,7 +37,6 @@ namespace mongo {
+ Request::Request( Message& m, AbstractMessagingPort* p ) :
+ _m(m) , _d( m ) , _p(p) , _didInit(false) {
+
+- verify( _d.getns() );
+ _id = _m.header()->id;
+
+ _clientInfo = ClientInfo::get();
+@@ -58,7 +57,7 @@ namespace mongo {
+
+ // Deprecated, will move to the strategy itself
+ void Request::reset() {
+- if ( _m.operation() == dbKillCursors ) {
++ if ( !_d.messageShouldHaveNs()) {
+ return;
+ }
+
+diff --git a/src/mongo/s/strategy_shard.cpp b/src/mongo/s/strategy_shard.cpp
+index 560a4ac..c3d9ede 100644
+--- a/src/mongo/s/strategy_shard.cpp
++++ b/src/mongo/s/strategy_shard.cpp
+@@ -1043,8 +1043,9 @@ namespace mongo {
+ // TODO: make this safer w/ shard add/remove
+ //
+
+- int* opts = (int*)( r.d().afterNS() );
+- opts[0] |= UpdateOption_Broadcast; // this means don't check shard version in mongod
++ int opts = r.d().getFlags();
++ opts |= UpdateOption_Broadcast; // this means don't check shard version in mongod
++ r.d().setFlags(opts);
+ broadcastWrite( dbUpdate, r );
+ return;
+ }
+@@ -1192,8 +1193,10 @@ namespace mongo {
+
+ if( ! shard ){
+
+- int * x = (int*)(r.d().afterNS());
+- x[0] |= RemoveOption_Broadcast; // this means don't check shard version in mongod
++ int opts = r.d().getFlags();
++ opts |= RemoveOption_Broadcast; // this means don't check shard version in mongod
++ r.d().setFlags(opts);
++
+ broadcastWrite(dbDelete, r);
+ return;
+ }
+diff --git a/src/mongo/s/writeback_listener.cpp b/src/mongo/s/writeback_listener.cpp
+index 0695c4c..8eddf78 100644
+--- a/src/mongo/s/writeback_listener.cpp
++++ b/src/mongo/s/writeback_listener.cpp
+@@ -294,7 +294,7 @@ namespace mongo {
+ Request r( msg , 0 );
+ r.init();
+
+- r.d().reservedField() |= Reserved_FromWriteback;
++ r.d().setReservedField(r.d().reservedField() | Reserved_FromWriteback);
+
+ ClientInfo * ci = r.getClientInfo();
+ if (!noauth) {
+diff --git a/src/mongo/tools/sniffer.cpp b/src/mongo/tools/sniffer.cpp
+index 5e2ac66..b6c97d9 100644
+--- a/src/mongo/tools/sniffer.cpp
++++ b/src/mongo/tools/sniffer.cpp
+@@ -329,9 +329,7 @@ void processMessage( Connection& c , Message& m ) {
+ break;
+ }
+ case mongo::dbKillCursors: {
+- int *x = (int *) m.singleData()->_data;
+- x++; // reserved
+- int n = *x;
++ int n = d.pullInt();
+ out() << "\tkillCursors n: " << n << endl;
+ break;
+ }
+@@ -357,7 +355,7 @@ void processMessage( Connection& c , Message& m ) {
+ if ( m.operation() == mongo::dbGetMore ) {
+ DbMessage d( m );
+ d.pullInt();
+- long long &cId = d.pullInt64();
++ long long cId = d.pullInt64();
+ cId = mapCursor[ c ][ cId ];
+ }
+ Message response;
+diff --git a/src/mongo/util/net/message.h b/src/mongo/util/net/message.h
+index ade0123..dee49f5 100644
+--- a/src/mongo/util/net/message.h
++++ b/src/mongo/util/net/message.h
+@@ -103,13 +103,18 @@ namespace mongo {
+
+ #pragma pack(1)
+ /* todo merge this with MSGHEADER (or inherit from it). */
+- struct MsgData {
++ class MsgData {
++ friend class Message;
++ friend class DbMessage;
++ friend class MessagingPort;
++ public:
+ int len; /* len of the msg, including this field */
+ MSGID id; /* request/reply id's match... */
+ MSGID responseTo; /* id of the message we are responding to */
+ short _operation;
+ char _flags;
+ char _version;
++
+ int operation() const {
+ return _operation;
+ }
+@@ -118,7 +123,6 @@ namespace mongo {
+ _version = 0;
+ _operation = o;
+ }
+- char _data[4];
+
+ int& dataAsInt() {
+ return *((int *) _data);
+@@ -140,6 +144,8 @@ namespace mongo {
+ }
+
+ int dataLen(); // len without header
++ private:
++ char _data[4]; //must be last member
+ };
+ const int MsgDataHeaderSize = sizeof(MsgData) - 4;
+ inline int MsgData::dataLen() {
diff --git a/debian/patches/cefb0ef38f050b73b2bf8211add55f3749753e0a.patch b/debian/patches/cefb0ef38f050b73b2bf8211add55f3749753e0a.patch
new file mode 100644
index 0000000..1649777
--- /dev/null
+++ b/debian/patches/cefb0ef38f050b73b2bf8211add55f3749753e0a.patch
@@ -0,0 +1,28 @@
+From cefb0ef38f050b73b2bf8211add55f3749753e0a Mon Sep 17 00:00:00 2001
+From: Mark Benvenuto <mark.benvenuto at mongodb.com>
+Date: Thu, 14 Aug 2014 17:33:12 -0400
+Subject: [PATCH] SERVER-14268: Backport from 2.6 to 2.4 - disable test
+
+---
+ src/mongo/db/SConscript | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
+index 8ac7897..2d3a4f6 100644
+--- a/src/mongo/db/SConscript
++++ b/src/mongo/db/SConscript
+@@ -13,14 +13,3 @@ env.StaticLibrary('common', ['field_ref.cpp'],
+ '$BUILD_DIR/mongo/foundation'])
+
+ env.CppUnitTest('field_ref_test', ['field_ref_test.cpp'], LIBDEPS=['common'])
+-
+-env.CppUnitTest(
+- target="dbmessage_test",
+- source=[
+- "dbmessage_test.cpp"
+- ],
+- LIBDEPS=[
+- "common",
+- "$BUILD_DIR/mongo/clientdriver",
+- ],
+-)
diff --git a/debian/patches/series b/debian/patches/series
index 54d40fa..18b9e89 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -13,3 +13,5 @@
0004-Support-ppc64el-builds.patch
0012-support-gnu.patch
no-unused-function.patch
+9105b69e1ded5b7d0d384d574103b0ee6bbb6122.patch
+cefb0ef38f050b73b2bf8211add55f3749753e0a.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mongodb/pkg-mongodb.git
More information about the Pkg-mongodb-maintainers
mailing list