Deleted Added
full compact
g_bde.c (112367) g_bde.c (112552)
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/geom/bde/g_bde.c 112367 2003-03-18 08:45:25Z phk $
32 * $FreeBSD: head/sys/geom/bde/g_bde.c 112552 2003-03-24 19:30:15Z phk $
33 *
34 */
35
36#include <sys/param.h>
37#include <sys/bio.h>
38#include <sys/lock.h>
39#include <sys/mutex.h>
40#include <sys/malloc.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/kthread.h>
44
45#include <crypto/rijndael/rijndael.h>
46#include <crypto/sha2/sha2.h>
47#include <geom/geom.h>
48#include <geom/bde/g_bde.h>
49#define BDE_CLASS_NAME "BDE"
50
51static void
52g_bde_start(struct bio *bp)
53{
54 struct g_geom *gp;
55 struct g_consumer *cp;
56 struct g_bde_softc *sc;
57
58 gp = bp->bio_to->geom;
59 cp = LIST_FIRST(&gp->consumer);
60 sc = gp->softc;
61 switch (bp->bio_cmd) {
62 case BIO_DELETE:
63 case BIO_READ:
64 case BIO_WRITE:
65 g_bde_start1(bp);
66 break;
67 case BIO_GETATTR:
68 case BIO_SETATTR:
69 g_io_deliver(bp, EOPNOTSUPP);
70 break;
71 default:
72 g_io_deliver(bp, EOPNOTSUPP);
73 return;
74 }
75 return;
76}
77
78static void
79g_bde_orphan(struct g_consumer *cp)
80{
81 struct g_geom *gp;
82 struct g_provider *pp;
83 struct g_bde_softc *sc;
84 int error;
85
86 g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name);
87 g_topology_assert();
88 KASSERT(cp->provider->error != 0,
89 ("g_bde_orphan with error == 0"));
90
91 gp = cp->geom;
92 sc = gp->softc;
93 gp->flags |= G_GEOM_WITHER;
94 error = cp->provider->error;
95 LIST_FOREACH(pp, &gp->provider, provider)
96 g_orphan_provider(pp, error);
97 bzero(sc, sizeof(struct g_bde_softc)); /* destroy evidence */
98 return;
99}
100
101static int
102g_bde_access(struct g_provider *pp, int dr, int dw, int de)
103{
104 struct g_geom *gp;
105 struct g_consumer *cp;
106
107 gp = pp->geom;
108 cp = LIST_FIRST(&gp->consumer);
109 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
110 de++;
111 dr++;
112 }
113 /* ... and let go of it on last close */
114 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
115 de--;
116 dr--;
117 }
118 return (g_access_rel(cp, dr, dw, de));
119}
120
121static int
122g_bde_config(struct g_configargs *ga)
123{
124 struct g_geom *gp;
125 struct g_consumer *cp;
126 struct g_provider *pp;
127 struct g_bde_key *kp;
128 int error;
129 u_int sectorsize;
130 off_t mediasize;
131 struct g_bde_softc *sc;
132
133 g_trace(G_T_TOPOLOGY, "g_bde_config(%d)", ga->flag);
134 g_topology_assert();
135 gp = NULL;
136 if (ga->flag == GCFG_DISMANTLE) {
137 /*
138 * Orderly detachment.
139 */
140 if (ga->geom != NULL) {
141 gp = ga->geom;
142 } else if (ga->provider != NULL) {
143 if (ga->provider->geom->class == ga->class) {
144 gp = ga->provider->geom;
145 } else {
146 LIST_FOREACH(cp, &ga->provider->consumers,
147 consumers) {
148 if (cp->geom->class == ga->class) {
149 gp = cp->geom;
150 break;
151 }
152 }
153 }
154 if (gp == NULL)
155 return (EINVAL);
156 } else {
157 return (EINVAL);
158 }
159 KASSERT(gp != NULL, ("NULL geom"));
160 pp = LIST_FIRST(&gp->provider);
161 KASSERT(pp != NULL, ("NULL provider"));
162 if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
163 return (EBUSY);
164 g_orphan_provider(pp, ENXIO);
165 sc = gp->softc;
166 cp = LIST_FIRST(&gp->consumer);
167 KASSERT(cp != NULL, ("NULL consumer"));
168 sc->dead = 1;
169 wakeup(sc);
170 error = g_access_rel(cp, -1, -1, -1);
171 KASSERT(error == 0, ("error on close"));
172 g_detach(cp);
173 g_destroy_consumer(cp);
174 g_topology_unlock();
175 while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
176 tsleep(sc, PRIBIO, "g_bdedie", hz);
177 g_waitidle();
178 g_topology_lock();
179 g_destroy_provider(pp);
180 mtx_destroy(&sc->worklist_mutex);
181 bzero(&sc->key, sizeof sc->key);
182 g_free(sc);
183 g_destroy_geom(gp);
184 return (0);
185 }
186
187 if (ga->flag != GCFG_CREATE)
188 return (EOPNOTSUPP);
189
190 if (ga->provider == NULL)
191 return (EINVAL);
192 /*
193 * Attach
194 */
195 gp = g_new_geomf(ga->class, "%s.bde", ga->provider->name);
196 gp->start = g_bde_start;
197 gp->orphan = g_bde_orphan;
198 gp->access = g_bde_access;
199 gp->spoiled = g_std_spoiled;
200 cp = g_new_consumer(gp);
201 g_attach(cp, ga->provider);
202 error = g_access_rel(cp, 1, 1, 1);
203 if (error) {
204 g_detach(cp);
205 g_destroy_consumer(cp);
206 g_destroy_geom(gp);
207 return (error);
208 }
209 g_topology_unlock();
210 g_waitidle();
211 while (1) {
212 sectorsize = cp->provider->sectorsize;
213 mediasize = cp->provider->mediasize;
214 sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO);
215 gp->softc = sc;
216 sc->geom = gp;
217 sc->consumer = cp;
218
219 error = g_bde_decrypt_lock(sc, ga->ptr,
220 (u_char *)ga->ptr + (sizeof sc->sha2),
221 mediasize, sectorsize, NULL);
222 bzero(sc->sha2, sizeof sc->sha2);
223 if (error)
224 break;
225 kp = &sc->key;
226
227 /* Initialize helper-fields */
228 kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
229 kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
230 kp->zone_width = kp->zone_cont + kp->sectorsize;
231 kp->media_width = kp->sectorN - kp->sector0 -
232 G_BDE_MAXKEYS * kp->sectorsize;
233
234 /* Our external parameters */
235 sc->zone_cont = kp->zone_cont;
236 sc->mediasize = g_bde_max_sector(kp);
237 sc->sectorsize = kp->sectorsize;
238
239 TAILQ_INIT(&sc->freelist);
240 TAILQ_INIT(&sc->worklist);
241 mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
242 mtx_lock(&Giant);
243 /* XXX: error check */
244 kthread_create(g_bde_worker, gp, &sc->thread, 0, 0,
245 "g_bde %s", gp->name);
246 mtx_unlock(&Giant);
247 g_topology_lock();
248 pp = g_new_providerf(gp, gp->name);
249 pp->flags |= G_PF_CANDELETE;
250 pp->stripesize = kp->zone_cont;
251 pp->stripeoffset = 0;
252 pp->mediasize = sc->mediasize;
253 pp->sectorsize = sc->sectorsize;
254 g_error_provider(pp, 0);
255 g_topology_unlock();
256 break;
257 }
258 g_topology_lock();
259 if (error == 0) {
260 ga->geom = gp;
261 return (0);
262 } else {
263 g_access_rel(cp, -1, -1, -1);
264 }
265 g_detach(cp);
266 g_destroy_consumer(cp);
267 if (gp->softc != NULL)
268 g_free(gp->softc);
269 g_destroy_geom(gp);
270 return (error);
271}
272
273static struct g_class g_bde_class = {
33 *
34 */
35
36#include <sys/param.h>
37#include <sys/bio.h>
38#include <sys/lock.h>
39#include <sys/mutex.h>
40#include <sys/malloc.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/kthread.h>
44
45#include <crypto/rijndael/rijndael.h>
46#include <crypto/sha2/sha2.h>
47#include <geom/geom.h>
48#include <geom/bde/g_bde.h>
49#define BDE_CLASS_NAME "BDE"
50
51static void
52g_bde_start(struct bio *bp)
53{
54 struct g_geom *gp;
55 struct g_consumer *cp;
56 struct g_bde_softc *sc;
57
58 gp = bp->bio_to->geom;
59 cp = LIST_FIRST(&gp->consumer);
60 sc = gp->softc;
61 switch (bp->bio_cmd) {
62 case BIO_DELETE:
63 case BIO_READ:
64 case BIO_WRITE:
65 g_bde_start1(bp);
66 break;
67 case BIO_GETATTR:
68 case BIO_SETATTR:
69 g_io_deliver(bp, EOPNOTSUPP);
70 break;
71 default:
72 g_io_deliver(bp, EOPNOTSUPP);
73 return;
74 }
75 return;
76}
77
78static void
79g_bde_orphan(struct g_consumer *cp)
80{
81 struct g_geom *gp;
82 struct g_provider *pp;
83 struct g_bde_softc *sc;
84 int error;
85
86 g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name);
87 g_topology_assert();
88 KASSERT(cp->provider->error != 0,
89 ("g_bde_orphan with error == 0"));
90
91 gp = cp->geom;
92 sc = gp->softc;
93 gp->flags |= G_GEOM_WITHER;
94 error = cp->provider->error;
95 LIST_FOREACH(pp, &gp->provider, provider)
96 g_orphan_provider(pp, error);
97 bzero(sc, sizeof(struct g_bde_softc)); /* destroy evidence */
98 return;
99}
100
101static int
102g_bde_access(struct g_provider *pp, int dr, int dw, int de)
103{
104 struct g_geom *gp;
105 struct g_consumer *cp;
106
107 gp = pp->geom;
108 cp = LIST_FIRST(&gp->consumer);
109 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
110 de++;
111 dr++;
112 }
113 /* ... and let go of it on last close */
114 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
115 de--;
116 dr--;
117 }
118 return (g_access_rel(cp, dr, dw, de));
119}
120
121static int
122g_bde_config(struct g_configargs *ga)
123{
124 struct g_geom *gp;
125 struct g_consumer *cp;
126 struct g_provider *pp;
127 struct g_bde_key *kp;
128 int error;
129 u_int sectorsize;
130 off_t mediasize;
131 struct g_bde_softc *sc;
132
133 g_trace(G_T_TOPOLOGY, "g_bde_config(%d)", ga->flag);
134 g_topology_assert();
135 gp = NULL;
136 if (ga->flag == GCFG_DISMANTLE) {
137 /*
138 * Orderly detachment.
139 */
140 if (ga->geom != NULL) {
141 gp = ga->geom;
142 } else if (ga->provider != NULL) {
143 if (ga->provider->geom->class == ga->class) {
144 gp = ga->provider->geom;
145 } else {
146 LIST_FOREACH(cp, &ga->provider->consumers,
147 consumers) {
148 if (cp->geom->class == ga->class) {
149 gp = cp->geom;
150 break;
151 }
152 }
153 }
154 if (gp == NULL)
155 return (EINVAL);
156 } else {
157 return (EINVAL);
158 }
159 KASSERT(gp != NULL, ("NULL geom"));
160 pp = LIST_FIRST(&gp->provider);
161 KASSERT(pp != NULL, ("NULL provider"));
162 if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
163 return (EBUSY);
164 g_orphan_provider(pp, ENXIO);
165 sc = gp->softc;
166 cp = LIST_FIRST(&gp->consumer);
167 KASSERT(cp != NULL, ("NULL consumer"));
168 sc->dead = 1;
169 wakeup(sc);
170 error = g_access_rel(cp, -1, -1, -1);
171 KASSERT(error == 0, ("error on close"));
172 g_detach(cp);
173 g_destroy_consumer(cp);
174 g_topology_unlock();
175 while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
176 tsleep(sc, PRIBIO, "g_bdedie", hz);
177 g_waitidle();
178 g_topology_lock();
179 g_destroy_provider(pp);
180 mtx_destroy(&sc->worklist_mutex);
181 bzero(&sc->key, sizeof sc->key);
182 g_free(sc);
183 g_destroy_geom(gp);
184 return (0);
185 }
186
187 if (ga->flag != GCFG_CREATE)
188 return (EOPNOTSUPP);
189
190 if (ga->provider == NULL)
191 return (EINVAL);
192 /*
193 * Attach
194 */
195 gp = g_new_geomf(ga->class, "%s.bde", ga->provider->name);
196 gp->start = g_bde_start;
197 gp->orphan = g_bde_orphan;
198 gp->access = g_bde_access;
199 gp->spoiled = g_std_spoiled;
200 cp = g_new_consumer(gp);
201 g_attach(cp, ga->provider);
202 error = g_access_rel(cp, 1, 1, 1);
203 if (error) {
204 g_detach(cp);
205 g_destroy_consumer(cp);
206 g_destroy_geom(gp);
207 return (error);
208 }
209 g_topology_unlock();
210 g_waitidle();
211 while (1) {
212 sectorsize = cp->provider->sectorsize;
213 mediasize = cp->provider->mediasize;
214 sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO);
215 gp->softc = sc;
216 sc->geom = gp;
217 sc->consumer = cp;
218
219 error = g_bde_decrypt_lock(sc, ga->ptr,
220 (u_char *)ga->ptr + (sizeof sc->sha2),
221 mediasize, sectorsize, NULL);
222 bzero(sc->sha2, sizeof sc->sha2);
223 if (error)
224 break;
225 kp = &sc->key;
226
227 /* Initialize helper-fields */
228 kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
229 kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
230 kp->zone_width = kp->zone_cont + kp->sectorsize;
231 kp->media_width = kp->sectorN - kp->sector0 -
232 G_BDE_MAXKEYS * kp->sectorsize;
233
234 /* Our external parameters */
235 sc->zone_cont = kp->zone_cont;
236 sc->mediasize = g_bde_max_sector(kp);
237 sc->sectorsize = kp->sectorsize;
238
239 TAILQ_INIT(&sc->freelist);
240 TAILQ_INIT(&sc->worklist);
241 mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
242 mtx_lock(&Giant);
243 /* XXX: error check */
244 kthread_create(g_bde_worker, gp, &sc->thread, 0, 0,
245 "g_bde %s", gp->name);
246 mtx_unlock(&Giant);
247 g_topology_lock();
248 pp = g_new_providerf(gp, gp->name);
249 pp->flags |= G_PF_CANDELETE;
250 pp->stripesize = kp->zone_cont;
251 pp->stripeoffset = 0;
252 pp->mediasize = sc->mediasize;
253 pp->sectorsize = sc->sectorsize;
254 g_error_provider(pp, 0);
255 g_topology_unlock();
256 break;
257 }
258 g_topology_lock();
259 if (error == 0) {
260 ga->geom = gp;
261 return (0);
262 } else {
263 g_access_rel(cp, -1, -1, -1);
264 }
265 g_detach(cp);
266 g_destroy_consumer(cp);
267 if (gp->softc != NULL)
268 g_free(gp->softc);
269 g_destroy_geom(gp);
270 return (error);
271}
272
273static struct g_class g_bde_class = {
274 BDE_CLASS_NAME,
275 NULL,
276 g_bde_config,
274 .name = BDE_CLASS_NAME,
275 .config = g_bde_config,
277 G_CLASS_INITIALIZER
278};
279
280DECLARE_GEOM_CLASS(g_bde_class, g_bde);
276 G_CLASS_INITIALIZER
277};
278
279DECLARE_GEOM_CLASS(g_bde_class, g_bde);