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