[master] a294c31dd Add a bitmask tracking SUB calls to detect recursions

Nils Goroll nils.goroll at uplex.de
Mon Feb 8 17:52:04 UTC 2021


commit a294c31ddabaf2cc08e92fa09e512233c154f7c1
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Sat Feb 6 15:13:42 2021 +0100

    Add a bitmask tracking SUB calls to detect recursions
    
    To allow dynamic SUB calls, we need to check for recursions at
    runtime, reflecting the compile time recursion check.
    
    We create a bitmask to note each dynamically called SUB by its unique
    number. To check for recursions, we only need to test if the
    respective bit for the sub number is already set.
    
    We only conduct this check if the track_call argument of
    vcl_call_method() is true. By setting this argument to the number of
    SUB references, we enable call tracking only for VCLs with dynamic SUB
    references (when (struct VCL_conf).nsub is non-zero).
    
    VCC already guarantees that static calls are loop free - so loops can
    only be introduced through dynamic SUB references.
    
    Call tracking with a bitmask was suggested by phk

diff --git a/bin/varnishd/cache/cache_vrt_vcl.c b/bin/varnishd/cache/cache_vrt_vcl.c
index 04cc68107..b474ea4e9 100644
--- a/bin/varnishd/cache/cache_vrt_vcl.c
+++ b/bin/varnishd/cache/cache_vrt_vcl.c
@@ -39,9 +39,11 @@
 
 #include "vcl.h"
 #include "vtim.h"
+#include "vbm.h"
 
 #include "cache_director.h"
 #include "cache_vcl.h"
+#include "vcc_interface.h"
 
 /*--------------------------------------------------------------------*/
 
@@ -444,10 +446,13 @@ VRT_VCL_Allow_Discard(struct vclref **refp)
 
 static void
 vcl_call_method(struct worker *wrk, struct req *req, struct busyobj *bo,
-    void *specific, unsigned method, vcl_func_f *func)
+    void *specific, unsigned method, vcl_func_f *func, unsigned track_call)
 {
-	uintptr_t aws;
+	uintptr_t rws = 0, aws;
 	struct vrt_ctx ctx;
+	struct vbitmap *vbm;
+	void *p;
+	size_t sz;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	INIT_OBJ(&ctx, VRT_CTX_MAGIC);
@@ -468,6 +473,15 @@ vcl_call_method(struct worker *wrk, struct req *req, struct busyobj *bo,
 	assert(ctx.now != 0);
 	ctx.specific = specific;
 	ctx.method = method;
+	if (track_call > 0) {
+		rws = WS_Snapshot(wrk->aws);
+		sz = VBITMAP_SZ(track_call);
+		p = WS_Alloc(wrk->aws, sz);
+		// No use to attempt graceful failure, all VCL calls will fail
+		AN(p);
+		vbm = vbit_init(p, sz);
+		ctx.called = vbm;
+	}
 	aws = WS_Snapshot(wrk->aws);
 	wrk->cur_method = method;
 	wrk->seen_methods |= method;
@@ -484,6 +498,8 @@ vcl_call_method(struct worker *wrk, struct req *req, struct busyobj *bo,
 	 * wrk->aws, but they can reserve and return from it.
 	 */
 	assert(aws == WS_Snapshot(wrk->aws));
+	if (rws != 0)
+		WS_Reset(wrk->aws, rws);
 }
 
 #define VCL_MET_MAC(func, upper, typ, bitmap)				\
@@ -496,7 +512,7 @@ VCL_##func##_method(struct vcl *vcl, struct worker *wrk,		\
 	CHECK_OBJ_NOTNULL(vcl->conf, VCL_CONF_MAGIC);			\
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);				\
 	vcl_call_method(wrk, req, bo, specific,				\
-	    VCL_MET_ ## upper, vcl->conf->func##_func);			\
+	    VCL_MET_ ## upper, vcl->conf->func##_func, vcl->conf->nsub);\
 	AN((1U << wrk->handling) & bitmap);				\
 }
 
diff --git a/include/vrt.h b/include/vrt.h
index 1b0765454..c95d0f820 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -332,6 +332,8 @@ struct vrt_ctx {
 	 *    synth+error:	struct vsb *
 	 */
 	void				*specific;
+	/* if present, vbitmap of called subs */
+	void				*called;
 };
 
 #define VRT_CTX		const struct vrt_ctx *ctx


More information about the varnish-commit mailing list