Issue 7886 - mdb_ovpage_free() can break mdb_copy
Summary: mdb_ovpage_free() can break mdb_copy
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-28 16:00 UTC by Hallvard Furuseth
Modified: 2014-12-11 01:02 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Hallvard Furuseth 2014-06-28 16:00:55 UTC
Full_Name: Hallvard B Furuseth
Version: LMDB_0.9.13
OS: Linux x86_64
URL: 
Submission from: (NULL) (81.191.45.35)
Submitted by: hallvard


Allocate an ovpage from mt_next_pgno, mdb_ovpage_free() it
and commit: The datafile may end before MDB_meta.mm_last_pg
since the ovpage was never written.  mdb_env_copyfd() & co
break when they read the file to mm_last_pg.

Same with loose pages if mdb_page_flush() skipped them,
which it could:  ecde3a4008f5080d8264926f49680db27804787f
in my branch mdb/loose3.

Bug demo:

  rm data.mdb; ./a.out && ./mdb_copy . > copy.mdb
  ./mdb_copy: copying failed, error 14 (Bad address)

(Piping it to /dev/null succeeds on Linux, apparently
it doesn't read anything.)

#include "lmdb.h"
#include <stdio.h>
#include <stdlib.h>
#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
    "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))

int main(void)
{
    int rc;
    unsigned sz;
    MDB_env *env;
    MDB_txn *txn;
    MDB_dbi dbi;
    static char buf[20000];
    E(mdb_env_create(&env));
    E(mdb_env_open(env, ".", 0, 0664));
    for (sz = 0; sz<=sizeof(buf); sz = (sz==2 ? sizeof(buf) : sz+1)) {
        E(mdb_txn_begin(env, NULL, 0, &txn));
        E(mdb_dbi_open(txn, NULL, 0, &dbi));
        E(mdb_put(txn, dbi, &(MDB_val){4,&sz}, &(MDB_val){sz,buf}, 0));
        if (sz)
            E(mdb_del(txn, dbi, &(MDB_val){4,&sz}, NULL));
        E(mdb_txn_commit(txn));
    }
    mdb_env_close(env);
    return 0;
}
Comment 1 Howard Chu 2014-06-30 04:44:38 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 2 Howard Chu 2014-06-30 11:44:00 UTC
h.b.furuseth@usit.uio.no wrote:
> Full_Name: Hallvard B Furuseth
> Version: LMDB_0.9.13
> OS: Linux x86_64
> URL:
> Submission from: (NULL) (81.191.45.35)
> Submitted by: hallvard
>
>
> Allocate an ovpage from mt_next_pgno, mdb_ovpage_free() it
> and commit: The datafile may end before MDB_meta.mm_last_pg
> since the ovpage was never written.  mdb_env_copyfd() & co
> break when they read the file to mm_last_pg.

fixed in mdb.master
>
> Same with loose pages if mdb_page_flush() skipped them,
> which it could:  ecde3a4008f5080d8264926f49680db27804787f
> in my branch mdb/loose3.
>
> Bug demo:
>
>    rm data.mdb; ./a.out && ./mdb_copy . > copy.mdb
>    ./mdb_copy: copying failed, error 14 (Bad address)
>
> (Piping it to /dev/null succeeds on Linux, apparently
> it doesn't read anything.)
>
> #include "lmdb.h"
> #include <stdio.h>
> #include <stdlib.h>
> #define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
> #define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
>      "%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))
>
> int main(void)
> {
>      int rc;
>      unsigned sz;
>      MDB_env *env;
>      MDB_txn *txn;
>      MDB_dbi dbi;
>      static char buf[20000];
>      E(mdb_env_create(&env));
>      E(mdb_env_open(env, ".", 0, 0664));
>      for (sz = 0; sz<=sizeof(buf); sz = (sz==2 ? sizeof(buf) : sz+1)) {
>          E(mdb_txn_begin(env, NULL, 0, &txn));
>          E(mdb_dbi_open(txn, NULL, 0, &dbi));
>          E(mdb_put(txn, dbi, &(MDB_val){4,&sz}, &(MDB_val){sz,buf}, 0));
>          if (sz)
>              E(mdb_del(txn, dbi, &(MDB_val){4,&sz}, NULL));
>          E(mdb_txn_commit(txn));
>      }
>      mdb_env_close(env);
>      return 0;
> }
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 3 OpenLDAP project 2014-08-01 21:04:51 UTC
fixed in mdb.master
Comment 4 Quanah Gibson-Mount 2014-12-11 01:02:49 UTC
changed state Test to Closed