summaryrefslogtreecommitdiff
path: root/librpc
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2021-05-22 18:40:13 +1200
committerDouglas Bagnall <dbagnall@samba.org>2021-06-02 03:56:36 +0000
commit3bc680c1e38bef75d5b212992e15f094c523923b (patch)
treee49d92cfa4079786a243329868a80d86a7916ad0 /librpc
parenta7d4f93cfdee0a2005be11880f8dd31f55149369 (diff)
downloadsamba-3bc680c1e38bef75d5b212992e15f094c523923b.tar.gz
pidl: Avoid leaving array_size NDR tokens around
In many cases these can and should be consumed as soon as they are used. This is not a complete fix, we don't clean up the array_size token after using it split between an NDR_SCALARS and an NDR_BUFFERS pass, but it is much better than it was and helps the winbind case with a large number of groups (eg 100,000) as otherwise we hit the 65535 NDR token limit. (This is an arbitary Samba-only limit to avoid DoS conditions) BUG: https://bugzilla.samba.org/show_bug.cgi?id=14710 Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Diffstat (limited to 'librpc')
-rw-r--r--librpc/ABI/ndr-2.0.0.sigs2
-rw-r--r--librpc/ndr/libndr.h2
-rw-r--r--librpc/ndr/ndr.c28
-rw-r--r--librpc/ndr/ndr_negoex.c8
-rw-r--r--librpc/ndr/ndr_spoolss_buf.c2
5 files changed, 36 insertions, 6 deletions
diff --git a/librpc/ABI/ndr-2.0.0.sigs b/librpc/ABI/ndr-2.0.0.sigs
index dbd65360eb8..aefe5aae64b 100644
--- a/librpc/ABI/ndr-2.0.0.sigs
+++ b/librpc/ABI/ndr-2.0.0.sigs
@@ -20,6 +20,7 @@ ndr_check_array_size: enum ndr_err_code (struct ndr_pull *, const void *, uint32
ndr_check_padding: void (struct ndr_pull *, size_t)
ndr_check_pipe_chunk_trailer: enum ndr_err_code (struct ndr_pull *, int, uint32_t)
ndr_check_steal_array_length: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t)
+ndr_check_steal_array_size: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t)
ndr_check_string_terminator: enum ndr_err_code (struct ndr_pull *, uint32_t, uint32_t)
ndr_get_array_length: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
ndr_get_array_size: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
@@ -250,6 +251,7 @@ ndr_size_struct: size_t (const void *, int, ndr_push_flags_fn_t)
ndr_size_union: size_t (const void *, int, uint32_t, ndr_push_flags_fn_t)
ndr_size_winreg_Data_GPO: size_t (const union winreg_Data_GPO *, uint32_t, int)
ndr_steal_array_length: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
+ndr_steal_array_size: enum ndr_err_code (struct ndr_pull *, const void *, uint32_t *)
ndr_string_array_size: size_t (struct ndr_push *, const char *)
ndr_string_length: uint32_t (const void *, uint32_t)
ndr_syntax_id_buf_string: char *(const struct ndr_syntax_id *, struct ndr_syntax_id_buf *)
diff --git a/librpc/ndr/libndr.h b/librpc/ndr/libndr.h
index 58b04e98371..8a0b072d800 100644
--- a/librpc/ndr/libndr.h
+++ b/librpc/ndr/libndr.h
@@ -656,7 +656,9 @@ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list, const void *ke
enum ndr_err_code ndr_token_peek(struct ndr_token_list *list, const void *key, uint32_t *v);
enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p);
enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size);
+enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size);
enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size);
+enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size);
enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p);
enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length);
enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length);
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index eaeb3b0e094..031e02a22da 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -1098,8 +1098,34 @@ _PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *
}
/*
- check the stored array size field
+ get and remove from the stored list the stored array size field
*/
+_PUBLIC_ enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
+{
+ return ndr_token_retrieve(&ndr->array_size_list, p, size);
+}
+
+/*
+ * check the stored array size field and remove from the stored list
+ * (the array_size NDR token list). We try to remove when possible to
+ * avoid the list growing towards the bounds check
+ */
+_PUBLIC_ enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
+{
+ uint32_t stored;
+ NDR_CHECK(ndr_steal_array_size(ndr, p, &stored));
+ if (stored != size) {
+ return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
+ "Bad array size - got %u expected %u\n",
+ stored, size);
+ }
+ return NDR_ERR_SUCCESS;
+}
+
+/*
+ * check the stored array size field (leaving it on the array_size
+ * token list)
+ */
_PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
{
uint32_t stored;
diff --git a/librpc/ndr/ndr_negoex.c b/librpc/ndr/ndr_negoex.c
index 95adce5a7e3..72c8774ce5c 100644
--- a/librpc/ndr/ndr_negoex.c
+++ b/librpc/ndr/ndr_negoex.c
@@ -99,7 +99,7 @@ enum ndr_err_code ndr_pull_negoex_BYTE_VECTOR(struct ndr_pull *ndr, int ndr_flag
}
#if 0
if (r->blob.data) {
- NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->blob.data, r->blob.length));
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->blob.data, r->blob.length));
}
#endif
}
@@ -179,7 +179,7 @@ enum ndr_err_code ndr_pull_negoex_AUTH_SCHEME_VECTOR(struct ndr_pull *ndr, int n
}
#if 0
if (r->array) {
- NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->array, r->count));
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
}
#endif
}
@@ -265,7 +265,7 @@ enum ndr_err_code ndr_pull_negoex_EXTENSION_VECTOR(struct ndr_pull *ndr, int ndr
}
#if 0
if (r->array) {
- NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->array, r->count));
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
}
#endif
}
@@ -351,7 +351,7 @@ enum ndr_err_code ndr_pull_negoex_ALERT_VECTOR(struct ndr_pull *ndr, int ndr_fla
}
#if 0
if (r->array) {
- NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->array, r->count));
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->array, r->count));
}
#endif
}
diff --git a/librpc/ndr/ndr_spoolss_buf.c b/librpc/ndr/ndr_spoolss_buf.c
index 9b98dd36143..c5fa82cdfde 100644
--- a/librpc/ndr/ndr_spoolss_buf.c
+++ b/librpc/ndr/ndr_spoolss_buf.c
@@ -1227,7 +1227,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_spoolss_DriverInfo101(struct ndr_pull *ndr,
ndr->flags = _flags_save_string;
}
if (r->file_info) {
- NDR_CHECK(ndr_check_array_size(ndr, (void*)&r->file_info, r->file_count));
+ NDR_CHECK(ndr_check_steal_array_size(ndr, (void*)&r->file_info, r->file_count));
}
}
return NDR_ERR_SUCCESS;