!50 backport to fix fuzz error

From: @eaglegai
Reviewed-by: @zengwefeng
Signed-off-by: @zengwefeng
This commit is contained in:
openeuler-ci-bot 2021-10-30 06:54:14 +00:00 committed by Gitee
commit ad11e732db
12 changed files with 1300 additions and 1 deletions

View File

@ -0,0 +1,35 @@
From 2f8c3b62266b729b47d5ba25f1966786c1af0e5f Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Thu, 30 Jan 2020 08:52:34 +1300
Subject: [PATCH] idl: drsuapi_DsaAddressListItem_V1 limit recursion
Limit number of drsuapi_DsaAddressListItem_V1 elements to 1024
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19820
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14254
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
librpc/idl/drsuapi.idl | 2 +-
1 files changed, 1 insertion(+), 1 deletions(-)
delete mode 100644 selftest/knownfail.d/bug-14254
diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl
index 2aaae8dce59..04725276121 100644
--- a/librpc/idl/drsuapi.idl
+++ b/librpc/idl/drsuapi.idl
@@ -1452,7 +1452,7 @@ interface drsuapi
/* list of network names of the DCs
* to which the referral is directed */
typedef struct {
- drsuapi_DsaAddressListItem_V1 *next;
+ [max_recursion(1024)] drsuapi_DsaAddressListItem_V1 *next;
lsa_String *address;
} drsuapi_DsaAddressListItem_V1;
--
GitLab

View File

@ -0,0 +1,126 @@
From 575d39048e3b4f619d65d65303ac809c40c5d495 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Fri, 7 Feb 2020 15:18:45 +1300
Subject: [PATCH] idl: limit recurion on recursive elements
Limit the max_recursion on self recursive definitions in the idl to
20,000. This value is hopefully large eneough to not impact normal
operation, but small eneough to prevent stack over flow issues.
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19820
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14254
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Thu Feb 27 02:29:21 UTC 2020 on sn-devel-184
---
librpc/idl/drsblobs.idl | 2 +-
librpc/idl/drsuapi.idl | 12 ++++++++----
librpc/idl/ioctl.idl | 2 +-
source3/librpc/idl/secrets.idl | 2 +-
source3/librpc/idl/smbXsrv.idl | 2 +-
5 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/librpc/idl/drsblobs.idl b/librpc/idl/drsblobs.idl
index 072546a4369..b096b671c80 100644
--- a/librpc/idl/drsblobs.idl
+++ b/librpc/idl/drsblobs.idl
@@ -579,7 +579,7 @@ interface drsblobs {
} ExtendedErrorParam;
typedef [public] struct {
- ExtendedErrorInfo *next;
+ [max_recursion(20000)] ExtendedErrorInfo *next;
ExtendedErrorComputerName computer_name;
hyper pid;
NTTIME time;
diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl
index 04725276121..db00eb8639e 100644
--- a/librpc/idl/drsuapi.idl
+++ b/librpc/idl/drsuapi.idl
@@ -690,7 +690,8 @@ interface drsuapi
} drsuapi_DsReplicaMetaDataCtr;
typedef [public,noprint] struct {
- drsuapi_DsReplicaObjectListItemEx *next_object;
+ [max_recursion(20000)]
+ drsuapi_DsReplicaObjectListItemEx *next_object;
drsuapi_DsReplicaObject object;
boolean32 is_nc_prefix;
GUID *parent_object_guid;
@@ -1308,7 +1309,8 @@ interface drsuapi
/*****************/
/* Function 0x11 */
typedef [public,noprint] struct {
- drsuapi_DsReplicaObjectListItem *next_object;
+ [max_recursion(20000)]
+ drsuapi_DsReplicaObjectListItem *next_object;
drsuapi_DsReplicaObject object;
} drsuapi_DsReplicaObjectListItem;
@@ -1408,7 +1410,8 @@ interface drsuapi
} drsuapi_DsAddEntry_AttrErr_V1;
typedef [noprint] struct {
- drsuapi_DsAddEntry_AttrErrListItem_V1 *next;
+ [max_recursion(20000)]
+ drsuapi_DsAddEntry_AttrErrListItem_V1 *next;
drsuapi_DsAddEntry_AttrErr_V1 err_data;
} drsuapi_DsAddEntry_AttrErrListItem_V1;
@@ -1464,7 +1467,8 @@ interface drsuapi
drsuapi_DsAddEntry_RefType ref_type;
uint16 addr_list_count;
drsuapi_DsaAddressListItem_V1 *addr_list;
- drsuapi_DsAddEntry_RefErrListItem_V1 *next;
+ [max_recursion(20000)]
+ drsuapi_DsAddEntry_RefErrListItem_V1 *next;
boolean32 is_choice_set;
drsuapi_DsAddEntry_ChoiceType choice;
} drsuapi_DsAddEntry_RefErrListItem_V1;
diff --git a/librpc/idl/ioctl.idl b/librpc/idl/ioctl.idl
index ba68fbcb8f6..390e8562f69 100644
--- a/librpc/idl/ioctl.idl
+++ b/librpc/idl/ioctl.idl
@@ -151,7 +151,7 @@ interface netinterface
} fsctl_sockaddr_storage;
typedef [public,relative_base,noprint] struct {
- [relative] fsctl_net_iface_info *next;
+ [relative,max_recursion(20000)] fsctl_net_iface_info *next;
uint32 ifindex;
fsctl_net_iface_capability capability;
[value(0)] uint32 reserved;
diff --git a/source3/librpc/idl/secrets.idl b/source3/librpc/idl/secrets.idl
index 2c06fa6990d..186d925e45e 100644
--- a/source3/librpc/idl/secrets.idl
+++ b/source3/librpc/idl/secrets.idl
@@ -100,7 +100,7 @@ import "misc.idl", "samr.idl", "lsa.idl", "netlogon.idl", "security.idl";
NTTIME password_last_change;
hyper password_changes;
- secrets_domain_info1_change *next_change;
+ [max_recursion(20000)] secrets_domain_info1_change *next_change;
[ref] secrets_domain_info1_password *password;
secrets_domain_info1_password *old_password;
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index c6ce9c48789..4d9249fb3bb 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -267,7 +267,7 @@ interface smbXsrv
typedef struct {
[ignore] smbXsrv_session_auth0 *prev;
- smbXsrv_session_auth0 *next;
+ [max_recursion(20000)] smbXsrv_session_auth0 *next;
[ignore] smbXsrv_session *session;
[ignore] smbXsrv_connection *connection;
[ignore] gensec_security *gensec;
--
GitLab

View File

@ -0,0 +1,300 @@
From a699256f438527455aaff6c73c88ee87ac7083ef Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Tue, 21 Apr 2020 15:37:40 +1200
Subject: [PATCH] lib ldb: Limit depth of ldb_parse_tree
Limit the number of nested conditionals allowed by ldb_parse tree to
128, to avoid potential stack overflow issues.
Credit Oss-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19508
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Gary Lockyer <gary@samba.org>
Autobuild-Date(master): Sun May 10 23:21:08 UTC 2020 on sn-devel-184
---
lib/ldb/common/ldb_parse.c | 72 +++++++++++++++++++++++------
lib/ldb/tests/ldb_parse_test.c | 83 +++++++++++++++++++++++++++++++++-
2 files changed, 140 insertions(+), 15 deletions(-)
diff --git a/lib/ldb/common/ldb_parse.c b/lib/ldb/common/ldb_parse.c
index 452c5830ed5..7e15206b168 100644
--- a/lib/ldb/common/ldb_parse.c
+++ b/lib/ldb/common/ldb_parse.c
@@ -43,6 +43,16 @@
#include "ldb_private.h"
#include "system/locale.h"
+/*
+ * Maximum depth of the filter parse tree, the value chosen is small enough to
+ * avoid triggering ASAN stack overflow checks. But large enough to be useful.
+ *
+ * On Windows clients the maximum number of levels of recursion allowed is 100.
+ * In the LDAP server, Windows restricts clients to 512 nested
+ * (eg) OR statements.
+ */
+#define LDB_MAX_PARSE_TREE_DEPTH 128
+
static int ldb_parse_hex2char(const char *x)
{
if (isxdigit(x[0]) && isxdigit(x[1])) {
@@ -231,7 +241,11 @@ static struct ldb_val **ldb_wildcard_decode(TALLOC_CTX *mem_ctx, const char *str
return ret;
}
-static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s);
+static struct ldb_parse_tree *ldb_parse_filter(
+ TALLOC_CTX *mem_ctx,
+ const char **s,
+ unsigned depth,
+ unsigned max_depth);
/*
@@ -498,7 +512,11 @@ static struct ldb_parse_tree *ldb_parse_simple(TALLOC_CTX *mem_ctx, const char *
<or> ::= '|' <filterlist>
<filterlist> ::= <filter> | <filter> <filterlist>
*/
-static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const char **s)
+static struct ldb_parse_tree *ldb_parse_filterlist(
+ TALLOC_CTX *mem_ctx,
+ const char **s,
+ unsigned depth,
+ unsigned max_depth)
{
struct ldb_parse_tree *ret, *next;
enum ldb_parse_op op;
@@ -533,7 +551,8 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch
return NULL;
}
- ret->u.list.elements[0] = ldb_parse_filter(ret->u.list.elements, &p);
+ ret->u.list.elements[0] =
+ ldb_parse_filter(ret->u.list.elements, &p, depth, max_depth);
if (!ret->u.list.elements[0]) {
talloc_free(ret);
return NULL;
@@ -547,7 +566,8 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch
break;
}
- next = ldb_parse_filter(ret->u.list.elements, &p);
+ next = ldb_parse_filter(
+ ret->u.list.elements, &p, depth, max_depth);
if (next == NULL) {
/* an invalid filter element */
talloc_free(ret);
@@ -576,7 +596,11 @@ static struct ldb_parse_tree *ldb_parse_filterlist(TALLOC_CTX *mem_ctx, const ch
/*
<not> ::= '!' <filter>
*/
-static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s)
+static struct ldb_parse_tree *ldb_parse_not(
+ TALLOC_CTX *mem_ctx,
+ const char **s,
+ unsigned depth,
+ unsigned max_depth)
{
struct ldb_parse_tree *ret;
const char *p = *s;
@@ -593,7 +617,7 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s)
}
ret->operation = LDB_OP_NOT;
- ret->u.isnot.child = ldb_parse_filter(ret, &p);
+ ret->u.isnot.child = ldb_parse_filter(ret, &p, depth, max_depth);
if (!ret->u.isnot.child) {
talloc_free(ret);
return NULL;
@@ -608,7 +632,11 @@ static struct ldb_parse_tree *ldb_parse_not(TALLOC_CTX *mem_ctx, const char **s)
parse a filtercomp
<filtercomp> ::= <and> | <or> | <not> | <simple>
*/
-static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const char **s)
+static struct ldb_parse_tree *ldb_parse_filtercomp(
+ TALLOC_CTX *mem_ctx,
+ const char **s,
+ unsigned depth,
+ unsigned max_depth)
{
struct ldb_parse_tree *ret;
const char *p = *s;
@@ -617,15 +645,15 @@ static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const ch
switch (*p) {
case '&':
- ret = ldb_parse_filterlist(mem_ctx, &p);
+ ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
break;
case '|':
- ret = ldb_parse_filterlist(mem_ctx, &p);
+ ret = ldb_parse_filterlist(mem_ctx, &p, depth, max_depth);
break;
case '!':
- ret = ldb_parse_not(mem_ctx, &p);
+ ret = ldb_parse_not(mem_ctx, &p, depth, max_depth);
break;
case '(':
@@ -641,21 +669,34 @@ static struct ldb_parse_tree *ldb_parse_filtercomp(TALLOC_CTX *mem_ctx, const ch
return ret;
}
-
/*
<filter> ::= '(' <filtercomp> ')'
*/
-static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char **s)
+static struct ldb_parse_tree *ldb_parse_filter(
+ TALLOC_CTX *mem_ctx,
+ const char **s,
+ unsigned depth,
+ unsigned max_depth)
{
struct ldb_parse_tree *ret;
const char *p = *s;
+ /*
+ * Check the depth of the parse tree, and reject the input if
+ * max_depth exceeded. This avoids stack overflow
+ * issues.
+ */
+ if (depth > max_depth) {
+ return NULL;
+ }
+ depth++;
+
if (*p != '(') {
return NULL;
}
p++;
- ret = ldb_parse_filtercomp(mem_ctx, &p);
+ ret = ldb_parse_filtercomp(mem_ctx, &p, depth, max_depth);
if (*p != ')') {
return NULL;
@@ -679,6 +720,8 @@ static struct ldb_parse_tree *ldb_parse_filter(TALLOC_CTX *mem_ctx, const char *
*/
struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
{
+ unsigned depth = 0;
+
while (s && isspace((unsigned char)*s)) s++;
if (s == NULL || *s == 0) {
@@ -686,7 +729,8 @@ struct ldb_parse_tree *ldb_parse_tree(TALLOC_CTX *mem_ctx, const char *s)
}
if (*s == '(') {
- return ldb_parse_filter(mem_ctx, &s);
+ return ldb_parse_filter(
+ mem_ctx, &s, depth, LDB_MAX_PARSE_TREE_DEPTH);
}
return ldb_parse_simple(mem_ctx, &s);
diff --git a/lib/ldb/tests/ldb_parse_test.c b/lib/ldb/tests/ldb_parse_test.c
index a739d7795d1..d7442b954ea 100644
--- a/lib/ldb/tests/ldb_parse_test.c
+++ b/lib/ldb/tests/ldb_parse_test.c
@@ -81,10 +81,91 @@ static void test_parse_filtertype(void **state)
test_roundtrip(ctx, " ", "(|(objectClass=*)(distinguishedName=*))");
}
+/*
+ * Test that a nested query with 128 levels of nesting is accepted
+ */
+static void test_nested_filter_eq_limit(void **state)
+{
+ struct test_ctx *ctx =
+ talloc_get_type_abort(*state, struct test_ctx);
+
+ /*
+ * 128 nested clauses
+ */
+ const char *nested_query = ""
+ "(|(!(|(&(|(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(&(|(|(|(|(|(|(!(|(!(|(|(|"
+ "(|(!(|(&(|(|(&(|(|(|(|(|(!(!(!(|"
+ "(|(!(|(&(|(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(&(|(|(|(!(|(|(&(|(|(|(|(|"
+ "(|(!(|(&(|(|(&(|(|(|(|(|(&(&(|(|"
+ "(|(!(|(&(|(|(|(|(|(|(!(|(|(|(|(|"
+ "(|(!(|(&(|(|(!(|(|(|(|(|(|(|(|(|"
+ "(a=b)"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))";
+
+ struct ldb_parse_tree *tree = ldb_parse_tree(ctx, nested_query);
+
+ assert_non_null(tree);
+ /*
+ * Check that we get the same query back
+ */
+ test_roundtrip(ctx, nested_query, nested_query);
+}
+
+/*
+ * Test that a nested query with 129 levels of nesting is rejected.
+ */
+static void test_nested_filter_gt_limit(void **state)
+{
+ struct test_ctx *ctx =
+ talloc_get_type_abort(*state, struct test_ctx);
+
+ /*
+ * 129 nested clauses
+ */
+ const char *nested_query = ""
+ "(|(!(|(|(&(|(|(|(|(&(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(!(|(|(|(|(!(|(|(|"
+ "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(|(!(&(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(|(|(|(|(|(|(|(|(|"
+ "(|(!(|(|(&(|(|(|(|(|(|(|(|(&(|(|"
+ "(|"
+ "(a=b)"
+ ")"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))"
+ "))))))))))))))))";
+
+ struct ldb_parse_tree *tree = ldb_parse_tree(ctx, nested_query);
+
+ assert_null(tree);
+}
+
int main(int argc, const char **argv)
{
const struct CMUnitTest tests[] = {
- cmocka_unit_test_setup_teardown(test_parse_filtertype, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_parse_filtertype, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_nested_filter_eq_limit, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_nested_filter_gt_limit, setup, teardown),
};
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
--
GitLab

View File

@ -0,0 +1,208 @@
From ae6927e4f08dcea89729d8e54363e98effab6624 Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Fri, 24 Jan 2020 10:41:35 +1300
Subject: [PATCH] librpc ndr: Heap-buffer-overflow in lzxpress_decompress
Reproducer for oss-fuzz Issue 20083
Project: samba
Fuzzing Engine: libFuzzer
Fuzz Target: fuzz_ndr_drsuapi_TYPE_OUT
Job Type: libfuzzer_asan_samba
Platform Id: linux
Crash Type: Heap-buffer-overflow READ 1
Crash Address: 0x6040000002fd
Crash State:
lzxpress_decompress
ndr_pull_compression_xpress_chunk
ndr_pull_compression_start
Sanitizer: address (ASAN)
Recommended Security Severity: Medium
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20083
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14236
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
librpc/ndr/libndr.h | 5 +-
librpc/tests/test_ndr.c | 84 ++++++++++++++++++++++++++
librpc/wscript_build | 8 +++
python/samba/tests/blackbox/ndrdump.py | 13 ++++
selftest/knownfail.d/bug-14236 | 1 +
source4/selftest/tests.py | 2 +
6 files changed, 112 insertions(+), 1 deletion(-)
create mode 100644 librpc/tests/test_ndr.c
create mode 100644 selftest/knownfail.d/bug-14236
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 58ef517d363..b7cccf3dfc5 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -309,7 +309,10 @@ enum ndr_compression_alg {
} while (0)
#define NDR_PULL_NEED_BYTES(ndr, n) do { \
- if (unlikely((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size)) { \
+ if (unlikely(\
+ (n) > ndr->data_size || \
+ ndr->offset + (n) > ndr->data_size || \
+ ndr->offset + (n) < ndr->offset)) { \
if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) { \
uint32_t _available = ndr->data_size - ndr->offset; \
uint32_t _missing = n - _available; \
diff --git a/librpc/tests/test_ndr.c b/librpc/tests/test_ndr.c
new file mode 100644
index 00000000000..1c074d71023
--- /dev/null
+++ b/librpc/tests/test_ndr.c
@@ -0,0 +1,84 @@
+/*
+ * Tests for librpc ndr functions
+ *
+ * Copyright (C) Catalyst.NET Ltd 2020
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "librpc/ndr/libndr.h"
+
+/*
+ * Test NDR_PULL_NEED_BYTES integer overflow handling.
+ */
+static enum ndr_err_code wrap_NDR_PULL_NEED_BYTES(
+ struct ndr_pull *ndr,
+ uint32_t bytes) {
+
+ NDR_PULL_NEED_BYTES(ndr, bytes);
+ return NDR_ERR_SUCCESS;
+}
+
+static void test_NDR_PULL_NEED_BYTES(void **state)
+{
+ struct ndr_pull ndr = {0};
+ enum ndr_err_code err;
+
+ ndr.data_size = UINT32_MAX;
+ ndr.offset = UINT32_MAX -1;
+
+ /*
+ * This will not cause an overflow
+ */
+ err = wrap_NDR_PULL_NEED_BYTES(&ndr, 1);
+ assert_int_equal(NDR_ERR_SUCCESS, err);
+
+ /*
+ * This will cause an overflow
+ * and (offset + n) will be less than data_size
+ */
+ err = wrap_NDR_PULL_NEED_BYTES(&ndr, 2);
+ assert_int_equal(NDR_ERR_BUFSIZE, err);
+}
+
+int main(int argc, const char **argv)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_NDR_PULL_NEED_BYTES),
+ };
+
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/librpc/wscript_build b/librpc/wscript_build
index 5eb78e6010a8..ec8697fbcc58 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -698,3 +698,11 @@ bld.SAMBA_BINARY('test_ndr_string',
ndr_nbt
''',
for_selftest=True)
+
+bld.SAMBA_BINARY('test_ndr',
+ source='tests/test_ndr.c',
+ deps='''
+ cmocka
+ ndr
+ ''',
+ for_selftest=True)
diff --git a/python/samba/tests/blackbox/ndrdump.py b/python/samba/tests/blackbox/ndrdump.py
index b3c837819b15..205519c3f8a6 100644
--- a/python/samba/tests/blackbox/ndrdump.py
+++ b/python/samba/tests/blackbox/ndrdump.py
@@ -437,3 +437,16 @@ def test_fuzzed_drsuapi_DsGetNCChanges(self):
except BlackboxProcessError as e:
self.fail(e)
self.assertEqual(actual, expected)
+
+ def test_ndrdump_fuzzed_ndr_compression(self):
+ expected = 'pull returned Buffer Size Error'
+ command = (
+ "ndrdump drsuapi 3 out --base64-input "
+ "--input BwAAAAcAAAAGAAAAAwAgICAgICAJAAAAICAgIAkAAAAgIAAA//////8=")
+ try:
+ actual = self.check_exit_code(command, 2)
+ except BlackboxProcessError as e:
+ self.fail(e)
+ # check_output will return bytes
+ # convert expected to bytes for python 3
+ self.assertRegex(actual.decode('utf8'), expected + '$')
diff --git a/selftest/knownfail.d/bug-14236 b/selftest/knownfail.d/bug-14236
new file mode 100644
index 00000000000..64b956997a6
--- /dev/null
+++ b/selftest/knownfail.d/bug-14236
@@ -0,0 +1 @@
+^samba.tests.blackbox.ndrdump.samba.tests.blackbox.ndrdump.NdrDumpTests.test_ndrdump_fuzzed_ndr_compression
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index f570d35dfba..ab2c4f69da0 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -1334,6 +1334,8 @@ plantestsuite("libcli.drsuapi.repl_decrypt", "none",
[os.path.join(bindir(), "test_ldap_message")])
plantestsuite("librpc.ndr.ndr_macros", "none",
[os.path.join(bindir(), "test_ndr_macros")])
+plantestsuite("librpc.ndr.ndr", "none",
+ [os.path.join(bindir(), "test_ndr")])
# process restart and limit tests, these break the environment so need to run
# in their own specific environment
--
GitLab

View File

@ -0,0 +1,40 @@
From 6d05fb3ea772c3642624ec6e0fb4e8d099bcdb8e Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Wed, 22 Jan 2020 14:16:02 +1300
Subject: [PATCH] librpc ndr: NDR_PULL_ALIGN check for unsigned overflow
Handle uint32 overflow in NDR_PULL_ALIGN
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20083
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14236
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
librpc/ndr/libndr.h | 7 +++++++
selftest/knownfail.d/bug-14236 | 1 -
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index b7cccf3dfc5..c2c7e263049 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -331,6 +331,13 @@ enum ndr_compression_alg {
if (unlikely(ndr->flags & LIBNDR_FLAG_PAD_CHECK)) { \
ndr_check_padding(ndr, n); \
} \
+ if(unlikely( \
+ ((ndr->offset + (n-1)) & (~(n-1))) < ndr->offset)) {\
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_BUFSIZE, \
+ "Pull align (overflow) %u", (unsigned)n); \
+ } \
ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \
} \
if (unlikely(ndr->offset > ndr->data_size)) { \
--
GitLab

View File

@ -0,0 +1,277 @@
From ba518a1debbe2dd8231ba2fb9bbb07eef743d86f Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Thu, 30 Jan 2020 08:49:07 +1300
Subject: [PATCH] librpc ndr: add recursion check macros
Add macros to check the recursion depth.
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19280
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14254
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
librpc/ndr/libndr.h | 37 ++++++++-
librpc/ndr/ndr.c | 2 +
librpc/tests/test_ndr_macros.c | 138 +++++++++++++++++++++++++++++++++
librpc/wscript_build | 9 +++
source4/selftest/tests.py | 2 +
5 files changed, 187 insertions(+), 1 deletion(-)
create mode 100644 librpc/tests/test_ndr_macros.c
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 8d407c40e43..fd87db928ed 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -79,6 +79,14 @@ struct ndr_pull {
/* this is used to ensure we generate unique reference IDs
between request and reply */
uint32_t ptr_count;
+ uint32_t recursion_depth;
+ /*
+ * The global maximum depth for recursion. When set it overrides the
+ * value supplied by the max_recursion idl attribute. This is needed
+ * for fuzzing as ASAN uses a low threshold for stack depth to check
+ * for stack overflow.
+ */
+ uint32_t global_max_recursion;
};
/* structure passed to functions that generate NDR formatted data */
@@ -249,7 +257,9 @@ enum ndr_err_code {
NDR_ERR_UNREAD_BYTES,
NDR_ERR_NDR64,
NDR_ERR_FLAGS,
- NDR_ERR_INCOMPLETE_BUFFER
+ NDR_ERR_INCOMPLETE_BUFFER,
+ NDR_ERR_MAX_RECURSION_EXCEEDED,
+ NDR_ERR_UNDERFLOW
};
#define NDR_ERR_CODE_IS_SUCCESS(x) (x == NDR_ERR_SUCCESS)
@@ -357,6 +367,31 @@ enum ndr_compression_alg {
} \
} while(0)
+#define NDR_RECURSION_CHECK(ndr, d) do { \
+ uint32_t _ndr_min_ = (d); \
+ if (ndr->global_max_recursion && ndr->global_max_recursion < (d)) { \
+ _ndr_min_ = ndr->global_max_recursion; \
+ } \
+ ndr->recursion_depth++; \
+ if (unlikely(ndr->recursion_depth > _ndr_min_)) { \
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_MAX_RECURSION_EXCEEDED, \
+ "Depth of recursion exceeds (%u)", \
+ (unsigned) d); \
+ } \
+} while (0)
+
+#define NDR_RECURSION_UNWIND(ndr) do { \
+ if (unlikely(ndr->recursion_depth == 0)) { \
+ return ndr_pull_error( \
+ ndr, \
+ NDR_ERR_UNDERFLOW, \
+ "ndr_pull.recursion_depth is 0"); \
+ } \
+ ndr->recursion_depth--; \
+} while (0)
+
/* these are used to make the error checking on each element in libndr
less tedious, hopefully making the code more readable */
#define NDR_CHECK(call) do { \
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index f96a0bca08b..afe22a28602 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -1950,6 +1950,8 @@ static const struct {
{ NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
{ NDR_ERR_NDR64, "NDR64 assertion error" },
{ NDR_ERR_INCOMPLETE_BUFFER, "Incomplete Buffer" },
+ { NDR_ERR_MAX_RECURSION_EXCEEDED, "Maximum Recursion Exceeded" },
+ { NDR_ERR_UNDERFLOW, "Underflow" },
{ 0, NULL }
};
diff --git a/librpc/tests/test_ndr_macros.c b/librpc/tests/test_ndr_macros.c
new file mode 100644
index 00000000000..0cd20d3e8f3
--- /dev/null
+++ b/librpc/tests/test_ndr_macros.c
@@ -0,0 +1,138 @@
+/*
+ * Tests for librpc ndr functions
+ *
+ * Copyright (C) Catalyst.NET Ltd 2020
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "librpc/ndr/libndr.h"
+
+/*
+ * Test NDR_RECURSION_CHECK.
+ */
+static enum ndr_err_code wrap_NDR_RECURSION_CHECK(
+ struct ndr_pull *ndr,
+ uint32_t bytes) {
+
+ NDR_RECURSION_CHECK(ndr, bytes);
+ return NDR_ERR_SUCCESS;
+}
+
+static void test_NDR_RECURSION_CHECK(void **state)
+{
+ struct ndr_pull ndr = {0};
+ enum ndr_err_code err;
+
+
+ ndr.global_max_recursion = 0;
+ ndr.recursion_depth = 42;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 43);
+ assert_int_equal(NDR_ERR_SUCCESS, err);
+ assert_int_equal(43, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 0;
+ ndr.recursion_depth = 43;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 43);
+ assert_int_equal(NDR_ERR_MAX_RECURSION_EXCEEDED, err);
+ assert_int_equal(44, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 0;
+ ndr.recursion_depth = 44;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 43);
+ assert_int_equal(NDR_ERR_MAX_RECURSION_EXCEEDED, err);
+ assert_int_equal(45, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 5;
+ ndr.recursion_depth = 5;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 20);
+ assert_int_equal(NDR_ERR_MAX_RECURSION_EXCEEDED, err);
+ assert_int_equal(6, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 5;
+ ndr.recursion_depth = 4;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 20);
+ assert_int_equal(NDR_ERR_SUCCESS, err);
+ assert_int_equal(5, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 20;
+ ndr.recursion_depth = 5;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 5);
+ assert_int_equal(NDR_ERR_MAX_RECURSION_EXCEEDED, err);
+ assert_int_equal(6, ndr.recursion_depth);
+
+ ndr.global_max_recursion = 20;
+ ndr.recursion_depth = 4;
+ err = wrap_NDR_RECURSION_CHECK(&ndr, 5);
+ assert_int_equal(NDR_ERR_SUCCESS, err);
+ assert_int_equal(5, ndr.recursion_depth);
+}
+
+/*
+ * Test NDR_RECURSION_RETURN.
+ */
+static enum ndr_err_code wrap_NDR_RECURSION_UNWIND(
+ struct ndr_pull *ndr) {
+
+ NDR_RECURSION_UNWIND(ndr);
+ return NDR_ERR_SUCCESS;
+}
+
+static void test_NDR_RECURSION_UNWIND(void **state)
+{
+ struct ndr_pull ndr = {0};
+ enum ndr_err_code err;
+
+ ndr.recursion_depth = 5;
+ err = wrap_NDR_RECURSION_UNWIND(&ndr);
+ assert_int_equal(NDR_ERR_SUCCESS, err);
+ assert_int_equal(4, ndr.recursion_depth);
+
+ ndr.recursion_depth = 0;
+ err = wrap_NDR_RECURSION_UNWIND(&ndr);
+ assert_int_equal(NDR_ERR_UNDERFLOW, err);
+ assert_int_equal(0, ndr.recursion_depth);
+
+}
+int main(int argc, const char **argv)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_NDR_RECURSION_CHECK),
+ cmocka_unit_test(test_NDR_RECURSION_UNWIND),
+ };
+
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/librpc/wscript_build b/librpc/wscript_build
index ec8697fbcc5..f0bf7f7785e 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -690,6 +690,14 @@ bld.SAMBA_SUBSYSTEM('NDR_FSRVP_STATE',
#
# Cmocka tests
#
+bld.SAMBA_BINARY('test_ndr_macros',
+ source='tests/test_ndr_macros.c',
+ deps='''
+ cmocka
+ ndr
+ ''',
+ for_selftest=True)
+
bld.SAMBA_BINARY('test_ndr_string',
source='tests/test_ndr_string.c',
deps='''
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 5cdb3d27b77..389a142db7d 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -1346,6 +1346,8 @@ plantestsuite("librpc.ndr.ndr_string", "none",
[os.path.join(bindir(), "test_ndr_dns_nbt")])
plantestsuite("libcli.ldap.ldap_message", "none",
[os.path.join(bindir(), "test_ldap_message")])
+plantestsuite("librpc.ndr.ndr_macros", "none",
+ [os.path.join(bindir(), "test_ndr_macros")])
# process restart and limit tests, these break the environment so need to run
# in their own specific environment
--
GitLab

View File

@ -0,0 +1,110 @@
From a97c78fb221a2f1aaca2effdb44c51e4f78ddd93 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Thu, 7 Nov 2019 10:03:36 +0100
Subject: [PATCH] lzxpress: add bounds checking to lzxpress_decompress()
lzxpress_decompress() would wander past the end of the array in
numerous locations.
Credit to OSS-Fuzz.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14190
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19382
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20083
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22485
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22667
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Autobuild-User(master): Douglas Bagnall <dbagnall@samba.org>
Autobuild-Date(master): Sun Aug 9 00:30:26 UTC 2020 on sn-devel-184
---
lib/compression/lzxpress.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/lib/compression/lzxpress.c b/lib/compression/lzxpress.c
index 024aba4c2ce..d8326304455 100644
--- a/lib/compression/lzxpress.c
+++ b/lib/compression/lzxpress.c
@@ -252,8 +252,24 @@ ssize_t lzxpress_decompress(const uint8_t *input,
offset = 0;
nibble_index = 0;
+#define __CHECK_BYTES(__size, __index, __needed) do { \
+ if (unlikely(__index >= __size)) { \
+ return -1; \
+ } else { \
+ uint32_t __avail = __size - __index; \
+ if (unlikely(__needed > __avail)) { \
+ return -1; \
+ } \
+ } \
+} while(0)
+#define CHECK_INPUT_BYTES(__needed) \
+ __CHECK_BYTES(input_size, input_index, __needed)
+#define CHECK_OUTPUT_BYTES(__needed) \
+ __CHECK_BYTES(max_output_size, output_index, __needed)
+
do {
if (indicator_bit == 0) {
+ CHECK_INPUT_BYTES(4);
indicator = PULL_LE_UINT32(input, input_index);
input_index += sizeof(uint32_t);
indicator_bit = 32;
@@ -266,10 +282,13 @@ ssize_t lzxpress_decompress(const uint8_t *input,
* check whether the 4th bit of the value in indicator is set
*/
if (((indicator >> indicator_bit) & 1) == 0) {
+ CHECK_INPUT_BYTES(1);
+ CHECK_OUTPUT_BYTES(1);
output[output_index] = input[input_index];
input_index += sizeof(uint8_t);
output_index += sizeof(uint8_t);
} else {
+ CHECK_INPUT_BYTES(2);
length = PULL_LE_UINT16(input, input_index);
input_index += sizeof(uint16_t);
offset = length / 8;
@@ -277,6 +296,7 @@ ssize_t lzxpress_decompress(const uint8_t *input,
if (length == 7) {
if (nibble_index == 0) {
+ CHECK_INPUT_BYTES(1);
nibble_index = input_index;
length = input[input_index] % 16;
input_index += sizeof(uint8_t);
@@ -286,9 +306,11 @@ ssize_t lzxpress_decompress(const uint8_t *input,
}
if (length == 15) {
+ CHECK_INPUT_BYTES(1);
length = input[input_index];
input_index += sizeof(uint8_t);
if (length == 255) {
+ CHECK_INPUT_BYTES(2);
length = PULL_LE_UINT16(input, input_index);
input_index += sizeof(uint16_t);
length -= (15 + 7);
@@ -299,10 +321,16 @@ ssize_t lzxpress_decompress(const uint8_t *input,
}
length += 3;
+ if (length == 0) {
+ return -1;
+ }
- do {
- if ((output_index >= max_output_size) || ((offset + 1) > output_index)) break;
+ if (offset >= output_index) {
+ return -1;
+ }
+ CHECK_OUTPUT_BYTES(length);
+ do {
output[output_index] = output[output_index - offset - 1];
output_index += sizeof(uint8_t);
--
GitLab

View File

@ -0,0 +1,35 @@
From 0c461f3bd589764c496b530f698e313df50667e6 Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Date: Thu, 6 Aug 2020 17:17:01 +1200
Subject: [PATCH] lzxpress: avoid technically undefined shift
UBSAN:
runtime error: left shift of 1 by 31 places cannot be represented in type 'int'
Credit to OSS-fuzz.
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22283
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Mon Aug 31 22:31:13 UTC 2020 on sn-devel-184
---
lib/compression/lzxpress.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/compression/lzxpress.c b/lib/compression/lzxpress.c
index d8326304455c..3453dd36f2aa 100644
--- a/lib/compression/lzxpress.c
+++ b/lib/compression/lzxpress.c
@@ -180,7 +180,7 @@ ssize_t lzxpress_compress(const uint8_t *uncompressed,
}
}
- indic |= 1 << (32 - ((indic_bit % 32) + 1));
+ indic |= 1U << (32 - ((indic_bit % 32) + 1));
if (best_len > 9) {
if (nibble_index == 0) {

View File

@ -0,0 +1,52 @@
From 5d323f2a2e36c23a007d93394f25df0f3d30942d Mon Sep 17 00:00:00 2001
From: Gary Lockyer <gary@catalyst.net.nz>
Date: Thu, 30 Jan 2020 08:51:47 +1300
Subject: [PATCH] pidl: Add recursive depth checks.
Add new parameter to elements "max_recursion" and modify pidl to call
NDR_RECURSION_CHECK and NDR_RECURSION_UNWIND for element tagged with
that attribute.
Credit to OSS-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19820
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14254
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
---
pidl/lib/Parse/Pidl/NDR.pm | 1 +
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/pidl/lib/Parse/Pidl/NDR.pm b/pidl/lib/Parse/Pidl/NDR.pm
index 44338a1298d8..d17d0b404ed0 100644
--- a/pidl/lib/Parse/Pidl/NDR.pm
+++ b/pidl/lib/Parse/Pidl/NDR.pm
@@ -1101,6 +1101,7 @@ my %property_list = (
"gensize" => ["TYPEDEF", "STRUCT", "UNION"],
"value" => ["ELEMENT"],
"flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
+ "max_recursion" => ["ELEMENT"],
# generic
"public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"],
diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
index 0d58cb5f03d5..119590f66969 100644
--- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
+++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
@@ -993,7 +993,14 @@ sub ParseDataPull($$$$$$$)
$var_name = get_pointer_to($var_name);
+ if (my $depth = has_property($e, "max_recursion")) {
+ my $d = parse_int($depth);
+ $self->pidl("NDR_RECURSION_CHECK($ndr, $d);");
+ }
$self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));");
+ if (has_property($e, "max_recursion")) {
+ $self->pidl("NDR_RECURSION_UNWIND($ndr);");
+ }
my $pl = GetPrevLevel($e, $l);

View File

@ -0,0 +1,38 @@
From ed9abf94b3167a1a61b5da163e9b07b06c8a457b Mon Sep 17 00:00:00 2001
From: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Date: Sun, 6 Sep 2020 09:35:49 +1200
Subject: [PATCH] utils/asn1: avoid undefined behaviour warning
UBSAN does not like an int >= 1<<24 being shifted left.
We check the overflow in the very next line.
Credit to OSS-Fuzz.
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25436
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Fri Sep 11 05:05:59 UTC 2020 on sn-devel-184
---
lib/util/asn1.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
index 6b1b4bc2877f..9ab9e1b08449 100644
--- a/lib/util/asn1.c
+++ b/lib/util/asn1.c
@@ -1071,7 +1071,11 @@ bool asn1_read_enumerated(struct asn1_data *data, int *v)
if (!asn1_read_uint8(data, &b)) {
return false;
}
- *v = (*v << 8) + b;
+ /*
+ * To please/fool the Undefined Behaviour Sanitizer we cast to
+ * unsigned for the left shift.
+ */
+ *v = ((unsigned int)*v << 8) + b;
}
return asn1_end_tag(data);
}

View File

@ -0,0 +1,50 @@
From 8cce23acb9f9bdde8bff3c3a7ffa83361e3a64a6 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze@samba.org>
Date: Fri, 31 Jul 2020 11:27:25 +0200
Subject: [PATCH] witness.idl: fix length calculation for
witness_IPaddrInfoList
If r->num is 0, we should not dereference r->addr.
Using ndr_size_witness_IPaddrInfoList() also make this much simpler
and avoids the magic 12.
Credit Oss-Fuzz
REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22175
REF: https://oss-fuzz.com/testcase-detail/5686294157197312
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14452
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Samuel Cabrero <scabrero@samba.org>
---
librpc/idl/witness.idl | 6 +++---
source4/torture/ndr/witness.c | 24 ------------------------
2 files changed, 3 insertions(+), 27 deletions(-)
diff --git a/librpc/idl/witness.idl b/librpc/idl/witness.idl
index e230a5ea709..652c0e9cb65 100644
--- a/librpc/idl/witness.idl
+++ b/librpc/idl/witness.idl
@@ -98,14 +98,14 @@ interface witness
WITNESS_IPADDR_OFFLINE = 0x10
} witness_IPaddrInfo_flags;
- typedef [flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN),gensize] struct {
+ typedef [flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN)] struct {
witness_IPaddrInfo_flags flags;
[flag(NDR_BIG_ENDIAN)] ipv4address ipv4;
[flag(NDR_BIG_ENDIAN)] ipv6address ipv6;
} witness_IPaddrInfo;
- typedef [flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN)] struct {
- [value(12+(r->num*ndr_size_witness_IPaddrInfo(r->addr, ndr->flags)))] uint32 length;
+ typedef [public,flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN),gensize] struct {
+ [value(ndr_size_witness_IPaddrInfoList(r, ndr->flags))] uint32 length;
[value(0)] uint32 reserved;
uint32 num;
witness_IPaddrInfo addr[num];
--
GitLab

View File

@ -49,7 +49,7 @@
Name: samba
Version: 4.12.5
Release: 7
Release: 8
Summary: A suite for Linux to interoperate with Windows
License: GPLv3+ and LGPLv3+
@ -75,6 +75,17 @@ Patch5: CVE-2021-20277.patch
Patch6: CVE-2020-27840.patch
Patch7: CVE-2021-20254.patch
Patch8: backport-CVE-2021-3671.patch
Patch9: backport-lzxpress-add-bounds-checking-to-lzxpress_decompress.patch
Patch10: backport-librpc-ndr-NDR_PULL_ALIGN-check-for-unsigned-overflow.patch
Patch11: backport-librpc-ndr-add-recursion-check-macros.patch
Patch12: backport-librpc-ndr-Heap-buffer-overflow-in-lzxpress_decompress.patch
Patch13: backport-pidl-Add-recursive-depth-checks.patch
Patch14: backport-idl-drsuapi_DsaAddressListItem_V1-limit-recursion.patch
Patch15: backport-idl-limit-recurion-on-recursive-elements.patch
Patch16: backport-lib-ldb-Limit-depth-of-ldb_parse_tree.patch
Patch17: backport-witness-idl-fix-length-calculation-for-witness_IPaddrInfoList.patch
Patch18: backport-lzxpress-avoid-technically-undefined-shift.patch
Patch19: backport-utils-asn1-avoid-undefined-behaviour.patch
BuildRequires: avahi-devel bison cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel flex gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel
BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel
@ -3209,6 +3220,23 @@ fi
%endif
%changelog
* Fri Oct 29 2021 gaihuiying <gaihuiying1@huawei.com> - 4.12.5-8
- Type:bugfix
- ID:NA
- SUG:NA
- DESC:fix fuzz error:
idl: drsuapi_DsaAddressListItem_V1 limit recursion
idl: limit recurion on recursive-elements
lib: ldb Limit depth of ldb_parse_tree
librpc: ndr add recursion check macros
librpc: ndr Heap-buffer-overflow in lzxpress_decompress
librpc: ndr NDR_PULL_ALIGN check for unsigned overflow
lzxpress: add bounds checking to lzxpress decompress
lzxpress: avoid technically undefined shift
pidl: Add recursive depth checks
utils: asn1 avoid undefined behaviour
witness: idl fix length calculation for witness_IPaddrInfoList
* Mon Oct 25 2021 gaihuiying <gaihuiying1@huawei.com> - 4.12.5-7
- Type:cves
- ID:CVE-2021-3671