summaryrefslogtreecommitdiff
path: root/net-nds/389-ds-base/files/389-ds-base-3.0.6-CVE-2025-2487.patch
blob: dbec67a4a40e2bbd8de60e7bb0cd0e6890891812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
From 40e752922e6160356399cd07169ec1f76dd7db99 Mon Sep 17 00:00:00 2001
From: Pierre Rogier <progier@redhat.com>
Date: Thu, 27 Feb 2025 16:36:48 +0100
Subject: [PATCH] Security fix for CVE-2025-2487

Description:
A denial of service vulnerability was found in the 389 Directory Server.
The 389 Directory Server may crash (Null Pointer Exception) after some
failed rename subtree operations (i.e. MODDN) issued by a user having enough
privileges to do so.

References:
- https://access.redhat.com/security/cve/CVE-2025-2487
- https://bugzilla.redhat.com/show_bug.cgi?id=2353071
---
 ldap/servers/slapd/back-ldbm/findentry.c   | 36 +++++++++++++++++-----
 ldap/servers/slapd/back-ldbm/ldbm_add.c    |  2 ++
 ldap/servers/slapd/back-ldbm/ldbm_modify.c |  6 ++++
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 13 ++++++--
 4 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/ldap/servers/slapd/back-ldbm/findentry.c b/ldap/servers/slapd/back-ldbm/findentry.c
index 7bb56ef2c4..907b4367a1 100644
--- a/ldap/servers/slapd/back-ldbm/findentry.c
+++ b/ldap/servers/slapd/back-ldbm/findentry.c
@@ -99,6 +99,7 @@ find_entry_internal_dn(
     int isroot = 0;
     int op_type;
     int reverted_entry = 0;
+    int return_err = LDAP_SUCCESS;
 
     /* get the managedsait ldap message control */
     slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
@@ -121,6 +122,7 @@ find_entry_internal_dn(
                 if (rc) { /* if check_entry_for_referral returns non-zero, result is sent. */
                     *rc = FE_RC_SENT_RESULT;
                 }
+                slapi_set_ldap_result(pb, LDAP_REFERRAL, NULL, NULL, 0, NULL);
                 return (NULL);
             }
         }
@@ -153,7 +155,12 @@ find_entry_internal_dn(
         slapi_log_err(SLAPI_LOG_ERR, "find_entry_internal_dn", "Retry count exceeded (%s)\n", slapi_sdn_get_dn(sdn));
     }
     if (reverted_entry) {
+        CACHE_RETURN(&inst->inst_cache, &e);
+        slapi_set_ldap_result(pb, LDAP_BUSY, NULL, NULL, 0, NULL);
         slapi_send_ldap_result(pb, LDAP_BUSY, NULL, "target entry busy because of a canceled operation", 0, NULL);
+        if (rc) {
+            *rc = FE_RC_SENT_RESULT;  /* Result is sent */
+        }
         return (NULL);
     }
     /*
@@ -179,6 +186,7 @@ find_entry_internal_dn(
                 if (rc) { /* if check_entry_for_referral returns non-zero, result is sent. */
                     *rc = FE_RC_SENT_RESULT;
                 }
+                slapi_set_ldap_result(pb, LDAP_REFERRAL, NULL, NULL, 0, NULL);
                 return (NULL);
             }
             /* else fall through to no such object */
@@ -189,7 +197,7 @@ find_entry_internal_dn(
             if (me && !isroot) {
                 /* If not root, you may not want to reveal it. */
                 int acl_type = -1;
-                int return_err = LDAP_NO_SUCH_OBJECT;
+                return_err = LDAP_NO_SUCH_OBJECT;
                 err = LDAP_SUCCESS;
                 switch (op_type) {
                 case SLAPI_OPERATION_ADD:
@@ -230,18 +238,22 @@ find_entry_internal_dn(
                      * do not return the "matched" DN.
                      * Plus, the bind case returns LDAP_INAPPROPRIATE_AUTH.
                      */
+                    slapi_set_ldap_result(pb, return_err, NULL, NULL, 0, NULL);
                     slapi_send_ldap_result(pb, return_err, NULL, NULL, 0, NULL);
                 } else {
+                slapi_set_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
                     slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT,
                                            (char *)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
                 }
             } else {
+                slapi_set_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
                 slapi_send_ldap_result(pb, LDAP_NO_SUCH_OBJECT,
                                        (char *)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
             }
         } else {
-            slapi_send_ldap_result(pb, (LDAP_INVALID_DN_SYNTAX == err) ? LDAP_INVALID_DN_SYNTAX : LDAP_OPERATIONS_ERROR,
-                                   (char *)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
+            return_err = (LDAP_INVALID_DN_SYNTAX == err) ? LDAP_INVALID_DN_SYNTAX : LDAP_OPERATIONS_ERROR;
+            slapi_set_ldap_result(pb, return_err, NULL, NULL, 0, NULL);
+            slapi_send_ldap_result(pb, return_err, (char *)slapi_sdn_get_dn(&ancestorsdn), NULL, 0, NULL);
         }
         if (rc) {
             *rc = FE_RC_SENT_RESULT;
@@ -265,13 +277,15 @@ find_entry_internal_uniqueid(
     backend *be,
     const char *uniqueid,
     int lock,
-    back_txn *txn)
+    back_txn *txn,
+    int *rc)
 {
     ldbm_instance *inst = (ldbm_instance *)be->be_instance_info;
     struct backentry *e;
     int err;
     size_t tries = 0;
     int reverted_entry = 0;
+    int return_err = 0;
 
     while ((tries < LDBM_CACHE_RETRY_COUNT) &&
            (e = uniqueid2entry(be, uniqueid, txn, &err)) != NULL) {
@@ -307,12 +321,20 @@ find_entry_internal_uniqueid(
     }
 
     if (reverted_entry) {
+        slapi_set_ldap_result(pb, LDAP_BUSY, NULL, NULL, 0, NULL);
         slapi_send_ldap_result(pb, LDAP_BUSY, NULL, "target entry busy because of a canceled operation", 0, NULL);
+        if (rc) {
+            *rc = FE_RC_SENT_RESULT;  /* Result is sent */
+        }
         return (NULL);
     } else {
         /* entry not found */
-        slapi_send_ldap_result(pb, (0 == err || DBI_RC_NOTFOUND == err) ? LDAP_NO_SUCH_OBJECT : LDAP_OPERATIONS_ERROR, NULL /* matched */, NULL,
-                               0, NULL);
+        return_err = (0 == err || DBI_RC_NOTFOUND == err) ? LDAP_NO_SUCH_OBJECT : LDAP_OPERATIONS_ERROR;
+        slapi_set_ldap_result(pb, return_err, NULL, NULL, 0, NULL);
+        slapi_send_ldap_result(pb, return_err, NULL /* matched */, NULL, 0, NULL);
+        if (rc) {
+            *rc = FE_RC_SENT_RESULT;  /* Result is sent */
+        }
     }
     slapi_log_err(SLAPI_LOG_TRACE,
                   "find_entry_internal_uniqueid", "<= not found; uniqueid = (%s)\n",
@@ -334,7 +356,7 @@ find_entry_internal(
     if (addr->uniqueid != NULL) {
         slapi_log_err(SLAPI_LOG_TRACE, "find_entry_internal", "=> (uniqueid=%s) lock %d\n",
                       addr->uniqueid, lock);
-        return (find_entry_internal_uniqueid(pb, be, addr->uniqueid, lock, txn));
+        return (find_entry_internal_uniqueid(pb, be, addr->uniqueid, lock, txn, rc));
     } else {
         struct backentry *entry = NULL;
 
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 067e19f0c6..39f49f8230 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -435,6 +435,8 @@ ldbm_back_add(Slapi_PBlock *pb)
                     slapi_log_err(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
                                   "find_entry2modify_only returned NULL parententry pdn: %s, uniqueid: %s\n",
                                   slapi_sdn_get_dn(&parentsdn), addr.uniqueid ? addr.uniqueid : "none");
+                    slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+                    goto error_return;
                 }
                 modify_init(&parent_modify_c, parententry);
             }
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 29df2ce75d..24c62a9524 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -177,6 +177,12 @@ modify_update_all(backend *be, Slapi_PBlock *pb, modify_context *mc, back_txn *t
         slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
         is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
     }
+    if (NULL == mc->new_entry) {
+        /* test entry to avoid crashing in id2entry_add_ext */
+        slapi_log_err(SLAPI_LOG_BACKLDBM, "modify_update_all",
+                      "No entry in modify_context ==> operation is aborted.\n");
+        return -1;
+    }
     /*
      * Update the ID to Entry index.
      * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index a024ca02ef..32542e110c 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -485,8 +485,8 @@ ldbm_back_modrdn(Slapi_PBlock *pb)
             slapi_pblock_get(pb, SLAPI_TARGET_ADDRESS, &old_addr);
             e = find_entry2modify(pb, be, old_addr, &txn, &result_sent);
             if (e == NULL) {
-                ldap_result_code = -1;
-                goto error_return; /* error result sent by find_entry2modify() */
+                slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+                goto error_return; /* error result set and sent by find_entry2modify() */
             }
             if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) &&
                 !is_resurect_operation) {
@@ -518,6 +518,11 @@ ldbm_back_modrdn(Slapi_PBlock *pb)
                 oldparent_addr.uniqueid = NULL;
             }
             parententry = find_entry2modify_only(pb, be, &oldparent_addr, &txn, &result_sent);
+            if (parententry == NULL) {
+                slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+                goto error_return; /* error result set and sent by find_entry2modify() */
+            }
+
             modify_init(&parent_modify_context, parententry);
 
             /* Fetch and lock the new parent of the entry that is moving */
@@ -528,6 +533,10 @@ ldbm_back_modrdn(Slapi_PBlock *pb)
                 }
                 newparententry = find_entry2modify_only(pb, be, newsuperior_addr, &txn, &result_sent);
                 slapi_ch_free_string(&newsuperior_addr->uniqueid);
+                if (newparententry == NULL) {
+                    slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
+                    goto error_return; /* error result set and sent by find_entry2modify() */
+                }
                 modify_init(&newparent_modify_context, newparententry);
             }