Bug 11495 - undefined behaviour detected by gnu gcc sanitizer
Summary: undefined behaviour detected by gnu gcc sanitizer
Status: RESOLVED FIXED
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: Other (show other bugs)
Version: 4.1.17
Hardware: x64 Linux
: P5 normal (vote)
Target Milestone: ---
Assignee: Karolin Seeger
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-09-05 08:25 UTC by Vittorio
Modified: 2019-02-05 14:16 UTC (History)
2 users (show)

See Also:


Attachments
git-am fix for master. (1.08 KB, patch)
2015-09-10 17:44 UTC, Jeremy Allison
no flags Details
Updated fix for master. (2.72 KB, patch)
2015-09-11 21:36 UTC, Jeremy Allison
no flags Details
git-am fix for 4.9.next, 4.8.next cherry-picked from master. (2.44 KB, patch)
2019-01-16 17:58 UTC, Jeremy Allison
ddiss: review+
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vittorio 2015-09-05 08:25:24 UTC
Hi there, I just built samba 4.1.17 
with the gnu gcc options -fsanitize=address -fsanitize=undefine -Og -ggdb -fno-omit-frame-pointer
and I got many runtime error messages from the sanitizer.
This is running "make test" as root.
Mostly they are due to memcpy called with NULL pointer(s), then qsort and memmove.
They seem harmless because the length parameter is (always?) zero, 
but I believe they should be fixed anyway, as in

if(len) memcpy(target,null-pointer,len)

Then there are undefined shifts like 1<<31 which should be 1u<<31
and more undefined shifts like 189<<24 which does not fit into the 'int' type.
Maybe these are important and not so harmless.
I have an x86-64 architecture under Linux 4.1.5 distribution Fedora 21.
gnu gcc is at level 5.2.0. This is important. 


I put a /*vz*/ comment at or near the lines I changed to "fix" these issues, a few are BAD,
I do not know how to fix them, a grep follows:

./libcli/smb/smb1cli_trans.c:		if(state->num_setup) memcpy(vwv + 14, state->setup,/*vz*/
./libcli/smb/smbXcli_base.c:		if(iov[i].iov_len) memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);/*vz*/
./lib/talloc/talloc.c:		if(size) memcpy(newp, p, size);/*vz*/
./lib/socket_wrapper/socket_wrapper.c:		if(this_time) memcpy(buf + ofs,/*vz*/
./lib/util/idtree.c:/*vz*/
./lib/util/asn1.c:	if(len) memcpy(data->data + data->ofs, p, len);/*vz*/
./lib/util/bitmap.c:	bm->b[i/32] |= (1u<<(i%32));/*vz*/
./lib/util/bitmap.c:	bm->b[i/32] &= ~(1u<<(i%32));/*vz*/
./lib/util/bitmap.c:	if (bm->b[i/32] & (1u<<(i%32))) { /*vz*/
./lib/krb5_wrap/enctype_convert.c:		uint32_t bit_value = (1u<< i) & enctype_bitmap;/*vz*/
./lib/crypto/md4.c:M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |/*vz*//*runtime error: left shift of 189 by 24 places cannot be represented in type 'int'*/
./lib/crypto/md4.c:	if(n) memcpy(buf, in, n);/*vz*/
./librpc/ndr/libndr.h:/* set to avoid recursion in ndr_size_*() calculation */ /*vz*/
#define LIBNDR_FLAG_NO_NDR_SIZE         (1u<<31)
./librpc/ndr/ndr_basic.c:	if(n) memcpy(ndr->data + ndr->offset, data, n);/*vz*/
./source4/libcli/raw/rawtrans.c:	if(parms->in.params.length) memcpy(req->out.data,/*vz*/
./source4/libcli/raw/rawtrans.c:	if(parms->in.data.length) memcpy(req->out.data + parms->in.params.length,/*vz*/
./source4/libcli/raw/rawtrans.c:	if(parms->in.setup_count) memcpy(req->out.vwv,/*vz*/
./source4/libcli/raw/rawtrans.c:	if(parms->in.data.length) memcpy(req->out.data + parms->in.params.length,/*vz*/
./source4/libcli/raw/rawrequest.c:	if(blob->length) memcpy(req->out.data + req->out.data_size, blob->data, blob->length);/*vz*/
./source4/libcli/raw/raweas.c:if(eas[i].value.length) memcpy(data+4+nlen+1, eas[i].value.data, eas[i].value.length);/*vz*/
./source4/libcli/raw/clitransport.c:assert(transport);/*vz*/
smbXcli_conn_disconnect(transport->conn, status); /* BAD: here transport == NULL */
./source4/ntvfs/common/brlock_tdb.c:	if(dbuf.dsize) memcpy(locks, dbuf.dptr, dbuf.dsize);/*vz*/
./source4/torture/smb2/dir.c:/*vz*//*BAD: index 702 out of bounds for type 'file_elem [702]'*/
files[num_files + 2].name = talloc_asprintf(mem_ctx, "T013-13.txt.3"); /*BAD*/
./source4/dsdb/kcc/kcc_topology.c:	if(internal_edges.count) qsort(internal_edges.data, internal_edges.count,/*vz*/
./source4/heimdal/lib/asn1/der_put.c:    if(data->length) memcpy (p+1, data->data, data->length);/*vz*/
./source4/heimdal/lib/krb5/store_emem.c:    if(size) memmove(s->ptr, data, size);/*vz*/
./source4/heimdal/lib/krb5/crypto.c:    if(len) memcpy(ipad + cm->blocksize, data, len);/*vz*/
./source4/smb_server/smb/nttrans.c:		if(trans->out.setup_count) memcpy((char *)(this_req->out.vwv) + VWV(18), trans->out.setup,/*vz*/
./bin/default/include/public/ndr.h:/* set to avoid recursion in ndr_size_*() calculation */ /*vz*/
#define LIBNDR_FLAG_NO_NDR_SIZE         (1u<<31)
./source3/lib/dbwrap/dbwrap_watch.c:	if(value.dsize) memcpy(ids, value.dptr, value.dsize);/*vz*/
./source3/lib/util_tdb.c:				if(i) memcpy(buf+4, s, i); /*vz*/
./source3/smbd/notify_internal.c:	if(value.dsize) memcpy(entries, value.dptr, value.dsize);/*vz*/
./source3/smbd/trans2.c:		if(ea_list->ea.value.length) memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);/*vz*/
./source3/libsmb/errormap.c:	for (i=0; NT_STATUS_V(dos_to_ntstatus_map[i].ntstatus); i++) {/*vz*//*BAD: index 249 out of bounds for type '<unknown> [249]'*/
./source3/libsmb/nmblib.c:	name->name[n] = 0;/*vz*//*BAD: index 16 out of bounds for type 'char [16]'*/
source4/ntvfs/posix/pvfs_dirlist.c:241:35: runtime error: signed integer overflow: 9223372036854775807 + 2147483682 cannot be represented in type 'long int'
Comment 1 Vittorio 2015-09-07 18:41:41 UTC
After downloading version 4.2.3 the following are the lines I changed
or where the sanitizer found issues, some are BAD in my opinion

./libcli/smb/smb1cli_trans.c:		if(state->num_setup) memcpy(vwv + 14, state->setup,/*vz*/
./libcli/smb/smbXcli_base.c:		if(iov[i].iov_len) memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);/*vz*/
./libcli/cldap/cldap.c:	if(blob1.length) memcpy(state->blob.data, blob1.data, blob1.length);/*vz*/
./lib/talloc/talloc.c:		if(size) memcpy(newp, p, size);/*vz*/
./lib/socket_wrapper/socket_wrapper.c:		if(this_time) memcpy(buf + ofs,/*vz*/
./lib/util/idtree.c:/*vz*/
./lib/util/idtree.c:	    ((id & ~(~0u<< MAX_ID_SHIFT)) >> (n + IDR_BITS))) { /*vz*/
./lib/util/asn1.c:	if(len) memcpy(data->data + data->ofs, p, len);/*vz*/
./lib/util/bitmap.c:	bm->b[i/32] |= (1u<<(i%32));/*vz*/
./lib/util/bitmap.c:	bm->b[i/32] &= ~(1u<<(i%32));/*vz*/
./lib/util/bitmap.c:	if (bm->b[i/32] & (1u<<(i%32))) {/*vz*/
./lib/krb5_wrap/enctype_convert.c:		uint32_t bit_value = (1u<< i) & enctype_bitmap;/*vz*/
./lib/crypto/aes_cmac_128.c:		if(len) memcpy(&tmp_block[ctx->last_len], msg, len);/*vz*/
./lib/crypto/md4.c:	if(n) memcpy(buf, in, n);/*vz*/
./librpc/ndr/libndr.h:/*vz*/
./librpc/ndr/ndr_basic.c:	if(n) memcpy(ndr->data + ndr->offset, data, n);/*vz*/
grep: ./st: Permission denied
./source4/libcli/raw/rawtrans.c:	if(parms->in.setup_count) memcpy(req->out.vwv,/*vz*/
./source4/libcli/raw/rawrequest.c:	if(blob->length) memcpy(req->out.data + req->out.data_size, blob->data, blob->length);/*vz*/
./source4/ntvfs/common/brlock_tdb.c:	if(dbuf.dsize) memcpy(locks, dbuf.dptr, dbuf.dsize);/*vz*/
./source4/ntvfs/posix/pvfs_dirlist.c:dir->offset = telldir(dir->dir) + DIR_OFFSET_BASE;/*vz*//*BAD: signed integer overflow: 9223372036854775807 + 2147483682 cannot be represented in type 'long int'*/
./source4/dsdb/kcc/kcc_topology.c:	if(internal_edges.count) qsort(internal_edges.data, internal_edges.count,/*vz*/
./source4/heimdal/lib/asn1/der_put.c:    if(data->length) memcpy (p+1, data->data, data->length);/*vz*/
./source4/heimdal/lib/krb5/store_emem.c:    if(size) memmove(s->ptr, data, size);/*vz*/
./source4/heimdal/lib/krb5/crypto.c:    if(len) memcpy(ipad + cm->blocksize, data, len);/*vz*/
./source4/heimdal/lib/krb5/crypto.c:	keyusage = CHECKSUM_USAGE(usage);/*vz*/ /*left shift of negative value -21*/
./source4/heimdal/lib/krb5/crypto.c:	keyusage = CHECKSUM_USAGE(usage);/*vz*/ /*left shift of negative value -21*/
./source4/heimdal/lib/hcrypto/des.c:    t2 = (*key)[4] << 24 | (*key)[5] << 16 | (*key)[6] << 8 | (*key)[7];/*vz*//*left shift of 186 by 24 places cannot be represented in type 'int'*/
./source4/heimdal/lib/hcrypto/des.c:    v[0] =  b[0] << 24;/*vz*/
./source4/heimdal/lib/hcrypto/des.c:    v[1] =  b[4] << 24;/*vz*/
./source4/smb_server/smb/nttrans.c:		if(trans->out.setup_count) memcpy((char *)(this_req->out.vwv) + VWV(18), trans->out.setup,/*vz*/
./source4/smb_server/smb/reply.c:		if(io->spnego.out.secblob.length) memcpy(req->out.data, io->spnego.out.secblob.data, io->spnego.out.secblob.length);/*vz*/
./bin/default/include/public/ndr.h:/*vz*/
./source3/lib/messages.c:	int64_t fds64[MIN(num_fds, INT8_MAX)];/*vz*//*num_fds==0*/
./source3/lib/dbwrap/dbwrap_watch.c:	if(value.dsize) memcpy(ids, value.dptr, value.dsize);/*vz*/
./source3/lib/util_tdb.c:				if(i) memcpy(buf+4, s, i);/*vz*/
./source3/lib/util_sock.c:		if(len) memcpy(p, iov[i].iov_base, len);/*vz*/
./source3/rpc_server/winreg/srv_winreg_nt.c:			if(outbuf_size) memcpy(r->out.data, outbuf, outbuf_size);/*vz*/
./source3/rpc_server/spoolss/srv_spoolss_nt.c:		if(val_size) memcpy(r->out.data, val_data, val_size);/*vz*/
./source3/smbd/notify_internal.c:	if(value.dsize) memcpy(entries, value.dptr, value.dsize);/*vz*/
./source3/smbd/trans2.c:		if(ea_list->ea.value.length) memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);/*vz*/
./source3/smbd/trans2.c:	SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^ /*vz*//*left shift of negative value -690670082*/
./source3/libsmb/nmblib.c:	name->name[n] = 0;/*vz*//*BAD: index 16 out of bounds for type 'char [16]'*/
./source3/locking/brlock.c:		if(lock_len) memcpy(data.dptr, br_lck->lock_data, lock_len);/*vz*/
./source3/locking/posix.c:	if(value.dsize) memcpy(fds, value.dptr, value.dsize);/*vz*/
Comment 2 Andrew Bartlett 2015-09-07 21:39:22 UTC
While we should go back and check the older releases in case of security issues, Samba development is done first in git master.  If you can run on that, it will be easier to get started on any patches you propose, or others glean from the output.

Thanks!
Comment 3 Vittorio 2015-09-10 03:41:32 UTC
Unfortunately I do not have time to look at the git version.
Version 4.2.3 is better that 4.1.17 concerning the sanitizer.
But I believe at least the out of bounds array access

source3/libsmb/nmblib.c:	name->name[n] = 0;/*vz*//*BAD: index 16 out of bounds for type 'char [16]'*/

should be fixed.

The overflows should be looked at.
Comment 4 Jeremy Allison 2015-09-10 17:44:02 UTC
Created attachment 11426 [details]
git-am fix for master.

Can you try this (which fixes the specific error you called out) ? It's not a security issue as:

struct nmb_name {
        nstring      name;
        char         scope[64];
        unsigned int name_type;
};

which means overflowing the name field will overwrite scope, but not anything else.
Comment 5 Vittorio 2015-09-11 10:31:46 UTC
In source4/auth/ntlm/auth_sam.c:415 the statement 

allowed_period = allowed_period_mins * 60 * 1000*1000*10;

is undefined because the constant does not fit in the int type.
The following is correct

allowed_period = allowed_period_mins * 600000000L;

The L suffix denotes a 'long int' constant.

auth_sam.c has to do with passwords so maybe this is a secutity issue.
Comment 6 Jeremy Allison 2015-09-11 20:02:29 UTC
(In reply to Vittorio from comment #5)

I'll take a look at this. In the meantime can you confirm the fix I posted for the previous issue ?
Comment 7 Jeremy Allison 2015-09-11 21:12:22 UTC
(In reply to Vittorio from comment #5)

OK, this is a bug, not a security issue. If:

allowed_period = allowed_period_mins * 60 * 1000*1000*10;

is truncated, then the Samba AD-DC will return NT_STATUS_WRONG_PASSWORD instead of allowing the user in, so it's failing closed. Your fix is still valid, and I'll update the patch to include it !

Cheers,

Jeremy.
Comment 8 Jeremy Allison 2015-09-11 21:36:48 UTC
Created attachment 11433 [details]
Updated fix for master.

Includes both patches. Can you confirm this fixes your issues ?
Comment 9 Vittorio 2015-09-12 05:31:28 UTC
Yes, I'll look into the new patch.

I remind you that there are several places where a left shift is undefined because it does not fit in its type, usually 'int'', as in

source3/smbd/process.c:290:2: runtime error: left shift of 56321 by 16 places cannot be represented in type 'int

source4/heimdal/lib/hcrypto/des.c:337:18: runtime error: left shift of 169 by 24 places cannot be represented in type 'int'

source3/lib/util.c:211:2: runtime error: left shift of 46336 by 16 places cannot be represented in type 'int'

source3/locking/posix.c:107:21: runtime error: left shift of 4611686018427387904 by 1 places cannot be represented in type 'long int'

lib/crypto/md4.c:115:20: runtime error: left shift of 175 by 24 places cannot be represented in type 'int'

libcli/smb/smbXcli_base.c:3072:2: runtime error: left shift of 36869 by 16 places cannot be represented in type 'int'

source3/smbd/trans2.c:3394:2: runtime error: left shift of 1090422573 by 16 places cannot be represented in type 'int'

source3/lib/sysquotas_linux.c:321:24: runtime error: left shift of 8388615 by 8 places cannot be represented in type 'int'

libcli/smb/smb_seal.c:59:2: runtime error: left shift of 54272 by 16 places cannot be represented in type 'int'

source4/smb_server/smb/reply.c:877:36: runtime error: left shift of 65534 by 16 places cannot be represented in type 'int'

These are on version 4.2.3
Comment 10 Jeremy Allison 2019-01-16 17:58:55 UTC
Created attachment 14778 [details]
git-am fix for 4.9.next, 4.8.next cherry-picked from master.

Applies cleanly to 4.9.next, 4.8.next.
Comment 11 David Disseldorp 2019-01-17 12:11:55 UTC
Comment on attachment 14778 [details]
git-am fix for 4.9.next, 4.8.next cherry-picked from master.

Looks good.
Comment 12 David Disseldorp 2019-01-17 12:14:58 UTC
@Karo: please merge for maintenance branches.
Comment 13 Karolin Seeger 2019-01-18 10:51:35 UTC
(In reply to David Disseldorp from comment #12)
Pushed to autobuild-v4-{9,8}-test.
Comment 14 Karolin Seeger 2019-02-05 14:16:28 UTC
(In reply to Karolin Seeger from comment #13)
Pushed to both branches.
Closing out bug report.

Thanks!