[PATCH 02/13] Create and use a smp_signspace structure to have range checking on the growing signed data structures.

Martin Blix Grydeland martin at varnish-software.com
Mon Oct 1 12:26:09 CEST 2012


---
 bin/varnishd/storage/storage_persistent.c      |   23 +++---
 bin/varnishd/storage/storage_persistent.h      |   35 +++++++--
 bin/varnishd/storage/storage_persistent_silo.c |   10 +--
 bin/varnishd/storage/storage_persistent_subr.c |   90 ++++++++++++++++++++----
 4 files changed, 126 insertions(+), 32 deletions(-)

diff --git a/bin/varnishd/storage/storage_persistent.c b/bin/varnishd/storage/storage_persistent.c
index 5d31caf..b54f497 100644
--- a/bin/varnishd/storage/storage_persistent.c
+++ b/bin/varnishd/storage/storage_persistent.c
@@ -68,13 +68,14 @@ static VTAILQ_HEAD(,smp_sc)	silos = VTAILQ_HEAD_INITIALIZER(silos);
  */
 
 static void
-smp_appendban(struct smp_sc *sc, struct smp_signctx *ctx,
+smp_appendban(struct smp_sc *sc, struct smp_signspace *spc,
     uint32_t len, const uint8_t *ban)
 {
 	uint8_t *ptr, *ptr2;
 
 	(void)sc;
-	ptr = ptr2 = SIGN_END(ctx);
+	ptr = ptr2 = SIGNSPACE_FRONT(spc);
+	assert(SIGNSPACE_FREE(spc) >= 4 + 4 + len);
 
 	memcpy(ptr, "BAN", 4);
 	ptr += 4;
@@ -85,7 +86,7 @@ smp_appendban(struct smp_sc *sc, struct smp_signctx *ctx,
 	memcpy(ptr, ban, len);
 	ptr += len;
 
-	smp_append_sign(ctx, ptr2, ptr - ptr2);
+	smp_append_signspace(spc, ptr - ptr2);
 }
 
 /* Trust that cache_ban.c takes care of locking */
@@ -106,7 +107,7 @@ SMP_NewBan(const uint8_t *ban, unsigned ln)
  */
 
 static int
-smp_open_bans(struct smp_sc *sc, struct smp_signctx *ctx)
+smp_open_bans(struct smp_sc *sc, struct smp_signspace *spc)
 {
 	uint8_t *ptr, *pe;
 	uint32_t length;
@@ -114,11 +115,11 @@ smp_open_bans(struct smp_sc *sc, struct smp_signctx *ctx)
 
 	ASSERT_CLI();
 	(void)sc;
-	i = smp_chk_sign(ctx);
+	i = smp_chk_signspace(spc);
 	if (i)
 		return (i);
-	ptr = SIGN_DATA(ctx);
-	pe = ptr + ctx->ss->length;
+	ptr = SIGNSPACE_DATA(spc);
+	pe = SIGNSPACE_FRONT(spc);
 
 	while (ptr < pe) {
 		if (memcmp(ptr, "BAN", 4)) {
@@ -148,7 +149,7 @@ smp_open_bans(struct smp_sc *sc, struct smp_signctx *ctx)
  */
 
 static int
-smp_open_segs(struct smp_sc *sc, struct smp_signctx *ctx)
+smp_open_segs(struct smp_sc *sc, struct smp_signspace *spc)
 {
 	uint64_t length, l;
 	struct smp_segptr *ss, *se;
@@ -156,12 +157,12 @@ smp_open_segs(struct smp_sc *sc, struct smp_signctx *ctx)
 	int i, n = 0;
 
 	ASSERT_CLI();
-	i = smp_chk_sign(ctx);
+	i = smp_chk_signspace(spc);
 	if (i)
 		return (i);
 
-	ss = SIGN_DATA(ctx);
-	length = ctx->ss->length;
+	ss = SIGNSPACE_DATA(spc);
+	length = SIGNSPACE_LEN(spc);
 
 	if (length == 0) {
 		/* No segments */
diff --git a/bin/varnishd/storage/storage_persistent.h b/bin/varnishd/storage/storage_persistent.h
index c817faf..ec97d3e 100644
--- a/bin/varnishd/storage/storage_persistent.h
+++ b/bin/varnishd/storage/storage_persistent.h
@@ -55,6 +55,21 @@ struct smp_signctx {
 	const char		*id;
 };
 
+/*
+ * A space wrapped by a signature
+ *
+ * A signspace is a chunk of the silo that is wrapped by a
+ * signature. It has attributes for size, so range checking can be
+ * performed.
+ *
+ */
+
+struct smp_signspace {
+	struct smp_signctx	ctx;
+	uint8_t			*start;
+	uint64_t		size;
+};
+
 struct smp_sc;
 
 /* XXX: name confusion with on-media version ? */
@@ -116,10 +131,10 @@ struct smp_sc {
 	VTAILQ_ENTRY(smp_sc)	list;
 
 	struct smp_signctx	idn;
-	struct smp_signctx	ban1;
-	struct smp_signctx	ban2;
-	struct smp_signctx	seg1;
-	struct smp_signctx	seg2;
+	struct smp_signspace	ban1;
+	struct smp_signspace	ban2;
+	struct smp_signspace	seg1;
+	struct smp_signspace	seg2;
 
 	struct ban		*tailban;
 
@@ -161,6 +176,11 @@ struct smp_sc {
 #define SIGN_DATA(ctx)	((void *)((ctx)->ss + 1))
 #define SIGN_END(ctx)	((void *)((int8_t *)SIGN_DATA(ctx) + (ctx)->ss->length))
 
+#define SIGNSPACE_DATA(spc)	(SIGN_DATA(&(spc)->ctx))
+#define SIGNSPACE_FRONT(spc)	(SIGN_END(&(spc)->ctx))
+#define SIGNSPACE_LEN(spc)	((spc)->ctx.ss->length)
+#define SIGNSPACE_FREE(spc)	((spc)->size - SIGNSPACE_LEN(spc))
+
 /* storage_persistent_mgt.c */
 
 void smp_mgt_init(struct stevedore *parent, int ac, char * const *av);
@@ -181,6 +201,13 @@ int smp_chk_sign(struct smp_signctx *ctx);
 void smp_append_sign(struct smp_signctx *ctx, const void *ptr, uint32_t len);
 void smp_reset_sign(struct smp_signctx *ctx);
 void smp_sync_sign(const struct smp_signctx *ctx);
+
+void smp_def_signspace(const struct smp_sc *sc, struct smp_signspace *spc,
+		       uint64_t off, uint64_t size, const char *id);
+int smp_chk_signspace(struct smp_signspace *spc);
+void smp_append_signspace(struct smp_signspace *spc, uint32_t len);
+void smp_reset_signspace(struct smp_signspace *spc);
+
 void smp_newsilo(struct smp_sc *sc);
 int smp_valid_silo(struct smp_sc *sc);
 
diff --git a/bin/varnishd/storage/storage_persistent_silo.c b/bin/varnishd/storage/storage_persistent_silo.c
index ff53af8..6ed80d2 100644
--- a/bin/varnishd/storage/storage_persistent_silo.c
+++ b/bin/varnishd/storage/storage_persistent_silo.c
@@ -58,15 +58,15 @@
  */
 
 static void
-smp_save_seg(const struct smp_sc *sc, struct smp_signctx *ctx)
+smp_save_seg(const struct smp_sc *sc, struct smp_signspace *spc)
 {
 	struct smp_segptr *ss;
 	struct smp_seg *sg;
 	uint64_t length;
 
 	Lck_AssertHeld(&sc->mtx);
-	smp_reset_sign(ctx);
-	ss = SIGN_DATA(ctx);
+	smp_reset_signspace(spc);
+	ss = SIGNSPACE_DATA(spc);
 	length = 0;
 	VTAILQ_FOREACH(sg, &sc->segments, list) {
 		assert(sg->p.offset < sc->mediasize);
@@ -75,8 +75,8 @@ smp_save_seg(const struct smp_sc *sc, struct smp_signctx *ctx)
 		ss++;
 		length += sizeof *ss;
 	}
-	smp_append_sign(ctx, SIGN_DATA(ctx), length);
-	smp_sync_sign(ctx);
+	smp_append_signspace(spc, length);
+	smp_sync_sign(&spc->ctx);
 }
 
 void
diff --git a/bin/varnishd/storage/storage_persistent_subr.c b/bin/varnishd/storage/storage_persistent_subr.c
index 004bba3..ac93544 100644
--- a/bin/varnishd/storage/storage_persistent_subr.c
+++ b/bin/varnishd/storage/storage_persistent_subr.c
@@ -179,6 +179,64 @@ smp_new_sign(const struct smp_sc *sc, struct smp_signctx *ctx,
 }
 
 /*--------------------------------------------------------------------
+ * Define a signature space by location, size and identifier
+ */
+
+void
+smp_def_signspace(const struct smp_sc *sc, struct smp_signspace *spc,
+		  uint64_t off, uint64_t size, const char *id)
+{
+	smp_def_sign(sc, &spc->ctx, off, id);
+	spc->start = SIGN_DATA(&spc->ctx);
+	spc->size = size - SMP_SIGN_SPACE;
+}
+
+/*--------------------------------------------------------------------
+ * Check that a signspace's signature space is good, leave state ready
+ * for append
+ */
+
+int
+smp_chk_signspace(struct smp_signspace *spc)
+{
+	return (smp_chk_sign(&spc->ctx));
+}
+
+/*--------------------------------------------------------------------
+ * Append data to a signature space
+ */
+
+void
+smp_append_signspace(struct smp_signspace *spc, uint32_t len)
+{
+	assert(len <= SIGNSPACE_FREE(spc));
+	smp_append_sign(&spc->ctx, SIGNSPACE_FRONT(spc), len);
+}
+
+/*--------------------------------------------------------------------
+ * Reset a signature space to empty, prepare for appending.
+ */
+
+void
+smp_reset_signspace(struct smp_signspace *spc)
+{
+	smp_reset_sign(&spc->ctx);
+}
+
+/*--------------------------------------------------------------------
+ * Create a new signature space and force the signature to backing store.
+ */
+
+static void
+smp_new_signspace(const struct smp_sc *sc, struct smp_signspace *spc,
+		  uint64_t off, uint64_t size, const char *id)
+{
+	smp_new_sign(sc, &spc->ctx, off, id);
+	spc->start = SIGN_DATA(&spc->ctx);
+	spc->size = size - SMP_SIGN_SPACE;
+}
+
+/*--------------------------------------------------------------------
  * Initialize a Silo with a valid but empty structure.
  *
  * XXX: more intelligent sizing of things.
@@ -220,10 +278,14 @@ smp_newsilo(struct smp_sc *sc)
 	si->stuff[SMP_END_STUFF] = si->mediasize;
 	assert(si->stuff[SMP_SPC_STUFF] < si->stuff[SMP_END_STUFF]);
 
-	smp_new_sign(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], "BAN 1");
-	smp_new_sign(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], "BAN 2");
-	smp_new_sign(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], "SEG 1");
-	smp_new_sign(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], "SEG 2");
+	smp_new_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF],
+			  smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1");
+	smp_new_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF],
+			  smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2");
+	smp_new_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF],
+			  smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1");
+	smp_new_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF],
+			  smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2");
 
 	smp_append_sign(&sc->idn, si, sizeof *si);
 	smp_sync_sign(&sc->idn);
@@ -282,20 +344,24 @@ smp_valid_silo(struct smp_sc *sc)
 	assert(smp_stuff_len(sc, SMP_BAN1_STUFF) ==
 	  smp_stuff_len(sc, SMP_BAN2_STUFF));
 
-	smp_def_sign(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], "BAN 1");
-	smp_def_sign(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], "BAN 2");
-	smp_def_sign(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], "SEG 1");
-	smp_def_sign(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], "SEG 2");
+	smp_def_signspace(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF],
+			  smp_stuff_len(sc, SMP_BAN1_STUFF), "BAN 1");
+	smp_def_signspace(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF],
+			  smp_stuff_len(sc, SMP_BAN2_STUFF), "BAN 2");
+	smp_def_signspace(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF],
+			  smp_stuff_len(sc, SMP_SEG1_STUFF), "SEG 1");
+	smp_def_signspace(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF],
+			  smp_stuff_len(sc, SMP_SEG2_STUFF), "SEG 2");
 
 	/* We must have one valid BAN table */
-	i = smp_chk_sign(&sc->ban1);
-	j = smp_chk_sign(&sc->ban2);
+	i = smp_chk_signspace(&sc->ban1);
+	j = smp_chk_signspace(&sc->ban2);
 	if (i && j)
 		return (100 + i * 10 + j);
 
 	/* We must have one valid SEG table */
-	i = smp_chk_sign(&sc->seg1);
-	j = smp_chk_sign(&sc->seg2);
+	i = smp_chk_signspace(&sc->seg1);
+	j = smp_chk_signspace(&sc->seg2);
 	if (i && j)
 		return (200 + i * 10 + j);
 	return (0);
-- 
1.7.9.5




More information about the varnish-dev mailing list