Bug 15014 - [FUZZING] excessive memory usage in dfsblobs
Summary: [FUZZING] excessive memory usage in dfsblobs
Status: NEW
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: DCE-RPCs and pipes (show other bugs)
Version: unspecified
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Samba QA Contact
QA Contact: Samba QA Contact
URL: https://bugs.chromium.org/p/oss-fuzz/...
Depends on:
Reported: 2022-03-13 01:11 UTC by Douglas Bagnall
Modified: 2022-03-13 22:14 UTC (History)
0 users

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Douglas Bagnall 2022-03-13 01:11:25 UTC
Given a 256kB file, fuzz_ndr_dfsblobs_TYPE_STRUCT can generate (per valgrind) 16,475,520 allocs, 16,475,512 frees, 4,020,344,240 bytes allocated.

I currently suspect that convert_string_talloc() is sometimes returning false (indicating an error) while not freeing the bad string, and ndr_pull_string_array() is hammering this. It gets freed eventually. The issue is that malformed data can OOM the server first.
Comment 1 Douglas Bagnall 2022-03-13 01:19:02 UTC
(In reply to Douglas Bagnall from comment #0)

> I currently suspect that convert_string_talloc() is sometimes returning false (indicating an error) while not freeing the bad string,

OK, not that. It is somewhere further up the stack, in the ndr_pull_string_array() or somewhere.

 	1572071304 byte(s) (93%) in 8190474 allocation(s)
	    #0 0x55d254c229cd in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:129:3
	    #1 0x55d254c69d36 in __talloc_with_prefix samba/lib/talloc/talloc.c:783:9
	    #2 0x55d254c62575 in __talloc samba/lib/talloc/talloc.c:825:9
	    #3 0x55d254c62575 in _talloc_named_const samba/lib/talloc/talloc.c:982:8
	    #4 0x55d254c62575 in _talloc_realloc samba/lib/talloc/talloc.c:1822:10
	    #5 0x55d254c68641 in _talloc_realloc_array samba/lib/talloc/talloc.c:2785:9
	    #6 0x55d254ccb566 in convert_string_talloc_handle samba/lib/util/charset/convert_string.c:413:7
	    #7 0x55d254ccc08b in convert_string_talloc samba/lib/util/charset/convert_string.c:553:9
	    #8 0x55d254c9bd1c in ndr_pull_string samba/librpc/ndr/ndr_string.c:164:15
	    #9 0x55d254c9de3d in ndr_pull_string_array samba/librpc/ndr/ndr_string.c:433:4
	    #10 0x55d254ce5691 in ndr_pull_dfs_domain_referral samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:713:6
	    #11 0x55d254ce2611 in ndr_pull_dfs_referral samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:836:5
	    #12 0x55d254ce2611 in ndr_pull_dfs_referral_v3 samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:976:4
	    #13 0x55d254cdfbcd in ndr_pull_dfs_referral_version samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:1115:5
	    #14 0x55d254cda542 in ndr_pull_dfs_referral_type samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:1198:4
	    #15 0x55d254cd9c48 in ndr_pull_dfs_referral_resp samba/bin/default/librpc/gen_ndr/ndr_dfsblobs.c:1270:4
	    #16 0x55d254c7814e in LLVMFuzzerTestOneInput samba/bin/default/lib/fuzzing/fuzz_ndr_dfsblobs_TYPE_STRUCT.c:276:13
Comment 2 Douglas Bagnall 2022-03-13 02:56:21 UTC
(In reply to Douglas Bagnall from comment #1)

more notes to myself.

in ndr_pull_dfs_domain_referral, line 660 and 673, 

                        uint32_t _flags_save_string = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_ALIGN2);
                        NDR_CHECK(ndr_pull_relative_ptr_short(ndr, &_ptr_special_name));
                        if (_ptr_special_name) {
>>>                             NDR_PULL_ALLOC(ndr, r->special_name);
                                NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->special_name, _ptr_special_name));
                        } else {
                                r->special_name = NULL;
                        ndr->flags = _flags_save_string;


                        uint32_t _flags_save_string_array = ndr->flags;
                        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING|LIBNDR_FLAG_STR_NULLTERM);
                        NDR_CHECK(ndr_pull_relative_ptr_short(ndr, &_ptr_expanded_names));
                        if (_ptr_expanded_names) {
>>>                             NDR_PULL_ALLOC(ndr, r->expanded_names);
                                NDR_CHECK(ndr_pull_relative_ptr1(ndr, r->expanded_names, _ptr_expanded_names));
                        } else {
                                r->expanded_names = NULL;
                        ndr->flags = _flags_save_string_array;

These are run 65535 times each time we go through lndr_pull_dfs_referral_resp(), line 1272:

		for (cntr_referral_entries_0 = 0; cntr_referral_entries_0 < (size_referral_entries_0); cntr_referral_entries_0++) {
			NDR_CHECK(ndr_pull_dfs_referral_type(ndr, NDR_BUFFERS, &r->referral_entries[cntr_referral_entries_0]));

so its not about things not being freed on error.
Comment 3 Douglas Bagnall 2022-03-13 22:14:40 UTC
In other words, another case of bug #14505.