From 240754ccee1b6b35ac47862be56dacec11e65b32 Mon Sep 17 00:00:00 2001
From: Dmitrijs Goloscapovs <dmitrijs.goloscapovs@zabbix.com>
Date: Thu, 27 Jul 2023 11:23:54 +0000
Subject: [PATCH] .......PS. [DEV-2387] added new limits for JS objects

Merge in ZBX/zabbix from feature/DEV-2387-6.0 to release/6.0

* commit '16e5f15a70cfbf00c646cb92d1fcb8a362900285':
  .......PS. [DEV-2387] removed logsize check based on json buffer
  .......PS. [DEV-2387] removed logsize check based on json buffer
  .......PS. [DEV-2387] fixed pr comments
  .......PS. [DEV-2387] removed useless include
  .......PS. [DEV-2387] added limits for logging and adding httprequest headers
  .......PS. [DEV-2387] limited initialization of new HttpRequest objects

CVE: CVE-2023-29449

Upstream-Status: Backport [https://git.zabbix.com/projects/ZBX/repos/zabbix/commits/240754ccee1]

Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
---
 src/libs/zbxembed/console.c     | 23 ++++++++++++-----------
 src/libs/zbxembed/embed.c       |  1 +
 src/libs/zbxembed/embed.h       |  3 +++
 src/libs/zbxembed/httprequest.c | 28 ++++++++++++++++++++++++++++
 src/libs/zbxembed/zabbix.c      | 23 ++++++++++++-----------
 5 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/src/libs/zbxembed/console.c b/src/libs/zbxembed/console.c
index c733487..60c48fc 100644
--- a/src/libs/zbxembed/console.c
+++ b/src/libs/zbxembed/console.c
@@ -90,27 +90,28 @@ static duk_ret_t	es_log_message(duk_context *ctx, int level)
	else
		msg_output = zbx_strdup(msg_output, "undefined");

-	zabbix_log(level, "%s", msg_output);
-
	duk_get_memory_functions(ctx, &out_funcs);
	env = (zbx_es_env_t *)out_funcs.udata;

-	if (NULL == env->json)
-		goto out;
-
-	if (ZBX_ES_LOG_MEMORY_LIMIT < env->json->buffer_size)	/* approximate limit */
+	if (ZBX_ES_LOG_MEMORY_LIMIT < env->log_size)
	{
		err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "log exceeds the maximum size of "
				ZBX_FS_UI64 " bytes.", ZBX_ES_LOG_MEMORY_LIMIT);
		goto out;
	}

-	zbx_json_addobject(env->json, NULL);
-	zbx_json_adduint64(env->json, "level", (zbx_uint64_t)level);
-	zbx_json_adduint64(env->json, "ms", zbx_get_duration_ms(&env->start_time));
-	zbx_json_addstring(env->json, "message", msg_output, ZBX_JSON_TYPE_STRING);
-	zbx_json_close(env->json);
+	zabbix_log(level, "%s", msg_output);
+
+	if (NULL != env->json)
+	{
+		zbx_json_addobject(env->json, NULL);
+		zbx_json_adduint64(env->json, "level", (zbx_uint64_t)level);
+		zbx_json_adduint64(env->json, "ms", zbx_get_duration_ms(&env->start_time));
+		zbx_json_addstring(env->json, "message", msg_output, ZBX_JSON_TYPE_STRING);
+		zbx_json_close(env->json);
+	}
 out:
+	env->log_size += strlen(msg_output);
	zbx_free(msg_output);

	if (-1 != err_index)
diff --git a/src/libs/zbxembed/embed.c b/src/libs/zbxembed/embed.c
index 34d8d18..cc80925 100644
--- a/src/libs/zbxembed/embed.c
+++ b/src/libs/zbxembed/embed.c
@@ -444,6 +444,7 @@ int	zbx_es_execute(zbx_es_t *es, const char *script, const char *code, int size,
	zabbix_log(LOG_LEVEL_DEBUG, "In %s() param:%s", __func__, param);

	zbx_timespec(&es->env->start_time);
+	es->env->http_req_objects = 0;

	if (NULL != es->env->json)
	{
diff --git a/src/libs/zbxembed/embed.h b/src/libs/zbxembed/embed.h
index a0a360c..2b954a8 100644
--- a/src/libs/zbxembed/embed.h
+++ b/src/libs/zbxembed/embed.h
@@ -48,6 +48,9 @@ struct zbx_es_env
	struct zbx_json	*json;

	jmp_buf		loc;
+
+	int		http_req_objects;
+	size_t		log_size;
 };

 zbx_es_env_t	*zbx_es_get_env(duk_context *ctx);
diff --git a/src/libs/zbxembed/httprequest.c b/src/libs/zbxembed/httprequest.c
index 8c2839c..7f0eed9 100644
--- a/src/libs/zbxembed/httprequest.c
+++ b/src/libs/zbxembed/httprequest.c
@@ -52,6 +52,7 @@ typedef struct
	size_t			headers_in_alloc;
	size_t			headers_in_offset;
	unsigned char		custom_header;
+	size_t			headers_sz;
 }
 zbx_es_httprequest_t;

@@ -145,13 +146,21 @@ static duk_ret_t	es_httprequest_dtor(duk_context *ctx)
  ******************************************************************************/
 static duk_ret_t	es_httprequest_ctor(duk_context *ctx)
 {
+#define MAX_HTTPREQUEST_OBJECT_COUNT	10
	zbx_es_httprequest_t	*request;
	CURLcode		err;
+	zbx_es_env_t		*env;
	int			err_index = -1;

	if (!duk_is_constructor_call(ctx))
		return DUK_RET_TYPE_ERROR;

+	if (NULL == (env = zbx_es_get_env(ctx)))
+		return duk_error(ctx, DUK_RET_TYPE_ERROR, "cannot access internal environment");
+
+	if (MAX_HTTPREQUEST_OBJECT_COUNT == env->http_req_objects)
+		return duk_error(ctx, DUK_RET_EVAL_ERROR, "maximum count of HttpRequest objects was reached");
+
	duk_push_this(ctx);

	request = (zbx_es_httprequest_t *)zbx_malloc(NULL, sizeof(zbx_es_httprequest_t));
@@ -189,7 +198,10 @@ out:
		return duk_throw(ctx);
	}

+	env->http_req_objects++;
+
	return 0;
+#undef MAX_HTTPREQUEST_OBJECT_COUNT
 }

 /******************************************************************************
@@ -201,10 +213,12 @@ out:
  ******************************************************************************/
 static duk_ret_t	es_httprequest_add_header(duk_context *ctx)
 {
+#define ZBX_ES_MAX_HEADERS_SIZE	ZBX_KIBIBYTE * 128
	zbx_es_httprequest_t	*request;
	CURLcode		err;
	char			*utf8 = NULL;
	int			err_index = -1;
+	size_t			header_sz;

	if (NULL == (request = es_httprequest(ctx)))
		return duk_error(ctx, DUK_RET_EVAL_ERROR, "internal scripting error: null object");
@@ -215,9 +229,20 @@ static duk_ret_t	es_httprequest_add_header(duk_context *ctx)
		goto out;
	}

+	header_sz = strlen(utf8);
+
+	if (ZBX_ES_MAX_HEADERS_SIZE < request->headers_sz + header_sz)
+	{
+		err_index = duk_push_error_object(ctx, DUK_RET_TYPE_ERROR, "headers exceeded maximum size of "
+			ZBX_FS_UI64 " bytes.", ZBX_ES_MAX_HEADERS_SIZE);
+
+		goto out;
+	}
+
	request->headers = curl_slist_append(request->headers, utf8);
	ZBX_CURL_SETOPT(ctx, request->handle, CURLOPT_HTTPHEADER, request->headers, err);
	request->custom_header = 1;
+	request->headers_sz += header_sz + 1;
 out:
	zbx_free(utf8);

@@ -225,6 +250,7 @@ out:
		return duk_throw(ctx);

	return 0;
+#undef ZBX_ES_MAX_HEADERS_SIZE
 }

 /******************************************************************************
@@ -244,6 +270,7 @@ static duk_ret_t	es_httprequest_clear_header(duk_context *ctx)
	curl_slist_free_all(request->headers);
	request->headers = NULL;
	request->custom_header = 0;
+	request->headers_sz = 0;

	return 0;
 }
@@ -311,6 +338,7 @@ static duk_ret_t	es_httprequest_query(duk_context *ctx, const char *http_request
		{
			curl_slist_free_all(request->headers);
			request->headers = NULL;
+			request->headers_sz = 0;
		}

		if (NULL != contents)
diff --git a/src/libs/zbxembed/zabbix.c b/src/libs/zbxembed/zabbix.c
index 820768f..0ecde86 100644
--- a/src/libs/zbxembed/zabbix.c
+++ b/src/libs/zbxembed/zabbix.c
@@ -81,27 +81,28 @@ static duk_ret_t	es_zabbix_log(duk_context *ctx)
		zbx_replace_invalid_utf8(message);
	}

-	zabbix_log(level, "%s", message);
-
	duk_get_memory_functions(ctx, &out_funcs);
	env = (zbx_es_env_t *)out_funcs.udata;

-	if (NULL == env->json)
-		goto out;
-
-	if (ZBX_ES_LOG_MEMORY_LIMIT < env->json->buffer_size)	/* approximate limit */
+	if (ZBX_ES_LOG_MEMORY_LIMIT < env->log_size)
	{
		err_index = duk_push_error_object(ctx, DUK_RET_EVAL_ERROR, "log exceeds the maximum size of "
				ZBX_FS_UI64 " bytes.", ZBX_ES_LOG_MEMORY_LIMIT);
		goto out;
	}

-	zbx_json_addobject(env->json, NULL);
-	zbx_json_adduint64(env->json, "level", (zbx_uint64_t)level);
-	zbx_json_adduint64(env->json, "ms", zbx_get_duration_ms(&env->start_time));
-	zbx_json_addstring(env->json, "message", message, ZBX_JSON_TYPE_STRING);
-	zbx_json_close(env->json);
+	zabbix_log(level, "%s", message);
+
+	if (NULL != env->json)
+	{
+		zbx_json_addobject(env->json, NULL);
+		zbx_json_adduint64(env->json, "level", (zbx_uint64_t)level);
+		zbx_json_adduint64(env->json, "ms", zbx_get_duration_ms(&env->start_time));
+		zbx_json_addstring(env->json, "message", message, ZBX_JSON_TYPE_STRING);
+		zbx_json_close(env->json);
+	}
 out:
+	env->log_size += strlen(message);
	zbx_free(message);

	if (-1 != err_index)
--
2.35.5
