From 470c3ae1c5dbde50a5ce77153429c854da25aac3 Mon Sep 17 00:00:00 2001 From: yangl777 Date: Mon, 3 Jun 2024 08:38:50 +0000 Subject: [PATCH] fix CVE-2021-3670 --- backport-CVE-2021-3670.patch | 165 +++++++++++++++++++++++++++++++++++ libldb.spec | 9 +- 2 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2021-3670.patch diff --git a/backport-CVE-2021-3670.patch b/backport-CVE-2021-3670.patch new file mode 100644 index 0000000..e0a62aa --- /dev/null +++ b/backport-CVE-2021-3670.patch @@ -0,0 +1,165 @@ +From 1d5b155619bc532c46932965b215bd73a920e56f Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Mon, 27 Sep 2021 16:47:46 +1300 +Subject: [PATCH] CVE-2021-3670 ldb: Confirm the request has not yet timed out + in ldb filter processing + +The LDB filter processing is where the time is spent in the LDB stack +but the timeout event will not get run while this is ongoing, so we +must confirm we have not yet timed out manually. + +RN: Ensure that the LDB request has not timed out during filter processing +as the LDAP server MaxQueryDuration is otherwise not honoured. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694 + +Signed-off-by: Andrew Bartlett +Reviewed-by: Douglas Bagnall + +--- + ldb_key_value/ldb_kv.c | 2 ++ + ldb_key_value/ldb_kv.h | 10 +++++++++ + ldb_key_value/ldb_kv_index.c | 41 +++++++++++++++++++++++++++++++++++ + ldb_key_value/ldb_kv_search.c | 33 +++++++++++++++++++++++++++- + 4 files changed, 85 insertions(+), 1 deletion(-) + +diff --git a/ldb_key_value/ldb_kv.c b/ldb_key_value/ldb_kv.c +index 4e7b8a1..8e36dc6 100644 +--- a/ldb_key_value/ldb_kv.c ++++ b/ldb_key_value/ldb_kv.c +@@ -2082,6 +2082,8 @@ static int ldb_kv_handle_request(struct ldb_module *module, + } + } + ++ ac->timeout_timeval = tv; ++ + /* set a spy so that we do not try to use the request context + * if it is freed before ltdb_callback fires */ + ac->spy = talloc(req, struct ldb_kv_req_spy); +diff --git a/ldb_key_value/ldb_kv.h b/ldb_key_value/ldb_kv.h +index f9dffae..ac474b0 100644 +--- a/ldb_key_value/ldb_kv.h ++++ b/ldb_key_value/ldb_kv.h +@@ -152,6 +152,16 @@ struct ldb_kv_context { + struct ldb_module *module; + struct ldb_request *req; + ++ /* ++ * Required as we might not get to the event loop before the ++ * timeout, so we need some old-style cooperative multitasking ++ * here. ++ */ ++ struct timeval timeout_timeval; ++ ++ /* Used to throttle calls to gettimeofday() */ ++ size_t timeout_counter; ++ + bool request_terminated; + struct ldb_kv_req_spy *spy; + +diff --git a/ldb_key_value/ldb_kv_index.c b/ldb_key_value/ldb_kv_index.c +index 8e756c1..aca542c 100644 +--- a/ldb_key_value/ldb_kv_index.c ++++ b/ldb_key_value/ldb_kv_index.c +@@ -2324,6 +2324,47 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv, + for (i = 0; i < num_keys; i++) { + int ret; + bool matched; ++ ++ /* ++ * Check the time every 64 records, to reduce calls to ++ * gettimeofday(). This is a compromise, not all ++ * calls to ldb_match_message() will take the same ++ * time, most will run quickly but by luck it might be ++ * possible to have 64 records that are slow, doing a ++ * recursive search via LDAP_MATCHING_RULE_IN_CHAIN. ++ * ++ * Thankfully this is after index processing so only ++ * on the subset that matches some index (but still ++ * possibly a big one like objectclass=user) ++ */ ++ if (i % 64 == 0) { ++ struct timeval now = tevent_timeval_current(); ++ int timeval_cmp = tevent_timeval_compare(&ac->timeout_timeval, ++ &now); ++ ++ /* ++ * The search has taken too long. This is the ++ * most likely place for our time to expire, ++ * as we are checking the records after the ++ * index set intersection. This is now the ++ * slow process of checking if the records ++ * actually match. ++ * ++ * The tevent based timeout is not likely to ++ * be hit, sadly, as we don't run an event ++ * loop. ++ * ++ * While we are indexed and most of the work ++ * should have been done already, the ++ * ldb_match_* calls can be quite expensive if ++ * the caller uses LDAP_MATCHING_RULE_IN_CHAIN ++ */ ++ if (timeval_cmp <= 0) { ++ talloc_free(keys); ++ return LDB_ERR_TIME_LIMIT_EXCEEDED; ++ } ++ } ++ + msg = ldb_msg_new(ac); + if (!msg) { + talloc_free(keys); +diff --git a/ldb_key_value/ldb_kv_search.c b/ldb_key_value/ldb_kv_search.c +index f2d9619..9636828 100644 +--- a/ldb_key_value/ldb_kv_search.c ++++ b/ldb_key_value/ldb_kv_search.c +@@ -314,7 +314,8 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv, + struct ldb_context *ldb; + struct ldb_kv_context *ac; + struct ldb_message *msg, *filtered_msg; +- int ret; ++ struct timeval now; ++ int ret, timeval_cmp; + bool matched; + + ac = talloc_get_type(state, struct ldb_kv_context); +@@ -341,6 +342,36 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv, + return 0; + } + ++ /* ++ * Check the time every 64 records, to reduce calls to ++ * gettimeofday(). This is a compromise, not all calls to ++ * ldb_match_message() will take the same time, most will fail ++ * quickly but by luck it might be possible to have 64 records ++ * that are slow, doing a recursive search via ++ * LDAP_MATCHING_RULE_IN_CHAIN. ++ */ ++ if (ac->timeout_counter++ % 64 == 0) { ++ now = tevent_timeval_current(); ++ timeval_cmp = tevent_timeval_compare(&ac->timeout_timeval, ++ &now); ++ ++ /* ++ * The search has taken too long. This is the most ++ * likely place for our time to expire, as we are in ++ * an un-indexed search and we return the data from ++ * within this loop. The tevent based timeout is not ++ * likely to be hit, sadly. ++ * ++ * ldb_match_msg_error() can be quite expensive if a ++ * LDAP_MATCHING_RULE_IN_CHAIN extended match was ++ * specified. ++ */ ++ if (timeval_cmp <= 0) { ++ ac->error = LDB_ERR_TIME_LIMIT_EXCEEDED; ++ return -1; ++ } ++ } ++ + msg = ldb_msg_new(ac); + if (!msg) { + ac->error = LDB_ERR_OPERATIONS_ERROR; +-- +2.43.0 + diff --git a/libldb.spec b/libldb.spec index c06f610..b42fdcd 100644 --- a/libldb.spec +++ b/libldb.spec @@ -6,7 +6,7 @@ Name: libldb Version: 2.0.12 -Release: 4 +Release: 5 Summary: A schema-less, ldap like, API and database Requires: libtalloc%{?_isa} >= %{talloc_version} Requires: libtdb%{?_isa} >= %{tdb_version} @@ -22,6 +22,7 @@ Patch3: backport-002-CVE-2022-32746.patch Patch4: backport-003-CVE-2022-32746.patch Patch5: backport-004-CVE-2022-32746.patch Patch6: backport-005-CVE-2022-32746.patch +Patch7: backport-CVE-2021-3670.patch BuildRequires: gcc libtalloc-devel >= %{talloc_version} libtdb-devel >= %{tdb_version} BuildRequires: libtevent-devel >= %{tevent_version} lmdb-devel >= 0.9.16 popt-devel @@ -173,6 +174,12 @@ echo "%{_libdir}/ldb" > %{buildroot}/etc/ld.so.conf.d/%{name}-%{_arch}.conf %{_mandir}/man1/ldbsearch.1.* %changelog +* Mon Jun 03 2024 yanglu - 2.0.12-5 +- Type:CVE +- ID:CVE-2021-3670 +- SUG:NA +- DESC:fix CVE-2021-3670 + * Wed Aug 31 2022 xingwei - 2.0.12-4 - Type:requirement - ID:NA -- Gitee