[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