Commit a0c9a8e9 authored by Martin Blix Grydeland's avatar Martin Blix Grydeland

Create and use a smp_signspace structure to have range checking on the

growing signed data structures.
parent 47f4078d
......@@ -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 */
......
......@@ -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);
......
......@@ -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
......
......@@ -178,6 +178,64 @@ smp_new_sign(const struct smp_sc *sc, struct smp_signctx *ctx,
smp_sync_sign(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.
*
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment