source: bin/varnishd/storage_persistent_subr.c @ e8a63f

Revision e8a63f, 8.5 KB checked in by Poul-Henning Kamp <phk@…>, 3 years ago (diff)

Try to read the silo signature to find the correct address to map
the silo into VM. If this fails or we get garbage, the silo will
be cleared.

Fixes #962

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2008-2011 Varnish Software AS
3 * All rights reserved.
4 *
5 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * Persistent storage method
29 *
30 * XXX: Before we start the client or maybe after it stops, we should give the
31 * XXX: stevedores a chance to examine their storage for consistency.
32 *
33 * XXX: Do we ever free the LRU-lists ?
34 */
35
36#include "config.h"
37
38#include <stdio.h>
39#include <stdlib.h>
40#include <stddef.h>
41#include <sys/mman.h>
42
43#include "cache.h"
44#include "vsha256.h"
45
46#include "persistent.h"
47#include "storage_persistent.h"
48
49/*--------------------------------------------------------------------
50 * SIGNATURE functions
51 * The signature is SHA256 over:
52 *    1. The smp_sign struct up to but not including the length field.
53 *    2. smp_sign->length bytes, starting after the smp_sign structure
54 *    3. The smp-sign->length field.
55 * The signature is stored after the byte-range from step 2.
56 */
57
58/*--------------------------------------------------------------------
59 * Define a signature by location and identifier.
60 */
61
62void
63smp_def_sign(const struct smp_sc *sc, struct smp_signctx *ctx,
64    uint64_t off, const char *id)
65{
66
67        AZ(off & 7);                    /* Alignment */
68        assert(strlen(id) < sizeof ctx->ss->ident);
69
70        memset(ctx, 0, sizeof *ctx);
71        ctx->ss = (void*)(sc->base + off);
72        ctx->unique = sc->unique;
73        ctx->id = id;
74}
75
76/*--------------------------------------------------------------------
77 * Check that a signature is good, leave state ready for append
78 */
79int
80smp_chk_sign(struct smp_signctx *ctx)
81{
82        struct SHA256Context cx;
83        unsigned char sign[SHA256_LEN];
84        int r = 0;
85
86        if (strncmp(ctx->id, ctx->ss->ident, sizeof ctx->ss->ident))
87                r = 1;
88        else if (ctx->unique != ctx->ss->unique)
89                r = 2;
90        else if ((uintptr_t)ctx->ss != ctx->ss->mapped)
91                r = 3;
92        else {
93                SHA256_Init(&ctx->ctx);
94                SHA256_Update(&ctx->ctx, ctx->ss,
95                    offsetof(struct smp_sign, length));
96                SHA256_Update(&ctx->ctx, SIGN_DATA(ctx), ctx->ss->length);
97                cx = ctx->ctx;
98                SHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length));
99                SHA256_Final(sign, &cx);
100                if (memcmp(sign, SIGN_END(ctx), sizeof sign))
101                        r = 4;
102        }
103        if (r) {
104                fprintf(stderr, "CHK(%p %s %p %s) = %d\n",
105                    ctx, ctx->id, ctx->ss,
106                    r > 1 ? ctx->ss->ident : "<invalid>", r);
107        }
108        return (r);
109}
110
111/*--------------------------------------------------------------------
112 * Append data to a signature
113 */
114void
115smp_append_sign(struct smp_signctx *ctx, const void *ptr, uint32_t len)
116{
117        struct SHA256Context cx;
118        unsigned char sign[SHA256_LEN];
119
120        if (len != 0) {
121                SHA256_Update(&ctx->ctx, ptr, len);
122                ctx->ss->length += len;
123        }
124        cx = ctx->ctx;
125        SHA256_Update(&cx, &ctx->ss->length, sizeof(ctx->ss->length));
126        SHA256_Final(sign, &cx);
127        memcpy(SIGN_END(ctx), sign, sizeof sign);
128XXXAZ(smp_chk_sign(ctx));
129}
130
131/*--------------------------------------------------------------------
132 * Reset a signature to empty, prepare for appending.
133 */
134
135void
136smp_reset_sign(struct smp_signctx *ctx)
137{
138
139        memset(ctx->ss, 0, sizeof *ctx->ss);
140        strcpy(ctx->ss->ident, ctx->id);
141        ctx->ss->unique = ctx->unique;
142        ctx->ss->mapped = (uintptr_t)ctx->ss;
143        SHA256_Init(&ctx->ctx);
144        SHA256_Update(&ctx->ctx, ctx->ss,
145            offsetof(struct smp_sign, length));
146        smp_append_sign(ctx, NULL, 0);
147}
148
149/*--------------------------------------------------------------------
150 * Force a write of a signature block to the backing store.
151 */
152
153void
154smp_sync_sign(const struct smp_signctx *ctx)
155{
156        int i;
157
158        /* XXX: round to pages */
159        i = msync((void*)ctx->ss, ctx->ss->length + SHA256_LEN, MS_SYNC);
160        if (i && 0)
161                fprintf(stderr, "SyncSign(%p %s) = %d %s\n",
162                    ctx->ss, ctx->id, i, strerror(errno));
163}
164
165/*--------------------------------------------------------------------
166 * Create and force a new signature to backing store
167 */
168
169static void
170smp_new_sign(const struct smp_sc *sc, struct smp_signctx *ctx,
171    uint64_t off, const char *id)
172{
173        smp_def_sign(sc, ctx, off, id);
174        smp_reset_sign(ctx);
175        smp_sync_sign(ctx);
176}
177
178/*--------------------------------------------------------------------
179 * Initialize a Silo with a valid but empty structure.
180 *
181 * XXX: more intelligent sizing of things.
182 */
183
184void
185smp_newsilo(struct smp_sc *sc)
186{
187        struct smp_ident        *si;
188
189        ASSERT_MGT();
190        assert(strlen(SMP_IDENT_STRING) < sizeof si->ident);
191
192        /* Choose a new random number */
193        sc->unique = random();
194
195        smp_reset_sign(&sc->idn);
196        si = sc->ident;
197
198        memset(si, 0, sizeof *si);
199        strcpy(si->ident, SMP_IDENT_STRING);
200        si->byte_order = 0x12345678;
201        si->size = sizeof *si;
202        si->major_version = 2;
203        si->unique = sc->unique;
204        si->mediasize = sc->mediasize;
205        si->granularity = sc->granularity;
206        /*
207         * Aim for cache-line-width
208         */
209        si->align = sizeof(void*) * 2;
210        sc->align = si->align;
211
212        si->stuff[SMP_BAN1_STUFF] = sc->granularity;
213        si->stuff[SMP_BAN2_STUFF] = si->stuff[SMP_BAN1_STUFF] + 1024*1024;
214        si->stuff[SMP_SEG1_STUFF] = si->stuff[SMP_BAN2_STUFF] + 1024*1024;
215        si->stuff[SMP_SEG2_STUFF] = si->stuff[SMP_SEG1_STUFF] + 1024*1024;
216        si->stuff[SMP_SPC_STUFF] = si->stuff[SMP_SEG2_STUFF] + 1024*1024;
217        si->stuff[SMP_END_STUFF] = si->mediasize;
218        assert(si->stuff[SMP_SPC_STUFF] < si->stuff[SMP_END_STUFF]);
219
220        smp_new_sign(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], "BAN 1");
221        smp_new_sign(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], "BAN 2");
222        smp_new_sign(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], "SEG 1");
223        smp_new_sign(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], "SEG 2");
224
225        smp_append_sign(&sc->idn, si, sizeof *si);
226        smp_sync_sign(&sc->idn);
227}
228
229/*--------------------------------------------------------------------
230 * Check if a silo is valid.
231 */
232
233int
234smp_valid_silo(struct smp_sc *sc)
235{
236        struct smp_ident        *si;
237        int i, j;
238
239        assert(strlen(SMP_IDENT_STRING) < sizeof si->ident);
240
241        i = smp_chk_sign(&sc->idn);
242        if (i)
243                return (i);
244
245        si = sc->ident;
246        if (strcmp(si->ident, SMP_IDENT_STRING))
247                return (12);
248        if (si->byte_order != 0x12345678)
249                return (13);
250        if (si->size != sizeof *si)
251                return (14);
252        if (si->major_version != 2)
253                return (15);
254        if (si->mediasize != sc->mediasize)
255                return (17);
256        if (si->granularity != sc->granularity)
257                return (18);
258        if (si->align < sizeof(void*))
259                return (19);
260        if (!PWR2(si->align))
261                return (20);
262        sc->align = si->align;
263        sc->unique = si->unique;
264
265        /* XXX: Sanity check stuff[6] */
266
267        assert(si->stuff[SMP_BAN1_STUFF] > sizeof *si + SHA256_LEN);
268        assert(si->stuff[SMP_BAN2_STUFF] > si->stuff[SMP_BAN1_STUFF]);
269        assert(si->stuff[SMP_SEG1_STUFF] > si->stuff[SMP_BAN2_STUFF]);
270        assert(si->stuff[SMP_SEG2_STUFF] > si->stuff[SMP_SEG1_STUFF]);
271        assert(si->stuff[SMP_SPC_STUFF] > si->stuff[SMP_SEG2_STUFF]);
272        assert(si->stuff[SMP_END_STUFF] == sc->mediasize);
273
274        assert(smp_stuff_len(sc, SMP_SEG1_STUFF) > 65536);
275        assert(smp_stuff_len(sc, SMP_SEG1_STUFF) ==
276          smp_stuff_len(sc, SMP_SEG2_STUFF));
277
278        assert(smp_stuff_len(sc, SMP_BAN1_STUFF) > 65536);
279        assert(smp_stuff_len(sc, SMP_BAN1_STUFF) ==
280          smp_stuff_len(sc, SMP_BAN2_STUFF));
281
282        smp_def_sign(sc, &sc->ban1, si->stuff[SMP_BAN1_STUFF], "BAN 1");
283        smp_def_sign(sc, &sc->ban2, si->stuff[SMP_BAN2_STUFF], "BAN 2");
284        smp_def_sign(sc, &sc->seg1, si->stuff[SMP_SEG1_STUFF], "SEG 1");
285        smp_def_sign(sc, &sc->seg2, si->stuff[SMP_SEG2_STUFF], "SEG 2");
286
287        /* We must have one valid BAN table */
288        i = smp_chk_sign(&sc->ban1);
289        j = smp_chk_sign(&sc->ban2);
290        if (i && j)
291                return (100 + i * 10 + j);
292
293        /* We must have one valid SEG table */
294        i = smp_chk_sign(&sc->seg1);
295        j = smp_chk_sign(&sc->seg2);
296        if (i && j)
297                return (200 + i * 10 + j);
298        return (0);
299}
Note: See TracBrowser for help on using the repository browser.