Skip to content

Commit

Permalink
feat(proxy-wasm) strengthen host functions context checks
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaultcha committed Nov 16, 2023
1 parent ddb3fa8 commit 4465a70
Show file tree
Hide file tree
Showing 25 changed files with 1,567 additions and 237 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ members = [
"t/lib/proxy-wasm-tests/rust-sdk-ver-zero-one",
"t/lib/proxy-wasm-tests/benchmarks",
"t/lib/proxy-wasm-tests/instance-lifecycle",
"t/lib/proxy-wasm-tests/context-checks",
]
exclude = [
"lib/ngx-wasm-rs",
Expand Down
33 changes: 16 additions & 17 deletions src/common/proxy_wasm/ngx_proxy_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ action2rc(ngx_proxy_wasm_ctx_t *pwctx,
case NGX_HTTP_REWRITE_PHASE:
case NGX_HTTP_ACCESS_PHASE:
case NGX_HTTP_CONTENT_PHASE:
case NGX_WASM_BACKGROUND_PHASE:
ngx_log_debug6(NGX_LOG_DEBUG_WASM, pwctx->log, 0,
"proxy_wasm pausing in \"%V\" phase "
"(filter: %l/%l, step: %d, action: %d, "
Expand Down Expand Up @@ -683,6 +684,7 @@ ngx_proxy_wasm_run_step(ngx_proxy_wasm_exec_t *pwexec,
ngx_int_t rc;
ngx_proxy_wasm_err_e ecode;
ngx_proxy_wasm_action_e action = NGX_PROXY_WASM_ACTION_CONTINUE;
ngx_proxy_wasm_exec_t *out;
ngx_proxy_wasm_ctx_t *pwctx = pwexec->parent;
ngx_proxy_wasm_filter_t *filter = pwexec->filter;
#if (NGX_DEBUG)
Expand All @@ -700,10 +702,12 @@ ngx_proxy_wasm_run_step(ngx_proxy_wasm_exec_t *pwexec,
if (pwexec->ictx == NULL || pwexec->ictx->instance->trapped) {
#endif
ecode = ngx_proxy_wasm_create_context(filter, pwctx, pwexec->id,
pwexec, NULL);
pwexec, &out);
if (ecode != NGX_PROXY_WASM_ERR_NONE) {
return ecode;
}

pwexec = out;
#if 1
}
#endif
Expand Down Expand Up @@ -842,6 +846,9 @@ get_instance(ngx_proxy_wasm_filter_t *filter,

dd("get instance in store: %p", store);

/* store initialized */
ngx_wasm_assert(store->pool);

for (q = ngx_queue_head(&store->busy);
q != ngx_queue_sentinel(&store->busy);
q = ngx_queue_next(q))
Expand Down Expand Up @@ -988,9 +995,6 @@ ngx_proxy_wasm_create_context(ngx_proxy_wasm_filter_t *filter,
ictx = in->ictx;

} else {
/* store initialized */
ngx_wasm_assert(store->pool);

ictx = get_instance(filter, store, log);
if (ictx == NULL) {
goto error;
Expand Down Expand Up @@ -1187,10 +1191,15 @@ ngx_proxy_wasm_create_context(ngx_proxy_wasm_filter_t *filter,

pwexec->started = 1;
}
}

if (out) {
*out = pwexec;
if (out) {
*out = pwexec;
}

} else {
if (out) {
*out = rexec;
}
}

return NGX_PROXY_WASM_ERR_NONE;
Expand Down Expand Up @@ -1245,19 +1254,9 @@ ngx_proxy_wasm_on_done(ngx_proxy_wasm_exec_t *pwexec)
pwexec->index + 1, pwexec->parent->nfilters);

#if 0
/**
* Currently, dispatches are synchronous hence will always
* have been executed when on_done is invoked.
*/
#ifdef NGX_WASM_HTTP
call = pwexec->call;
if (call) {
ngx_log_debug3(NGX_LOG_DEBUG_WASM, pwexec->log, 0,
"proxy_wasm \"%V\" filter (%l/%l) "
"cancelling HTTP dispatch",
pwexec->filter->name, pwexec->index + 1,
pwexec->parent->nfilters);

ngx_http_proxy_wasm_dispatch_destroy(call);

pwexec->call = NULL;
Expand Down
149 changes: 128 additions & 21 deletions src/common/proxy_wasm/ngx_proxy_wasm_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,42 @@ static ngx_int_t ngx_proxy_wasm_hfuncs_no_http(ngx_wavm_instance_t *instance,

static ngx_chain_t *
ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance,
ngx_proxy_wasm_buffer_type_e buf_type, unsigned *none)
ngx_proxy_wasm_buffer_type_e buf_type, unsigned *none, char **trapmsg)
{
#ifdef NGX_WASM_HTTP
ngx_chain_t *cl;
ngx_http_wasm_req_ctx_t *rctx;
ngx_http_request_t *r;
ngx_proxy_wasm_ctx_t *pwctx;
ngx_proxy_wasm_exec_t *pwexec;

rctx = ngx_http_proxy_wasm_get_rctx(instance);
r = rctx->r;
pwexec = ngx_proxy_wasm_instance2pwexec(instance);
pwctx = pwexec->parent;
#endif

switch (buf_type) {

#ifdef NGX_WASM_HTTP
case NGX_PROXY_WASM_BUFFER_HTTP_REQUEST_BODY:

/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_REQ_HEADERS:
case NGX_PROXY_WASM_STEP_REQ_BODY:
case NGX_PROXY_WASM_STEP_LOG:
break;
default:
*trapmsg = "can only get request body during "
"\"on_request_body\", \"on_log\"";
return NULL;
}

/* get */

rctx = ngx_http_proxy_wasm_get_rctx(instance);
r = rctx->r;

if (r->request_body == NULL
|| r->request_body->bufs == NULL)
{
Expand All @@ -61,6 +82,23 @@ ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance,
return r->request_body->bufs;

case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY:

/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_RESP_BODY:
case NGX_PROXY_WASM_STEP_LOG:
break;
default:
*trapmsg = "can only get response body during "
"\"on_response_body\", \"on_log\"";
return NULL;
}

/* get */

rctx = ngx_http_proxy_wasm_get_rctx(instance);

cl = rctx->resp_chunk;
if (cl == NULL) {
/* no body */
Expand All @@ -74,9 +112,21 @@ ngx_proxy_wasm_get_buffer_helper(ngx_wavm_instance_t *instance,
{
ngx_wasm_http_reader_ctx_t *reader;
ngx_http_proxy_wasm_dispatch_t *call;
ngx_proxy_wasm_exec_t *pwexec;

pwexec = ngx_proxy_wasm_instance2pwexec(instance);
/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE:
case NGX_PROXY_WASM_STEP_LOG:
break;
default:
*trapmsg = "can only get dispatch response body during "
"\"on_http_dispatch_response\"";
return NULL;
}

/* get */

call = pwexec->call;
if (call == NULL) {
return NULL;
Expand Down Expand Up @@ -207,11 +257,10 @@ ngx_proxy_wasm_hfuncs_set_tick_period(ngx_wavm_instance_t *instance,
ngx_event_t *ev;
ngx_proxy_wasm_exec_t *rexec = ngx_proxy_wasm_instance2pwexec(instance);

ngx_wasm_assert(rexec->root_id == NGX_PROXY_WASM_ROOT_CTX_ID);

if (rexec->root_id != NGX_PROXY_WASM_ROOT_CTX_ID) {
/* ignore */
return ngx_proxy_wasm_result_ok(rets);
return ngx_proxy_wasm_result_trap(rexec,
"can only set tick_period in "
"root context", rets, NGX_WAVM_OK);
}

if (ngx_exiting) {
Expand Down Expand Up @@ -254,6 +303,7 @@ ngx_proxy_wasm_hfuncs_get_buffer(ngx_wavm_instance_t *instance,
{
size_t offset, max_len, len, chunk_len;
unsigned none = 0;
char *trapmsg = NULL;
u_char *start = NULL;
ngx_chain_t *cl = NULL;
ngx_buf_t *buf;
Expand Down Expand Up @@ -282,8 +332,14 @@ ngx_proxy_wasm_hfuncs_get_buffer(ngx_wavm_instance_t *instance,
break;

default:
cl = ngx_proxy_wasm_get_buffer_helper(instance, buf_type, &none);
cl = ngx_proxy_wasm_get_buffer_helper(instance, buf_type, &none,
&trapmsg);
if (cl == NULL) {
if (trapmsg) {
return ngx_proxy_wasm_result_trap(pwexec, trapmsg,
rets, NGX_WAVM_BAD_USAGE);
}

if (none) {
return ngx_proxy_wasm_result_notfound(rets);
}
Expand Down Expand Up @@ -376,9 +432,10 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance,
ngx_wavm_ptr_t *buf_data;
ngx_http_wasm_req_ctx_t *rctx;
ngx_proxy_wasm_exec_t *pwexec;
ngx_proxy_wasm_ctx_t *pwctx;

rctx = ngx_http_proxy_wasm_get_rctx(instance);
pwexec = ngx_proxy_wasm_instance2pwexec(instance);
pwctx = pwexec->parent;

offset = args[1].of.i32;
max = args[2].of.i32;
Expand All @@ -400,35 +457,64 @@ ngx_proxy_wasm_hfuncs_set_buffer(ngx_wavm_instance_t *instance,

#ifdef NGX_WASM_HTTP
case NGX_PROXY_WASM_BUFFER_HTTP_REQUEST_BODY:

/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_REQ_HEADERS:
case NGX_PROXY_WASM_STEP_REQ_BODY:
break;
default:
return ngx_proxy_wasm_result_trap(pwexec,
"can only set request body "
"during \"on_request_body\"",
rets, NGX_WAVM_BAD_USAGE);
}

/* set */

rctx = ngx_http_proxy_wasm_get_rctx(instance);

ngx_wasm_assert(rctx);

if (offset == 0 && max == 0 && buf_len > 0) {
rc = ngx_http_wasm_prepend_req_body(rctx, &s);

} else {
rc = ngx_http_wasm_set_req_body(rctx, &s, offset, max);
}

if (rc == NGX_ABORT) {
ngx_wasm_assert(rc != NGX_ABORT);
break;

case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY:

/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_RESP_BODY:
break;
default:
return ngx_proxy_wasm_result_trap(pwexec,
"cannot set request body",
"can only set response body "
"during \"on_response_body\"",
rets, NGX_WAVM_BAD_USAGE);
}

break;
/* set */

rctx = ngx_http_proxy_wasm_get_rctx(instance);

ngx_wasm_assert(rctx);

case NGX_PROXY_WASM_BUFFER_HTTP_RESPONSE_BODY:
if (offset == 0 && max == 0 && buf_len > 0) {
rc = ngx_http_wasm_prepend_resp_body(rctx, &s);

} else {
rc = ngx_http_wasm_set_resp_body(rctx, &s, offset, max);
}

if (rc == NGX_ABORT) {
return ngx_proxy_wasm_result_trap(pwexec,
"cannot set response body",
rets, NGX_WAVM_BAD_USAGE);
}

ngx_wasm_assert(rc != NGX_ABORT);
break;
#endif

Expand Down Expand Up @@ -972,12 +1058,33 @@ ngx_proxy_wasm_hfuncs_dispatch_http_call(ngx_wavm_instance_t *instance,
uint32_t *callout_id, timeout;
ngx_str_t host, body;
ngx_proxy_wasm_marshalled_map_t headers, trailers;
ngx_proxy_wasm_ctx_t *pwctx;
ngx_proxy_wasm_exec_t *pwexec;
ngx_http_wasm_req_ctx_t *rctx;
ngx_http_proxy_wasm_dispatch_t *call = NULL;

pwexec = ngx_proxy_wasm_instance2pwexec(instance);
rctx = ngx_http_proxy_wasm_get_rctx(instance);
pwctx = pwexec->parent;

/* check context */

switch (pwctx->step) {
case NGX_PROXY_WASM_STEP_REQ_HEADERS:
case NGX_PROXY_WASM_STEP_REQ_BODY:
case NGX_PROXY_WASM_STEP_TICK:
case NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE:
break;
default:
return ngx_proxy_wasm_result_trap(pwexec,
"can only send HTTP dispatch "
"during "
"\"on_request_headers\", "
"\"on_request_body\", "
"\"on_dispatch_response\", "
"\"on_tick\"",
rets, NGX_WAVM_BAD_USAGE);
}

host.len = args[1].of.i32;
host.data = NGX_WAVM_HOST_LIFT_SLICE(instance, args[0].of.i32, host.len);
Expand Down
12 changes: 11 additions & 1 deletion src/http/proxy_wasm/ngx_http_proxy_wasm_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ ngx_http_proxy_wasm_dispatch(ngx_proxy_wasm_exec_t *pwexec,
/* rctx or fake request */

if (rctx == NULL) {
ngx_wasm_assert(pwexec->in_tick);
ngx_wasm_assert(pwexec->root_id == NGX_PROXY_WASM_ROOT_CTX_ID);
ngx_wasm_assert(pwexec->parent->id == NGX_PROXY_WASM_ROOT_CTX_ID);

Expand Down Expand Up @@ -825,6 +824,11 @@ ngx_http_proxy_wasm_dispatch_resume_handler(ngx_wasm_socket_tcp_t *sock)
/* save step */
step = pwexec->parent->step;

#ifdef NGX_WASM_HTTP
pwexec->parent->phase = ngx_wasm_phase_lookup(&ngx_http_wasm_subsystem,
NGX_WASM_BACKGROUND_PHASE);
#endif

ecode = ngx_proxy_wasm_run_step(pwexec,
NGX_PROXY_WASM_STEP_DISPATCH_RESPONSE);
if (ecode != NGX_PROXY_WASM_ERR_NONE) {
Expand All @@ -838,6 +842,12 @@ ngx_http_proxy_wasm_dispatch_resume_handler(ngx_wasm_socket_tcp_t *sock)
/* resume current step if unfinished */
rc = ngx_proxy_wasm_resume(pwexec->parent, pwexec->parent->phase,
step);
if (rc == NGX_AGAIN) {
goto done;

} else if (rc != NGX_OK) {
goto error;
}

} else {
/* another call was setup during the callback */
Expand Down
Loading

0 comments on commit 4465a70

Please sign in to comment.