Free opencrypto sessions on suspend, as they also might keep encryption keys.

This commit is contained in:
Pawel Jakub Dawidek 2010-10-21 19:44:28 +00:00
parent 9f95314538
commit 3ac01bc2ae
2 changed files with 81 additions and 35 deletions

View File

@ -314,6 +314,69 @@ g_eli_start(struct bio *bp)
}
}
static int
g_eli_newsession(struct g_eli_worker *wr)
{
struct g_eli_softc *sc;
struct cryptoini crie, cria;
int error;
sc = wr->w_softc;
bzero(&crie, sizeof(crie));
crie.cri_alg = sc->sc_ealgo;
crie.cri_klen = sc->sc_ekeylen;
if (sc->sc_ealgo == CRYPTO_AES_XTS)
crie.cri_klen <<= 1;
crie.cri_key = sc->sc_ekeys[0];
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
bzero(&cria, sizeof(cria));
cria.cri_alg = sc->sc_aalgo;
cria.cri_klen = sc->sc_akeylen;
cria.cri_key = sc->sc_akey;
crie.cri_next = &cria;
}
switch (sc->sc_crypto) {
case G_ELI_CRYPTO_SW:
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_SOFTWARE);
break;
case G_ELI_CRYPTO_HW:
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_HARDWARE);
break;
case G_ELI_CRYPTO_UNKNOWN:
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_HARDWARE);
if (error == 0) {
mtx_lock(&sc->sc_queue_mtx);
if (sc->sc_crypto == G_ELI_CRYPTO_UNKNOWN)
sc->sc_crypto = G_ELI_CRYPTO_HW;
mtx_unlock(&sc->sc_queue_mtx);
} else {
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_SOFTWARE);
mtx_lock(&sc->sc_queue_mtx);
if (sc->sc_crypto == G_ELI_CRYPTO_UNKNOWN)
sc->sc_crypto = G_ELI_CRYPTO_SW;
mtx_unlock(&sc->sc_queue_mtx);
}
break;
default:
panic("%s: invalid condition", __func__);
}
return (error);
}
static void
g_eli_freesession(struct g_eli_worker *wr)
{
crypto_freesession(wr->w_sid);
}
static void
g_eli_cancel(struct g_eli_softc *sc)
{
@ -361,6 +424,7 @@ g_eli_worker(void *arg)
struct g_eli_softc *sc;
struct g_eli_worker *wr;
struct bio *bp;
int error;
wr = arg;
sc = wr->w_softc;
@ -388,7 +452,7 @@ again:
if (sc->sc_flags & G_ELI_FLAG_DESTROY) {
g_eli_cancel(sc);
LIST_REMOVE(wr, w_next);
crypto_freesession(wr->w_sid);
g_eli_freesession(wr);
free(wr, M_ELI);
G_ELI_DEBUG(1, "Thread %s exiting.",
curthread->td_proc->p_comm);
@ -411,12 +475,21 @@ again:
* Suspend requested, mark the worker as
* suspended and go to sleep.
*/
wr->w_active = 0;
if (wr->w_active) {
g_eli_freesession(wr);
wr->w_active = FALSE;
}
wakeup(&sc->sc_workers);
msleep(sc, &sc->sc_queue_mtx, PRIBIO,
"geli:suspend", 0);
if (!(sc->sc_flags & G_ELI_FLAG_SUSPEND))
wr->w_active = 1;
if (!wr->w_active &&
!(sc->sc_flags & G_ELI_FLAG_SUSPEND)) {
error = g_eli_newsession(wr);
KASSERT(error == 0,
("g_eli_newsession() failed on resume (error=%d)",
error));
wr->w_active = TRUE;
}
goto again;
}
msleep(sc, &sc->sc_queue_mtx, PDROP, "geli:w", 0);
@ -630,7 +703,6 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
struct g_geom *gp;
struct g_provider *pp;
struct g_consumer *cp;
struct cryptoini crie, cria;
u_int i, threads;
int error;
@ -658,7 +730,7 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
gp->access = g_std_access;
sc->sc_inflight = 0;
sc->sc_crypto = G_ELI_CRYPTO_SW;
sc->sc_crypto = G_ELI_CRYPTO_UNKNOWN;
sc->sc_flags = md->md_flags;
/* Backward compatibility. */
if (md->md_version < 4)
@ -772,20 +844,6 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
LIST_INIT(&sc->sc_workers);
bzero(&crie, sizeof(crie));
crie.cri_alg = sc->sc_ealgo;
crie.cri_klen = sc->sc_ekeylen;
if (sc->sc_ealgo == CRYPTO_AES_XTS)
crie.cri_klen <<= 1;
crie.cri_key = sc->sc_ekeys[0];
if (sc->sc_flags & G_ELI_FLAG_AUTH) {
bzero(&cria, sizeof(cria));
cria.cri_alg = sc->sc_aalgo;
cria.cri_klen = sc->sc_akeylen;
cria.cri_key = sc->sc_akey;
crie.cri_next = &cria;
}
threads = g_eli_threads;
if (threads == 0)
threads = mp_ncpus;
@ -805,20 +863,7 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
wr->w_number = i;
wr->w_active = TRUE;
/*
* If this is the first pass, try to get hardware support.
* Use software cryptography, if we cannot get it.
*/
if (LIST_EMPTY(&sc->sc_workers)) {
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_HARDWARE);
if (error == 0)
sc->sc_crypto = G_ELI_CRYPTO_HW;
}
if (sc->sc_crypto == G_ELI_CRYPTO_SW) {
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_SOFTWARE);
}
error = g_eli_newsession(wr);
if (error != 0) {
free(wr, M_ELI);
if (req != NULL) {
@ -834,7 +879,7 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
error = kproc_create(g_eli_worker, wr, &wr->w_proc, 0, 0,
"g_eli[%u] %s", i, bpp->name);
if (error != 0) {
crypto_freesession(wr->w_sid);
g_eli_freesession(wr);
free(wr, M_ELI);
if (req != NULL) {
gctl_error(req, "Cannot create kernel thread "

View File

@ -113,6 +113,7 @@ extern int g_eli_debug;
extern u_int g_eli_overwrites;
extern u_int g_eli_batch;
#define G_ELI_CRYPTO_UNKNOWN 0
#define G_ELI_CRYPTO_HW 1
#define G_ELI_CRYPTO_SW 2