summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarolin Seeger <kseeger@samba.org>2021-04-29 11:12:26 +0200
committerKarolin Seeger <kseeger@samba.org>2021-04-29 11:12:26 +0200
commit5ab7bbd30bd8cdd4510c07b37577f6c4d78ee187 (patch)
treec7fe64e93264066f63f34321d4076ae169ef36d9
parentdeb7b32b4372625211a4d6ba26e3d00223e903ca (diff)
parent703c6301013f78e80882abfe8375d6a45a176b7f (diff)
downloadsamba-5ab7bbd30bd8cdd4510c07b37577f6c4d78ee187.tar.gz
Merge tag 'samba-4.12.15' into v4-12-test
samba: tag release samba-4.12.15
-rw-r--r--WHATSNEW.txt68
-rw-r--r--source3/passdb/lookup_sid.c140
2 files changed, 184 insertions, 24 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index f3c64a7050c..d77b074f2a7 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,4 +1,69 @@
===============================
+ Release Notes for Samba 4.12.15
+ April 29, 2021
+ ===============================
+
+
+This is a security release in order to address the following defect:
+
+o CVE-2021-20254: Negative idmap cache entries can cause incorrect group entries
+ in the Samba file server process token.
+
+
+=======
+Details
+=======
+
+o CVE-2021-20254:
+ The Samba smbd file server must map Windows group identities (SIDs) into unix
+ group ids (gids). The code that performs this had a flaw that could allow it
+ to read data beyond the end of the array in the case where a negative cache
+ entry had been added to the mapping cache. This could cause the calling code
+ to return those values into the process token that stores the group
+ membership for a user.
+
+ Most commonly this flaw caused the calling code to crash, but an alert user
+ (Peter Eriksson, IT Department, Linköping University) found this flaw by
+ noticing an unprivileged user was able to delete a file within a network
+ share that they should have been disallowed access to.
+
+ Analysis of the code paths has not allowed us to discover a way for a
+ remote user to be able to trigger this flaw reproducibly or on demand,
+ but this CVE has been issued out of an abundance of caution.
+
+
+Changes since 4.12.14
+---------------------
+
+o Volker Lendecke <vl@samba.org>
+ * BUG 14571: CVE-2021-20254: Fix buffer overrun in sids_to_unixids().
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored. All bug reports should
+be filed under the Samba 4.1 and newer product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
+
+ ===============================
Release Notes for Samba 4.12.14
March 24, 2021
===============================
@@ -55,8 +120,7 @@ database (https://bugzilla.samba.org/).
======================================================================
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
===============================
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 82c47b3145b..6887b6ebb62 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -29,6 +29,7 @@
#include "../libcli/security/security.h"
#include "lib/winbind_util.h"
#include "../librpc/gen_ndr/idmap.h"
+#include "lib/util/bitmap.h"
static bool lookup_unix_user_name(const char *name, struct dom_sid *sid)
{
@@ -1247,7 +1248,9 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
{
struct wbcDomainSid *wbc_sids = NULL;
struct wbcUnixId *wbc_ids = NULL;
+ struct bitmap *found = NULL;
uint32_t i, num_not_cached;
+ uint32_t wbc_ids_size = 0;
wbcErr err;
bool ret = false;
@@ -1255,6 +1258,20 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
if (wbc_sids == NULL) {
return false;
}
+ found = bitmap_talloc(wbc_sids, num_sids);
+ if (found == NULL) {
+ goto fail;
+ }
+
+ /*
+ * We go through the requested SID array three times.
+ * First time to look for global_sid_Unix_Users
+ * and global_sid_Unix_Groups SIDS, and to look
+ * for mappings cached in the idmap_cache.
+ *
+ * Use bitmap_set() to mark an ids[] array entry as
+ * being mapped.
+ */
num_not_cached = 0;
@@ -1266,17 +1283,20 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
&sids[i], &rid)) {
ids[i].type = ID_TYPE_UID;
ids[i].id = rid;
+ bitmap_set(found, i);
continue;
}
if (sid_peek_check_rid(&global_sid_Unix_Groups,
&sids[i], &rid)) {
ids[i].type = ID_TYPE_GID;
ids[i].id = rid;
+ bitmap_set(found, i);
continue;
}
if (idmap_cache_find_sid2unixid(&sids[i], &ids[i], &expired)
&& !expired)
{
+ bitmap_set(found, i);
continue;
}
ids[i].type = ID_TYPE_NOT_SPECIFIED;
@@ -1287,62 +1307,138 @@ bool sids_to_unixids(const struct dom_sid *sids, uint32_t num_sids,
if (num_not_cached == 0) {
goto done;
}
- wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached);
+
+ /*
+ * For the ones that we couldn't map in the loop above, query winbindd
+ * via wbcSidsToUnixIds().
+ */
+
+ wbc_ids_size = num_not_cached;
+ wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, wbc_ids_size);
if (wbc_ids == NULL) {
goto fail;
}
- for (i=0; i<num_not_cached; i++) {
+ for (i=0; i<wbc_ids_size; i++) {
wbc_ids[i].type = WBC_ID_TYPE_NOT_SPECIFIED;
}
- err = wbcSidsToUnixIds(wbc_sids, num_not_cached, wbc_ids);
+ /*
+ * gcc versions at least 5.x -> 6.x have a bug
+ * with initializing the wbc_ids[i].type and
+ * wbc_ids[i].id.gid to (uint32_t)-1 in the
+ * same loop when using [-Werror=strict-overflow].
+ * The error is:
+ *
+ * ../../source3/passdb/lookup_sid.c:1246:6: error: assuming
+ * pointer wraparound does not occur when comparing P +- C1
+ * with P +- C2 [-Werror=strict-overflow]
+ *
+ * Doing this loop twice fixes the compiler error.
+ * As wbc_ids_size isn't large this isn't too much
+ * of a performance burden.
+ */
+ for (i=0; i<wbc_ids_size; i++) {
+ wbc_ids[i].id.gid = (uint32_t)-1;
+ }
+ err = wbcSidsToUnixIds(wbc_sids, wbc_ids_size, wbc_ids);
if (!WBC_ERROR_IS_OK(err)) {
DEBUG(10, ("wbcSidsToUnixIds returned %s\n",
wbcErrorString(err)));
}
+ /*
+ * Second time through the SID array, replace
+ * the ids[] entries that wbcSidsToUnixIds() was able to
+ * map.
+ *
+ * Use bitmap_set() to mark an ids[] array entry as
+ * being mapped.
+ */
+
num_not_cached = 0;
for (i=0; i<num_sids; i++) {
- if (ids[i].type == ID_TYPE_NOT_SPECIFIED) {
- switch (wbc_ids[num_not_cached].type) {
- case WBC_ID_TYPE_UID:
- ids[i].type = ID_TYPE_UID;
- ids[i].id = wbc_ids[num_not_cached].id.uid;
- break;
- case WBC_ID_TYPE_GID:
- ids[i].type = ID_TYPE_GID;
- ids[i].id = wbc_ids[num_not_cached].id.gid;
- break;
- default:
- /* The types match, and wbcUnixId -> id is a union anyway */
- ids[i].type = (enum id_type)wbc_ids[num_not_cached].type;
- ids[i].id = wbc_ids[num_not_cached].id.gid;
- break;
- }
- num_not_cached += 1;
+ if (bitmap_query(found, i)) {
+ continue;
}
+
+ SMB_ASSERT(num_not_cached < wbc_ids_size);
+
+ switch (wbc_ids[num_not_cached].type) {
+ case WBC_ID_TYPE_UID:
+ ids[i].type = ID_TYPE_UID;
+ ids[i].id = wbc_ids[num_not_cached].id.uid;
+ bitmap_set(found, i);
+ break;
+ case WBC_ID_TYPE_GID:
+ ids[i].type = ID_TYPE_GID;
+ ids[i].id = wbc_ids[num_not_cached].id.gid;
+ bitmap_set(found, i);
+ break;
+ case WBC_ID_TYPE_BOTH:
+ ids[i].type = ID_TYPE_BOTH;
+ ids[i].id = wbc_ids[num_not_cached].id.uid;
+ bitmap_set(found, i);
+ break;
+ case WBC_ID_TYPE_NOT_SPECIFIED:
+ /*
+ * wbcSidsToUnixIds() wasn't able to map this
+ * so we still need to check legacy_sid_to_XXX()
+ * below. Don't mark the bitmap entry
+ * as being found so the final loop knows
+ * to try and map this entry.
+ */
+ ids[i].type = ID_TYPE_NOT_SPECIFIED;
+ ids[i].id = (uint32_t)-1;
+ break;
+ default:
+ /*
+ * A successful return from wbcSidsToUnixIds()
+ * cannot return anything other than the values
+ * checked for above. Ensure this is so.
+ */
+ smb_panic(__location__);
+ break;
+ }
+ num_not_cached += 1;
}
+ /*
+ * Third and final time through the SID array,
+ * try legacy_sid_to_gid()/legacy_sid_to_uid()
+ * for entries we haven't already been able to
+ * map.
+ *
+ * Use bitmap_set() to mark an ids[] array entry as
+ * being mapped.
+ */
+
for (i=0; i<num_sids; i++) {
- if (ids[i].type != ID_TYPE_NOT_SPECIFIED) {
+ if (bitmap_query(found, i)) {
continue;
}
if (legacy_sid_to_gid(&sids[i], &ids[i].id)) {
ids[i].type = ID_TYPE_GID;
+ bitmap_set(found, i);
continue;
}
if (legacy_sid_to_uid(&sids[i], &ids[i].id)) {
ids[i].type = ID_TYPE_UID;
+ bitmap_set(found, i);
continue;
}
}
done:
+ /*
+ * Pass through the return array for consistency.
+ * Any ids[].id mapped to (uint32_t)-1 must be returned
+ * as ID_TYPE_NOT_SPECIFIED.
+ */
for (i=0; i<num_sids; i++) {
switch(ids[i].type) {
case WBC_ID_TYPE_GID:
case WBC_ID_TYPE_UID:
case WBC_ID_TYPE_BOTH:
- if (ids[i].id == -1) {
+ if (ids[i].id == (uint32_t)-1) {
ids[i].type = ID_TYPE_NOT_SPECIFIED;
}
break;