The branch, master has been updated via edad945339f librpc/nbt: Avoid reading invalid member of union via 47b6696dcdf librpc:ndr: Fix overflow in ndr_push_expand from 6f073f258f1 s3:rpc_server: Fix double blackslash issue in dfs path
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit edad945339f6401b2566efddd33f47195e2637c3 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Jul 6 10:57:59 2023 +1200 librpc/nbt: Avoid reading invalid member of union WACK packets use the ‘data’ member of the ‘nbt_rdata’ union, but they claim to be a different type — NBT_QTYPE_NETBIOS — than would normally be used with that union member. This means that if rr_type is equal to NBT_QTYPE_NETBIOS, ndr_push_nbt_res_rec() has to guess which type the structure really is by examining the data member. However, if the structure is actually of a different type, that union member will not be valid and accessing it will invoke undefined behaviour. To fix this, eliminate all the guesswork and introduce a new type, NBT_QTYPE_WACK, which can never appear on the wire, and which indicates that although the ‘data’ union member should be used, the wire type is actually NBT_QTYPE_NETBIOS. This means that as far as NDR is concerned, the ‘netbios’ member of the ‘nbt_rdata’ union will consistently be used for all NBT_QTYPE_NETBIOS structures; we shall no longer access the wrong member of the union. Credit to OSS-Fuzz. REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=38480 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15019 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Autobuild-User(master): Douglas Bagnall <dbagn...@samba.org> Autobuild-Date(master): Fri Jul 7 01:14:06 UTC 2023 on atb-devel-224 commit 47b6696dcdfe7c5cb6e58ac6586ba45d39c39cc6 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Jul 6 10:50:05 2023 +1200 librpc:ndr: Fix overflow in ndr_push_expand If ‘size’ was equal to UINT32_MAX, the expression ‘size+1’ could overflow to zero. This could result in inadequate memory being allocated, which could cause ndr_pull_compression_xpress_huff_raw_chunk() to overflow memory with zero bytes. Credit to OSS-Fuzz. REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=57728 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15415 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: libcli/nbt/nbtname.c | 20 +++----------------- librpc/idl/nbt.idl | 18 +++++++++--------- librpc/ndr/ndr.c | 3 +++ source4/nbt_server/packet.c | 2 +- 4 files changed, 16 insertions(+), 27 deletions(-) Changeset truncated at 500 lines: diff --git a/libcli/nbt/nbtname.c b/libcli/nbt/nbtname.c index ec2b395d681..c4f2524021f 100644 --- a/libcli/nbt/nbtname.c +++ b/libcli/nbt/nbtname.c @@ -478,23 +478,9 @@ _PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, talloc_free(s); } -_PUBLIC_ enum ndr_err_code ndr_push_nbt_res_rec(struct ndr_push *ndr, int ndr_flags, const struct nbt_res_rec *r) +_PUBLIC_ enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r) { - { - uint32_t _flags_save_STRUCT = ndr->flags; - ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); - if (ndr_flags & NDR_SCALARS) { - NDR_CHECK(ndr_push_align(ndr, 4)); - NDR_CHECK(ndr_push_nbt_name(ndr, NDR_SCALARS, &r->name)); - NDR_CHECK(ndr_push_nbt_qtype(ndr, NDR_SCALARS, r->rr_type)); - NDR_CHECK(ndr_push_nbt_qclass(ndr, NDR_SCALARS, r->rr_class)); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ttl)); - NDR_CHECK(ndr_push_set_switch_value(ndr, &r->rdata, ((((r->rr_type) == NBT_QTYPE_NETBIOS) && ((r->rdata).data.length == 2))?0:r->rr_type))); - NDR_CHECK(ndr_push_nbt_rdata(ndr, NDR_SCALARS, &r->rdata)); - } - if (ndr_flags & NDR_BUFFERS) { - } - ndr->flags = _flags_save_STRUCT; - } + /* For WACK replies, we need to send NBT_QTYPE_NETBIOS on the wire. */ + NDR_CHECK(ndr_push_enum_uint16(ndr, NDR_SCALARS, (r == NBT_QTYPE_WACK) ? NBT_QTYPE_NETBIOS : r)); return NDR_ERR_SUCCESS; } diff --git a/librpc/idl/nbt.idl b/librpc/idl/nbt.idl index fd56c46bb5e..11814e7970e 100644 --- a/librpc/idl/nbt.idl +++ b/librpc/idl/nbt.idl @@ -79,12 +79,18 @@ interface nbt NBT_QCLASS_IP = 0x01 } nbt_qclass; - typedef [public,enum16bit] enum { + typedef [public,enum16bit,nopush] enum { NBT_QTYPE_ADDRESS = 0x0001, NBT_QTYPE_NAMESERVICE = 0x0002, NBT_QTYPE_NULL = 0x000A, NBT_QTYPE_NETBIOS = 0x0020, - NBT_QTYPE_STATUS = 0x0021 + NBT_QTYPE_STATUS = 0x0021, + /* + * Indicates that this is a WACK packet. As long as the size of + * ‘int’ is larger than 16 bits, this value cannot appear on the + * wire. We’ll encode it instead as NBT_QTYPE_NETBIOS. + */ + NBT_QTYPE_WACK = -1 } nbt_qtype; typedef struct { @@ -168,13 +174,7 @@ interface nbt [default] nbt_rdata_data data; } nbt_rdata; -/* - * this macro works around the problem - * that we need to use nbt_rdata_data - * together with NBT_QTYPE_NETBIOS - * for WACK replies - */ - typedef [flag(LIBNDR_PRINT_ARRAY_HEX),nopush] struct { + typedef [flag(LIBNDR_PRINT_ARRAY_HEX)] struct { nbt_name name; nbt_qtype rr_type; nbt_qclass rr_class; diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 44cf524867d..d187a0d0110 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -286,6 +286,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_ } ndr->alloc_size += NDR_BASE_MARSHALL_SIZE; + if (size == UINT32_MAX) { + return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand"); + } if (size+1 > ndr->alloc_size) { ndr->alloc_size = size+1; } diff --git a/source4/nbt_server/packet.c b/source4/nbt_server/packet.c index b9aea56d3d2..1305d6546c5 100644 --- a/source4/nbt_server/packet.c +++ b/source4/nbt_server/packet.c @@ -368,7 +368,7 @@ void nbtd_wack_reply(struct nbt_name_socket *nbtsock, if (packet->answers == NULL) goto failed; packet->answers[0].name = *name; - packet->answers[0].rr_type = NBT_QTYPE_NETBIOS; + packet->answers[0].rr_type = NBT_QTYPE_WACK; packet->answers[0].rr_class = NBT_QCLASS_IP; packet->answers[0].ttl = ttl; packet->answers[0].rdata.data.length = 2; -- Samba Shared Repository