diff options
author | Andrew Bartlett <abartlet@samba.org> | 2018-05-04 14:35:14 +1200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2018-05-09 04:29:48 +0200 |
commit | 1174b52b91de045b5c111dff97c49488ac963bfa (patch) | |
tree | edcfc6278291c9efd8b53736e1a967ba0f968d32 | |
parent | 4e78aeedb8329953df83fc7f2c191b2c97a051d0 (diff) | |
download | samba-1174b52b91de045b5c111dff97c49488ac963bfa.tar.gz |
ldb_tdb: Prevent ldb_tdb reuse after a fork()
We may relax this restriction in the future, but for now do not assume
that the caller has done a tdb_reopen_all() at the right time.
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.c | 111 | ||||
-rw-r--r-- | lib/ldb/ldb_tdb/ldb_tdb.h | 7 |
2 files changed, 109 insertions, 9 deletions
diff --git a/lib/ldb/ldb_tdb/ldb_tdb.c b/lib/ldb/ldb_tdb/ldb_tdb.c index 0833a4fd0ca..93fc96faca3 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/lib/ldb/ldb_tdb/ldb_tdb.c @@ -100,6 +100,17 @@ static int ltdb_lock_read(struct ldb_module *module) struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); int tdb_ret = 0; int ret; + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } if (tdb_transaction_active(ltdb->tdb) == false && ltdb->read_lock_count == 0) { @@ -128,6 +139,17 @@ static int ltdb_unlock_read(struct ldb_module *module) { void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } if (!tdb_transaction_active(ltdb->tdb) && ltdb->read_lock_count == 1) { tdb_unlockall_read(ltdb->tdb); ltdb->read_lock_count--; @@ -1447,21 +1469,69 @@ static int ltdb_rename(struct ltdb_context *ctx) static int ltdb_tdb_transaction_start(struct ltdb_private *ltdb) { + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(ltdb->module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_transaction_start(ltdb->tdb); } static int ltdb_tdb_transaction_cancel(struct ltdb_private *ltdb) { + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(ltdb->module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_transaction_cancel(ltdb->tdb); } static int ltdb_tdb_transaction_prepare_commit(struct ltdb_private *ltdb) { + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(ltdb->module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_transaction_prepare_commit(ltdb->tdb); } static int ltdb_tdb_transaction_commit(struct ltdb_private *ltdb) { + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(ltdb->module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + return tdb_transaction_commit(ltdb->tdb); } @@ -1470,6 +1540,18 @@ static int ltdb_start_trans(struct ldb_module *module) void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(ltdb->module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } + /* Do not take out the transaction lock on a read-only DB */ if (ltdb->read_only) { return LDB_ERR_UNWILLING_TO_PERFORM; @@ -1498,6 +1580,17 @@ static int ltdb_prepare_commit(struct ldb_module *module) int ret; void *data = ldb_module_get_private(module); struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private); + pid_t pid = getpid(); + + if (ltdb->pid != pid) { + ldb_asprintf_errstring( + ldb_module_get_ctx(module), + __location__": Reusing ldb opend by pid %d in " + "process %d\n", + ltdb->pid, + pid); + return LDB_ERR_PROTOCOL_ERROR; + } if (!ltdb->kv_ops->transaction_active(ltdb)) { ldb_set_errstring(ldb_module_get_ctx(module), @@ -2138,8 +2231,6 @@ int init_store(struct ltdb_private *ltdb, const char *options[], struct ldb_module **_module) { - struct ldb_module *module; - if (getenv("LDB_WARN_UNINDEXED")) { ltdb->warn_unindexed = true; } @@ -2150,23 +2241,25 @@ int init_store(struct ltdb_private *ltdb, ltdb->sequence_number = 0; - module = ldb_module_new(ldb, ldb, name, <db_ops); - if (!module) { + ltdb->pid = getpid(); + + ltdb->module = ldb_module_new(ldb, ldb, name, <db_ops); + if (!ltdb->module) { ldb_oom(ldb); talloc_free(ltdb); return LDB_ERR_OPERATIONS_ERROR; } - ldb_module_set_private(module, ltdb); - talloc_steal(module, ltdb); + ldb_module_set_private(ltdb->module, ltdb); + talloc_steal(ltdb->module, ltdb); - if (ltdb_cache_load(module) != 0) { + if (ltdb_cache_load(ltdb->module) != 0) { ldb_asprintf_errstring(ldb, "Unable to load ltdb cache " "records for backend '%s'", name); - talloc_free(module); + talloc_free(ltdb->module); return LDB_ERR_OPERATIONS_ERROR; } - *_module = module; + *_module = ltdb->module; /* * Set or override the maximum key length * diff --git a/lib/ldb/ldb_tdb/ldb_tdb.h b/lib/ldb/ldb_tdb/ldb_tdb.h index 4d531208da6..caaa67a98e1 100644 --- a/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/lib/ldb/ldb_tdb/ldb_tdb.h @@ -36,6 +36,7 @@ struct kv_db_ops { ldb_context */ struct ltdb_private { const struct kv_db_ops *kv_ops; + struct ldb_module *module; TDB_CONTEXT *tdb; unsigned int connect_flags; @@ -75,6 +76,12 @@ struct ltdb_private { * greater than this length will be rejected. */ unsigned max_key_length; + + /* + * The PID that opened this database so we don't work in a + * fork()ed child. + */ + pid_t pid; }; struct ltdb_context { |