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 *
|
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 = {
|