mirror of
https://github.com/nginx/nginx.git
synced 2026-10-25 23:20:04 -05:00
Access log: buffer overrun protection.
Similarly to generic script operations, access log script copy operations now check if there is enough room in the buffer. Signed-off-by: Roman Arutyunyan <arut@nginx.com> Origin: <https://freenginx.org/hg/nginx/rev/ceff7ca7785a>
This commit is contained in:
1 parent
b767540492
commit
4d32a2703c
2 files changed
+235
-51
No files matched your search
@@ -17,7 +17,7 @@
|
||||
typedef struct ngx_stream_log_op_s ngx_stream_log_op_t;
|
||||
|
||||
typedef u_char *(*ngx_stream_log_op_run_pt) (ngx_stream_session_t *s,
|
||||
u_char *buf, ngx_stream_log_op_t *op);
|
||||
u_char *buf, u_char *end, ngx_stream_log_op_t *op);
|
||||
|
||||
typedef size_t (*ngx_stream_log_op_getlen_pt) (ngx_stream_session_t *s,
|
||||
uintptr_t data);
|
||||
@@ -115,16 +115,19 @@ static ngx_int_t ngx_stream_log_variable_compile(ngx_conf_t *cf,
|
||||
static size_t ngx_stream_log_variable_getlen(ngx_stream_session_t *s,
|
||||
uintptr_t data);
|
||||
static u_char *ngx_stream_log_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_op_t *op);
|
||||
u_char *end, ngx_stream_log_op_t *op);
|
||||
static uintptr_t ngx_stream_log_escape(u_char *dst, u_char *src, size_t size);
|
||||
static size_t ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s,
|
||||
uintptr_t data);
|
||||
static u_char *ngx_stream_log_json_variable(ngx_stream_session_t *s,
|
||||
u_char *buf, ngx_stream_log_op_t *op);
|
||||
u_char *buf, u_char *end, ngx_stream_log_op_t *op);
|
||||
static size_t ngx_stream_log_unescaped_variable_getlen(ngx_stream_session_t *s,
|
||||
uintptr_t data);
|
||||
static u_char *ngx_stream_log_unescaped_variable(ngx_stream_session_t *s,
|
||||
u_char *buf, ngx_stream_log_op_t *op);
|
||||
u_char *buf, u_char *end, ngx_stream_log_op_t *op);
|
||||
|
||||
static ngx_int_t ngx_stream_log_check_length(ngx_stream_session_t *s,
|
||||
u_char *buf, u_char *end, size_t len);
|
||||
|
||||
|
||||
static void *ngx_stream_log_create_main_conf(ngx_conf_t *cf);
|
||||
@@ -200,7 +203,7 @@ ngx_module_t ngx_stream_log_module = {
|
||||
static ngx_int_t
|
||||
ngx_stream_log_handler(ngx_stream_session_t *s)
|
||||
{
|
||||
u_char *line, *p;
|
||||
u_char *line, *p, *end;
|
||||
size_t len, size;
|
||||
ssize_t n;
|
||||
ngx_str_t val;
|
||||
@@ -257,6 +260,8 @@ ngx_stream_log_handler(ngx_stream_session_t *s)
|
||||
}
|
||||
}
|
||||
|
||||
len += NGX_LINEFEED_SIZE;
|
||||
|
||||
if (log[l].syslog_peer) {
|
||||
|
||||
/* length of syslog's PRI and HEADER message parts */
|
||||
@@ -267,8 +272,6 @@ ngx_stream_log_handler(ngx_stream_session_t *s)
|
||||
goto alloc_line;
|
||||
}
|
||||
|
||||
len += NGX_LINEFEED_SIZE;
|
||||
|
||||
buffer = log[l].file ? log[l].file->data : NULL;
|
||||
|
||||
if (buffer) {
|
||||
@@ -284,13 +287,18 @@ ngx_stream_log_handler(ngx_stream_session_t *s)
|
||||
if (len <= (size_t) (buffer->last - buffer->pos)) {
|
||||
|
||||
p = buffer->pos;
|
||||
end = p + len - NGX_LINEFEED_SIZE;
|
||||
|
||||
if (buffer->event && p == buffer->start) {
|
||||
ngx_add_timer(buffer->event, buffer->flush);
|
||||
}
|
||||
|
||||
for (i = 0; i < log[l].format->ops->nelts; i++) {
|
||||
p = op[i].run(s, p, &op[i]);
|
||||
for (i = 0; i < log[l].format->ops->nelts && p; i++) {
|
||||
p = op[i].run(s, p, end, &op[i]);
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_linefeed(p);
|
||||
@@ -313,13 +321,18 @@ ngx_stream_log_handler(ngx_stream_session_t *s)
|
||||
}
|
||||
|
||||
p = line;
|
||||
end = p + len - NGX_LINEFEED_SIZE;
|
||||
|
||||
if (log[l].syslog_peer) {
|
||||
p = ngx_syslog_add_header(log[l].syslog_peer, line);
|
||||
}
|
||||
|
||||
for (i = 0; i < log[l].format->ops->nelts; i++) {
|
||||
p = op[i].run(s, p, &op[i]);
|
||||
for (i = 0; i < log[l].format->ops->nelts && p; i++) {
|
||||
p = op[i].run(s, p, end, &op[i]);
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (log[l].syslog_peer) {
|
||||
@@ -663,7 +676,7 @@ ngx_stream_log_flush_handler(ngx_event_t *ev)
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_stream_log_copy_short(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_copy_short(ngx_stream_session_t *s, u_char *buf, u_char *end,
|
||||
ngx_stream_log_op_t *op)
|
||||
{
|
||||
size_t len;
|
||||
@@ -672,6 +685,10 @@ ngx_stream_log_copy_short(ngx_stream_session_t *s, u_char *buf,
|
||||
len = op->len;
|
||||
data = op->data;
|
||||
|
||||
if (ngx_stream_log_check_length(s, buf, end, len) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
*buf++ = (u_char) (data & 0xff);
|
||||
data >>= 8;
|
||||
@@ -682,9 +699,13 @@ ngx_stream_log_copy_short(ngx_stream_session_t *s, u_char *buf,
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_stream_log_copy_long(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_copy_long(ngx_stream_session_t *s, u_char *buf, u_char *end,
|
||||
ngx_stream_log_op_t *op)
|
||||
{
|
||||
if (ngx_stream_log_check_length(s, buf, end, op->len) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, (u_char *) op->data, op->len);
|
||||
}
|
||||
|
||||
@@ -745,22 +766,39 @@ ngx_stream_log_variable_getlen(ngx_stream_session_t *s, uintptr_t data)
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_stream_log_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_variable(ngx_stream_session_t *s, u_char *buf, u_char *end,
|
||||
ngx_stream_log_op_t *op)
|
||||
{
|
||||
uintptr_t len;
|
||||
ngx_stream_variable_value_t *value;
|
||||
|
||||
value = ngx_stream_get_indexed_variable(s, op->data);
|
||||
|
||||
if (value == NULL || value->not_found) {
|
||||
if (ngx_stream_log_check_length(s, buf, end, 1) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*buf = '-';
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
if (value->escape == 0) {
|
||||
if (ngx_stream_log_check_length(s, buf, end, value->len) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, value->data, value->len);
|
||||
|
||||
} else {
|
||||
len = ngx_stream_log_escape(NULL, value->data, value->len);
|
||||
|
||||
if (ngx_stream_log_check_length(s, buf, end, value->len + len * 3)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (u_char *) ngx_stream_log_escape(buf, value->data, value->len);
|
||||
}
|
||||
}
|
||||
@@ -847,9 +885,10 @@ ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s, uintptr_t data)
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_stream_log_json_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_json_variable(ngx_stream_session_t *s, u_char *buf, u_char *end,
|
||||
ngx_stream_log_op_t *op)
|
||||
{
|
||||
uintptr_t len;
|
||||
ngx_stream_variable_value_t *value;
|
||||
|
||||
value = ngx_stream_get_indexed_variable(s, op->data);
|
||||
@@ -859,9 +898,21 @@ ngx_stream_log_json_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
}
|
||||
|
||||
if (value->escape == 0) {
|
||||
if (ngx_stream_log_check_length(s, buf, end, value->len) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, value->data, value->len);
|
||||
|
||||
} else {
|
||||
len = ngx_escape_json(NULL, value->data, value->len);
|
||||
|
||||
if (ngx_stream_log_check_length(s, buf, end, value->len + len)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (u_char *) ngx_escape_json(buf, value->data, value->len);
|
||||
}
|
||||
}
|
||||
@@ -887,7 +938,7 @@ ngx_stream_log_unescaped_variable_getlen(ngx_stream_session_t *s,
|
||||
|
||||
static u_char *
|
||||
ngx_stream_log_unescaped_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
ngx_stream_log_op_t *op)
|
||||
u_char *end, ngx_stream_log_op_t *op)
|
||||
{
|
||||
ngx_stream_variable_value_t *value;
|
||||
|
||||
@@ -897,10 +948,28 @@ ngx_stream_log_unescaped_variable(ngx_stream_session_t *s, u_char *buf,
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (ngx_stream_log_check_length(s, buf, end, value->len) != NGX_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, value->data, value->len);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_stream_log_check_length(ngx_stream_session_t *s, u_char *buf, u_char *end,
|
||||
size_t len)
|
||||
{
|
||||
if (end - buf < (ssize_t) len) {
|
||||
ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0,
|
||||
"no buffer space in log script copy");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_stream_log_create_main_conf(ngx_conf_t *cf)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user