PERFORCE change 165990 for review
Gleb Kurtsou
gk at FreeBSD.org
Mon Jul 13 09:18:13 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=165990
Change 165990 by gk at gk_h1 on 2009/07/13 09:18:07
Use salsa20 for encryption
Remove all cipher block alignment handling bloat
Implement key generation function (using salsa20)
Use uma zones for cryptographically sensitive info (to bzero memory before free)
Add key reference counting and locking
Support nodes without key
Add transparent mode. Emulate read-only filesystem if no keys specified
Affected files ...
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#6 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#3 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#6 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#5 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#6 edit
Differences ...
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#6 (text+ko) ====
@@ -37,24 +37,28 @@
* $FreeBSD$
*/
+#include <sys/param.h>
+#include <sys/mutex.h>
+#include <sys/refcount.h>
#include <sys/queue.h>
#include <sys/uio.h>
#ifdef _KERNEL
-#define PEFS_BLOCK 16
-#define PEFS_TWEAK_SIZE 16
-#define PEFS_KEY_SIZE 64
+#define PEFS_TWEAK_SIZE 8
+#define PEFS_KEY_BITS 256
+#define PEFS_KEY_SIZE (PEFS_KEY_BITS / 8)
#define PEFS_NAME_CSUM_SIZE 2
#define PEFS_NAME_NTOP_SIZE(a) (((a) * 4 + 2)/3)
#define PEFS_NAME_PTON_SIZE(a) (((a) * 3)/4)
-SLIST_HEAD(pefs_key_head, pefs_key);
+LIST_HEAD(pefs_key_head, pefs_key);
struct pefs_key {
- SLIST_ENTRY(pefs_key) pk_entry;
volatile u_int pk_refcnt;
+ LIST_ENTRY(pefs_key) pk_entry;
+ struct mtx *pk_entry_lock;
char pk_name[PEFS_KEY_SIZE];
char pk_data[PEFS_KEY_SIZE];
};
@@ -64,16 +68,20 @@
char ptk_tweak[PEFS_TWEAK_SIZE];
};
+#define PN_HASKEY 0x0001
+
struct pefs_node {
LIST_ENTRY(pefs_node) pn_hash; /* Hash list */
struct vnode *pn_lowervp; /* VREFed once */
struct vnode *pn_vnode; /* Back pointer */
+ int pn_flags;
struct pefs_tkey pn_tkey;
};
struct pefs_mount {
struct mount *pm_vfs;
struct vnode *pm_rootvp; /* Reference to root pefs_node */
+ struct mtx pm_keys_lock;
struct pefs_key_head pm_keys;
};
@@ -128,21 +136,30 @@
struct vfsconf;
struct vop_generic_args;
+struct pefs_ctx;
int pefs_init(struct vfsconf *vfsp);
int pefs_uninit(struct vfsconf *vfsp);
-int pefs_node_get(struct mount *mp, struct vnode *lowervp, struct vnode **vpp, struct pefs_tkey *ptk);
+void pefs_crypto_init(void);
+void pefs_crypto_uninit(void);
+
+int pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode *ldvp, struct vnode **vpp, struct ucred *cred, struct pefs_tkey *ptk);
void pefs_node_free(struct pefs_node *xp);
+int pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len);
struct pefs_key* pefs_node_key(struct pefs_node *pn);
-struct pefs_tkey* pefs_node_tkey(struct pefs_node *pn);
+
+struct pefs_ctx *pefs_ctx_get(void);
+void pefs_ctx_free(struct pefs_ctx *ctx);
+
+struct pefs_key* pefs_key_get(char *passwd, int passwd_len);
+struct pefs_key* pefs_key_ref(struct pefs_key *pk);
+void pefs_key_release(struct pefs_key *pk);
-void pefs_data_encrypt(struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
-void pefs_data_encrypt_buf(struct pefs_tkey *ptk, off_t offset, void *mem, size_t size);
-void pefs_data_decrypt(struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
-void pefs_data_decrypt_buf(struct pefs_tkey *ptk, off_t offset, void *mem, size_t size);
+void pefs_data_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
+void pefs_data_decrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc);
-int pefs_name_encrypt(struct pefs_tkey *ptk, const char *plain, size_t plain_len, char *enc, size_t enc_size);
-int pefs_name_decrypt(struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size);
+int pefs_name_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, const char *plain, size_t plain_len, char *enc, size_t enc_size);
+int pefs_name_decrypt(struct pefs_ctx *ctx, struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size);
int pefs_name_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
int pefs_name_pton(char const *src, size_t srclen, u_char *target, size_t targsize);
@@ -150,6 +167,7 @@
struct pefs_chunk* pefs_chunk_create(size_t size);
void pefs_chunk_restore(struct pefs_chunk* pc);
void pefs_chunk_free(struct pefs_chunk* pc);
+void* pefs_chunk_pullup(struct pefs_chunk *pc, size_t size);
struct uio* pefs_chunk_uio(struct pefs_chunk *pc, off_t uio_offset, enum uio_rw uio_rw);
struct uio* pefs_chunk_uio_range(struct pefs_chunk *pc, size_t skip, size_t size, off_t uio_offset, enum uio_rw uio_rw);
void* pefs_chunk_get(struct pefs_chunk *pc, size_t *size, long *_state);
@@ -160,6 +178,25 @@
extern struct vop_vector pefs_vnodeops;
+static inline struct pefs_key*
+pefs_rootkey(struct pefs_mount *pm)
+{
+ struct pefs_key *pk;
+
+ mtx_lock(&pm->pm_keys_lock);
+ pk = LIST_FIRST(&pm->pm_keys);
+ mtx_unlock(&pm->pm_keys_lock);
+
+ return (pk);
+}
+
+static inline int
+pefs_no_keys(struct vnode *vp)
+{
+ return (!(VP_TO_PN(vp)->pn_flags & PN_HASKEY) &&
+ pefs_rootkey(VFS_TO_PEFS(vp->v_mount)) == NULL);
+}
+
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_PEFSBUF);
#endif
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_crypto.c#3 (text+ko) ====
@@ -29,96 +29,167 @@
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/libkern.h>
+#include <sys/malloc.h>
#include <sys/mount.h>
+#include <sys/queue.h>
#include <sys/vnode.h>
-#include <crypto/rc4/rc4.h>
+#include <vm/uma.h>
+
+#include <crypto/salsa20/salsa20.h>
#include <fs/pefs/pefs.h>
-#if 0
+static const char magic_tweak_name[PEFS_TWEAK_SIZE] = {
+ 0x5c, 0x83, 0xcb, 0x96, 0x2f, 0xaf, 0x3b, 0xb5,
+};
+
+#define MAGIC_KEYGEN_ITERATIONS 32
+
+static const uint8_t magic_key_keygen[PEFS_KEY_SIZE] = {
+ 0xd2, 0x68, 0x7d, 0x52, 0xb7, 0xc1, 0xe0, 0xc7,
+ 0x26, 0xf1, 0x53, 0xaf, 0xa1, 0x46, 0x7a, 0xc9,
+ 0x3a, 0x37, 0xc6, 0xf6, 0x7d, 0xd3, 0xbe, 0xed,
+ 0xf4, 0x52, 0x24, 0x9e, 0x6c, 0x85, 0xd9, 0x5c,
+};
+
+static const uint8_t magic_tweak_keygen[PEFS_TWEAK_SIZE] = {
+ 0xc8, 0x27, 0xa3, 0x7e, 0xcf, 0x86, 0x3d, 0x0d,
+};
+
+struct pefs_ctx {
+ salsa20_ctx pctx_salsa;
+};
+
+static uma_zone_t pefs_ctx_zone;
+static uma_zone_t pefs_key_zone;
+
+void
+pefs_crypto_init(void)
+{
+ pefs_ctx_zone = uma_zcreate("pefs_ctx", sizeof(struct pefs_ctx),
+ NULL, NULL, NULL, (uma_fini) bzero,
+ UMA_ALIGN_PTR, 0);
+ pefs_key_zone = uma_zcreate("pefs_key", sizeof(struct pefs_key),
+ NULL, NULL, NULL, (uma_fini) bzero,
+ UMA_ALIGN_PTR, 0);
+}
+
+void
+pefs_crypto_uninit(void)
+{
+ uma_zdestroy(pefs_ctx_zone);
+ uma_zdestroy(pefs_key_zone);
+}
+
+struct pefs_ctx *
+pefs_ctx_get(void)
+{
+ return uma_zalloc(pefs_ctx_zone, M_WAITOK);
+}
+
+void
+pefs_ctx_free(struct pefs_ctx *ctx)
+{
+ uma_zfree(pefs_ctx_zone, ctx);
+}
+
static void
-pefs_xor(void *mem, size_t size)
+pefs_key_generate(struct pefs_ctx *ctx, uint8_t *key)
{
- char *b = (char *)mem;
- char *e = b + size;
+ uint8_t tweak[PEFS_TWEAK_SIZE];
+ int i, j;
+
+ memcpy(tweak, magic_tweak_keygen, PEFS_TWEAK_SIZE);
+
+ salsa20_keysetup(&ctx->pctx_salsa, magic_key_keygen, PEFS_KEY_BITS);
+ salsa20_ivsetup(&ctx->pctx_salsa, tweak, 0);
+ salsa20_crypt(&ctx->pctx_salsa, key, key, PEFS_KEY_SIZE);
- for (; b < e; b++) {
- *b ^= 0xAA;
+ for (i = 1; i < MAGIC_KEYGEN_ITERATIONS; i++) {
+ for (j = 0; j < PEFS_TWEAK_SIZE; j++)
+ tweak[j]++;
+ salsa20_keysetup(&ctx->pctx_salsa, key, PEFS_KEY_BITS);
+ salsa20_ivsetup(&ctx->pctx_salsa, tweak, i * 64);
+ salsa20_crypt(&ctx->pctx_salsa, key, key, PEFS_KEY_SIZE);
}
}
-static void
-pefs_xor_chunk(struct pefs_chunk *pc)
+struct pefs_key *
+pefs_key_get(char *passwd, int passwd_len)
+{
+ struct pefs_ctx *ctx;
+ struct pefs_key *pk;
+ int i;
+
+ pk = uma_zalloc(pefs_key_zone, M_WAITOK | M_ZERO);
+ refcount_init(&pk->pk_refcnt, 1);
+
+ if (passwd_len > PEFS_KEY_SIZE)
+ passwd_len = PEFS_KEY_SIZE;
+ memcpy(pk->pk_name, passwd, passwd_len);
+ for (i = passwd_len; i < PEFS_KEY_SIZE; i++)
+ pk->pk_name[i] = passwd[i % passwd_len];
+
+ ctx = pefs_ctx_get();
+ pefs_key_generate(ctx, pk->pk_name);
+ memcpy(pk->pk_data, pk->pk_name, PEFS_KEY_SIZE);
+ pefs_key_generate(ctx, pk->pk_data);
+ pefs_ctx_free(ctx);
+
+ return (pk);
+}
+
+struct pefs_key *
+pefs_key_ref(struct pefs_key *pk)
{
- long arg = 0;
- char *mem;
- size_t size;
+ refcount_acquire(&pk->pk_refcnt);
+ return (pk);
+}
- while (1) {
- mem = pefs_chunk_get(pc, &size, &arg);
- if (mem == NULL)
- break;
- pefs_xor(mem, size);
- }
+void
+pefs_key_release(struct pefs_key *pk)
+{
+ if (pk == NULL)
+ return;
+ if (refcount_release(&pk->pk_refcnt))
+ uma_zfree(pefs_key_zone, pk);
}
-#endif
void
-pefs_data_encrypt(struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
+pefs_data_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
{
long arg = 0;
char *mem;
size_t size;
+ int free_ctx = 0;
if (ptk->ptk_key == NULL) {
PEFSDEBUG("!!! %s: NULL ptk_key\n", __func__);
return;
}
- if (offset % PEFS_BLOCK != 0) {
- PEFSDEBUG("!!! %s: invalid offset %jd\n", __func__, offset);
- return;
+ if (ctx == NULL) {
+ ctx = pefs_ctx_get();
+ free_ctx = 1;
}
- // FIXME
- struct rc4_state rc4state;
- rc4_init(&rc4state, ptk->ptk_key->pk_data, PEFS_KEY_SIZE);
+ salsa20_keysetup(&ctx->pctx_salsa, ptk->ptk_key->pk_data, PEFS_KEY_BITS);
+ salsa20_ivsetup(&ctx->pctx_salsa, ptk->ptk_tweak, offset);
while (1) {
mem = pefs_chunk_get(pc, &size, &arg);
if (mem == NULL)
break;
- rc4_crypt(&rc4state, mem, mem, size);
+ salsa20_crypt(&ctx->pctx_salsa, mem, mem, size);
}
-}
-void
-pefs_data_encrypt_buf(struct pefs_tkey *ptk, off_t offset, void *mem, size_t size)
-{
- if (ptk->ptk_key == NULL) {
- PEFSDEBUG("!!! %s: NULL ptk_key\n", __func__);
- return;
- }
- if (offset % PEFS_BLOCK != 0) {
- PEFSDEBUG("!!! %s: invalid offset %jd\n", __func__, offset);
- return;
- }
-
- // FIXME
- struct rc4_state rc4state;
- rc4_init(&rc4state, ptk->ptk_key->pk_data, PEFS_KEY_SIZE);
- rc4_crypt(&rc4state, mem, mem, size);
+ if (free_ctx)
+ pefs_ctx_free(ctx);
}
void
-pefs_data_decrypt(struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
+pefs_data_decrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, off_t offset, struct pefs_chunk *pc)
{
- pefs_data_encrypt(ptk, offset, pc);
-}
-
-void
-pefs_data_decrypt_buf(struct pefs_tkey *ptk, off_t offset, void *mem, size_t size)
-{
- pefs_data_encrypt_buf(ptk, offset, mem, size);
+ pefs_data_encrypt(ctx, ptk, offset, pc);
}
/*
@@ -135,9 +206,15 @@
count -= 2;
}
+ /* Fold 32-bit sum to 16 bits */
+ while (sum >> 16)
+ sum = (sum & 0xffff) + (sum >> 16);
+
/* Add left-over byte, if any */
- if (count > 0)
+ if (count > 0) {
sum += * (unsigned char *) buf;
+ sum <<= 8;
+ }
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
@@ -147,13 +224,15 @@
}
int
-pefs_name_encrypt(struct pefs_tkey *ptk, const char *plain, size_t plain_len, char *enc, size_t enc_size)
+pefs_name_encrypt(struct pefs_ctx *ctx, struct pefs_tkey *ptk, const char *plain, size_t plain_len, char *enc, size_t enc_size)
{
char *buf;
size_t size;
u_short csum;
+ int free_ctx = 0;
int r;
+
if (ptk == NULL || ptk->ptk_key == NULL) {
PEFSDEBUG("!!!! %s: NULL key\n", __func__);
return (-1);
@@ -174,10 +253,17 @@
csum = pefs_name_checksum(buf, size);
memcpy(buf + size - PEFS_NAME_CSUM_SIZE, &csum, PEFS_NAME_CSUM_SIZE);
- // FIXME
- struct rc4_state rc4state;
- rc4_init(&rc4state, ptk->ptk_key->pk_name, PEFS_KEY_SIZE);
- rc4_crypt(&rc4state, buf, buf, size);
+ if (ctx == NULL) {
+ ctx = pefs_ctx_get();
+ free_ctx = 1;
+ }
+
+ salsa20_keysetup(&ctx->pctx_salsa, ptk->ptk_key->pk_name, PEFS_KEY_BITS);
+ salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
+ salsa20_crypt(&ctx->pctx_salsa, buf, buf, size);
+
+ if (free_ctx)
+ pefs_ctx_free(ctx);
r = pefs_name_ntop(buf, size, enc, enc_size);
@@ -189,9 +275,10 @@
}
int
-pefs_name_decrypt(struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size)
+pefs_name_decrypt(struct pefs_ctx *ctx, struct pefs_key *pk, struct pefs_tkey *ptk, const char *enc, size_t enc_len, char *plain, size_t plain_size)
{
u_short csum;
+ int free_ctx = 0;
int r;
if (pk == NULL) {
@@ -205,10 +292,17 @@
return (-1);
}
- // FIXME
- struct rc4_state rc4state;
- rc4_init(&rc4state, pk->pk_name, PEFS_KEY_SIZE);
- rc4_crypt(&rc4state, plain, plain, r);
+ if (ctx == NULL) {
+ ctx = pefs_ctx_get();
+ free_ctx = 1;
+ }
+
+ salsa20_keysetup(&ctx->pctx_salsa, pk->pk_name, PEFS_KEY_BITS);
+ salsa20_ivsetup(&ctx->pctx_salsa, magic_tweak_name, 0);
+ salsa20_crypt(&ctx->pctx_salsa, plain, plain, r);
+
+ if (free_ctx)
+ pefs_ctx_free(ctx);
csum = pefs_name_checksum(plain, r);
if (csum != 0) {
@@ -227,7 +321,8 @@
if (r < plain_size)
plain[r] = '\0';
- printf("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
+ PEFSDEBUG("pefs_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
return r;
}
+
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#6 (text+ko) ====
@@ -41,9 +41,12 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
-#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/dirent.h>
+#include <sys/queue.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/vnode.h>
@@ -66,32 +69,38 @@
static LIST_HEAD(pefs_node_hashhead, pefs_node) *pefs_node_hashtbl;
static u_long pefs_node_hash;
-struct mtx pefs_hashmtx;
+static struct mtx pefs_hashmtx;
static MALLOC_DEFINE(M_PEFSHASH, "pefs_hash", "PEFS hash table");
-static MALLOC_DEFINE(M_PEFSNODE, "pefs_node", "PEFS vnode private part");
MALLOC_DEFINE(M_PEFSBUF, "pefs_buf", "PEFS buffers");
+static uma_zone_t pefs_node_zone;
+
/*
* Initialise cache headers
*/
int
pefs_init(struct vfsconf *vfsp)
{
+ PEFSDEBUG("pefs_init\n");
- PEFSDEBUG("pefs_init\n"); /* printed during system boot */
+ pefs_node_zone = uma_zcreate("pefs_node", sizeof(struct pefs_node),
+ NULL, NULL, NULL, (uma_fini) bzero,
+ UMA_ALIGN_PTR, 0);
+
pefs_node_hashtbl = hashinit(NPENODECACHE, M_PEFSHASH, &pefs_node_hash);
- mtx_init(&pefs_hashmtx, "pehs", NULL, MTX_DEF);
+ mtx_init(&pefs_hashmtx, "pefs_hash", NULL, MTX_DEF);
+ pefs_crypto_init();
return (0);
}
int
-pefs_uninit(vfsp)
- struct vfsconf *vfsp;
+pefs_uninit(struct vfsconf *vfsp)
{
-
+ pefs_crypto_uninit();
mtx_destroy(&pefs_hashmtx);
free(pefs_node_hashtbl, M_PEFSHASH);
+ uma_zdestroy(pefs_node_zone);
return (0);
}
@@ -166,36 +175,119 @@
}
static void
-pefs_insmntque_dtr(struct vnode *vp, void *xp)
+pefs_insmntque_dtr(struct vnode *vp, void *_pn)
{
+ struct pefs_node *pn = _pn;
+
+ PEFSDEBUG("pefs_insmntque_dtr: free node %p\n", pn);
vp->v_data = NULL;
vp->v_vnlock = &vp->v_lock;
- free(xp, M_PEFSNODE);
+ pefs_key_release(pn->pn_tkey.ptk_key);
+ uma_zfree(pefs_node_zone, pn);
vp->v_op = &dead_vnodeops;
(void) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
vgone(vp);
vput(vp);
}
+int
+pefs_node_lookup_name(struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, char *encname, int *encname_len)
+{
+ struct vnode *nldvp;
+ int error, locked, dlocked;
+ int buflen = *encname_len;
+
+ PEFSDEBUG("%s: lvp=%p, ldvp=%p, cred=%p\n", __func__, lvp, ldvp, cred);
+ ASSERT_VOP_LOCKED(lvp, "pefs_node_lookup_name");
+ locked = VOP_ISLOCKED(lvp);
+ if (ldvp) {
+ dlocked = VOP_ISLOCKED(ldvp);
+ if (dlocked)
+ VOP_UNLOCK(ldvp, 0);
+ } else {
+ dlocked = 0;
+ }
+
+ vref(lvp);
+ VOP_UNLOCK(lvp, 0);
+ nldvp = lvp;
+ error = vn_vptocnp(&nldvp, cred, encname, encname_len);
+ PEFSDEBUG("%s: vn_vptocnp(dvp) result %d; nldvp=%p; ldvp=%p, len=%d\n", __func__, error, nldvp, ldvp, *encname_len);
+ if (!error)
+ vdrop(nldvp);
+ vrele(lvp);
+ vn_lock(lvp, locked | LK_RETRY);
+ if (ldvp && dlocked)
+ vn_lock(ldvp, dlocked | LK_RETRY);
+ if (error)
+ return (ENOENT);
+
+ memcpy(encname, encname + *encname_len, buflen - *encname_len);
+ *encname_len = buflen - *encname_len;
+ if (*encname_len < buflen)
+ encname[*encname_len] = '\0';
+ PEFSDEBUG("%s: len=%d %s\n", __func__, *encname_len, encname);
+
+ return 0;
+}
+
+static int
+pefs_node_lookup_key(struct pefs_mount *pm, struct vnode *lvp, struct vnode *ldvp, struct ucred *cred, struct pefs_tkey *ptk)
+{
+ char *namebuf;
+ char *encname;
+ int error, encname_len, name_len;
+
+ namebuf = malloc((MAXNAMLEN + 1)*2, M_PEFSBUF, M_WAITOK | M_ZERO);
+ encname = namebuf + MAXNAMLEN + 1;
+ encname_len = MAXNAMLEN + 1;
+
+ error = pefs_node_lookup_name(lvp, ldvp, cred, encname, &encname_len);
+ if (!error) {
+ free(namebuf, M_PEFSBUF);
+ return (error);
+ }
+
+ PEFSDEBUG("%s: encname_len=%d; encname=%s\n", __func__, encname_len,
+ encname);
+
+ name_len = pefs_name_decrypt(NULL, pefs_rootkey(pm), ptk,
+ encname, encname_len,
+ namebuf, MAXNAMLEN + 1);
+
+ if (name_len < 0) {
+ PEFSDEBUG("%s: not found: %.*s\n", __func__, encname_len, encname);
+ error = 0;
+ } else {
+ pefs_key_ref(ptk->ptk_key);
+ }
+
+ free(namebuf, M_PEFSBUF);
+
+ return (error);
+}
+
/*
* Make a new or get existing pefs node.
- * Vp is the alias vnode, lowervp is the lower vnode.
+ * vp is the alias vnode
+ * lvp is the lower vnode
+ * ldvp is the lower directory vnode, used if no key specified
*
- * The lowervp assumed to be locked and having "spare" reference. This routine
- * vrele lowervp if pefs node was taken from hash. Otherwise it "transfers"
+ * The lvp assumed to be locked and having "spare" reference. This routine
+ * vrele lvp if pefs node was taken from hash. Otherwise it "transfers"
* the caller's "spare" reference to created pefs vnode.
*/
int
-pefs_node_get(struct mount *mp, struct vnode *lowervp, struct vnode **vpp, struct pefs_tkey *ptk)
+pefs_node_get(struct mount *mp, struct vnode *lvp, struct vnode *ldvp, struct vnode **vpp, struct ucred *cred, struct pefs_tkey *ptk)
{
struct pefs_node *xp;
struct vnode *vp;
int error;
/* Lookup the hash firstly */
- *vpp = pefs_hashget(mp, lowervp);
+ *vpp = pefs_hashget(mp, lvp);
if (*vpp != NULL) {
- vrele(lowervp);
+ vrele(lvp);
return (0);
}
@@ -203,7 +295,7 @@
* We do not serialize vnode creation, instead we will check for
* duplicates later, when adding new vnode to hash.
*
- * Note that duplicate can only appear in hash if the lowervp is
+ * Note that duplicate can only appear in hash if the lvp is
* locked LK_SHARED.
*/
@@ -212,26 +304,39 @@
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
- xp = malloc(sizeof(struct pefs_node),
- M_PEFSNODE, M_WAITOK | M_ZERO);
+ xp = uma_zalloc(pefs_node_zone, M_WAITOK | M_ZERO);
+
+ if (ptk != NULL && ptk->ptk_key != NULL) {
+ xp->pn_tkey = *ptk;
+ xp->pn_flags = PN_HASKEY;
+ pefs_key_ref(xp->pn_tkey.ptk_key);
+ } else if (mp->mnt_data != NULL && pefs_rootkey(VFS_TO_PEFS(mp)) != NULL) {
+ if (cred == NULL)
+ cred = curthread->td_ucred;
+ error = pefs_node_lookup_key(VFS_TO_PEFS(mp), lvp, ldvp, cred, &xp->pn_tkey);
+ if (error) {
+ uma_zfree(pefs_node_zone, xp);
+ return (error);
+ }
+ if (xp->pn_tkey.ptk_key != NULL)
+ xp->pn_flags = PN_HASKEY;
+ }
error = getnewvnode("pefs", mp, &pefs_vnodeops, &vp);
if (error) {
- free(xp, M_PEFSNODE);
+ pefs_key_release(xp->pn_tkey.ptk_key);
+ uma_zfree(pefs_node_zone, xp);
return (error);
}
- if (ptk != NULL)
- xp->pn_tkey = *ptk;
+ if (xp->pn_tkey.ptk_key == NULL)
+ PEFSDEBUG("%s: creating node without key: %p: %p->%p\n", __func__, xp, vp, lvp);
- if (!ptk)
- PEFSDEBUG("%s: creating node without key: %p: %p->%p\n", __func__, xp, vp, lowervp);
-
xp->pn_vnode = vp;
- xp->pn_lowervp = lowervp;
- vp->v_type = lowervp->v_type;
+ xp->pn_lowervp = lvp;
+ vp->v_type = lvp->v_type;
vp->v_data = xp;
- vp->v_vnlock = lowervp->v_vnlock;
+ vp->v_vnlock = lvp->v_vnlock;
if (vp->v_vnlock == NULL)
panic("pefs_node_get: Passed a NULL vnlock.\n");
error = insmntque1(vp, mp, pefs_insmntque_dtr, xp);
@@ -243,7 +348,7 @@
*/
*vpp = pefs_hashins(mp, xp);
if (*vpp != NULL) {
- vrele(lowervp);
+ vrele(lvp);
vp->v_vnlock = &vp->v_lock;
xp->pn_lowervp = NULL;
vrele(vp);
@@ -260,33 +365,28 @@
void
pefs_node_free(struct pefs_node *xp)
{
-
+ PEFSDEBUG("pefs_node_free: free node %p\n", xp);
mtx_lock(&pefs_hashmtx);
LIST_REMOVE(xp, pn_hash);
mtx_unlock(&pefs_hashmtx);
- free(xp, M_PEFSNODE);
+ pefs_key_release(xp->pn_tkey.ptk_key);
+ uma_zfree(pefs_node_zone, xp);
}
struct pefs_key*
pefs_node_key(struct pefs_node *pn)
{
- if (pn->pn_tkey.ptk_key == NULL) {
- PEFSDEBUG("!!!!! %s: key is not set: pn=%p\n", __func__, pn);
- // FIXME !!!!!
- pn->pn_tkey.ptk_key = SLIST_FIRST(&VFS_TO_PEFS(pn->pn_vnode->v_mount)->pm_keys);
- }
- return (pn->pn_tkey.ptk_key);
+ struct pefs_key *pk;
-}
-
-struct pefs_tkey*
-pefs_node_tkey(struct pefs_node *pn)
-{
- if (pn->pn_tkey.ptk_key == NULL) {
- pefs_node_key(pn);
+ if (pn->pn_flags & PN_HASKEY) {
+ MPASS(pn->pn_tkey.ptk_key != NULL);
+ pk = pn->pn_tkey.ptk_key;
+ } else {
+ MPASS(pn->pn_tkey.ptk_key == NULL);
+ pk = pefs_rootkey(VFS_TO_PEFS(pn->pn_vnode->v_mount));
}
- return (&pn->pn_tkey);
-
+ MPASS(pk != NULL);
+ return (pefs_key_ref(pk));
}
struct pefs_chunk*
@@ -296,7 +396,6 @@
int iovcnt;
iovcnt = (size + PAGE_SIZE - 1) / PAGE_SIZE;
- PEFSDEBUG("%s: length=%u; iovcnt=%d\n", __func__, size, iovcnt);
pc = malloc(sizeof(struct pefs_chunk) + (sizeof(void*) + sizeof(struct iovec) * 2) * iovcnt,
M_PEFSBUF, M_WAITOK | M_ZERO);
@@ -314,8 +413,8 @@
pc->pc_iov[i].iov_base = pc->pc_bases[i];
size -= len;
}
- if (size != 0)
- panic("pefs_chunk initialization error\n");
+
+ MPASS(size == 0);
return (pc);
}
@@ -335,6 +434,19 @@
}
}
+void*
+pefs_chunk_pullup(struct pefs_chunk *pc, size_t size)
+{
+ if (size > PAGE_SIZE)
+ panic("pefs_chunk_pullup: size > PAGE_SIZE");
+ if (pc->pc_iovcnt == 0)
+ panic("pefs_chunk_pullup: chunk is empty");
+ if (size > pc->pc_size || size > pc->pc_iov[0].iov_len)
+ panic("pefs_chunk_pullup: size is too large: %u, available %u",
+ size, min(pc->pc_size, pc->pc_iov[0].iov_len));
+ return (pc->pc_iov[0].iov_base);
+}
+
void
pefs_chunk_free(struct pefs_chunk* pc)
{
@@ -375,8 +487,6 @@
pc->pc_uio.uio_iov[i].iov_len = min(size, pc->pc_iov[skip_iov + i].iov_len - skip);
size -= pc->pc_uio.uio_iov[i].iov_len;
skip = 0;
- printf("%s: creating iov: i=%d; len=%d; base=%p\n", __func__, i,
- pc->pc_uio.uio_iov[i].iov_len, pc->pc_uio.uio_iov[i].iov_base);
}
pc->pc_uio.uio_iovcnt = i;
@@ -389,7 +499,7 @@
void *mem;
if (!size || !state || *state < 0)
- panic("invalid args");
+ panic("pefs_chunk_get: invalid args");
if (*state >= pc->pc_iovcnt) {
*size = 0;
return (NULL);
@@ -443,9 +553,6 @@
if (skip_begin + skip_end == 0)
return;
- PEFSDEBUG("%s: skip_begin=%d; skip_end=%d; size=%d\n", __func__,
- skip_begin, skip_end, pc->pc_size);
-
for (int i = 0; i < pc->pc_iovcnt && skip_begin; i++) {
struct iovec *iov = &pc->pc_iov[i];
@@ -504,9 +611,9 @@
* with a funny vop vector.
*/
if (vp->v_op != pefs_vnodeop_p) {
- printf ("pefs_checkvp: on non-null-node\n");
+ printf("pefs_checkvp: on non-null-node\n");
while (pefs_checkvp_barrier) /*WAIT*/ ;
- panic("pefs_checkvp");
+ panic("pefs_checkvp: on non-null-node");
};
#endif
if (a->pefs_lowervp == NULLVP) {
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vfsops.c#5 (text+ko) ====
@@ -67,9 +67,6 @@
int isvnunlocked = 0, len;
struct nameidata nd, *ndp = &nd;
- // FIXME
- struct pefs_key *pk;
-
PEFSDEBUG("pefs_mount(mp = %p)\n", (void *)mp);
if (mp->mnt_flag & MNT_ROOTFS)
@@ -132,17 +129,19 @@
return (EDEADLK);
}
- // FIXME
- pk = malloc(sizeof(struct pefs_key), M_PEFSBUF, M_WAITOK | M_ZERO);
- memset(pk->pk_data, 0xaa, PEFS_KEY_SIZE);
- memset(pk->pk_name, 0xbb, PEFS_KEY_SIZE);
+ xmp = (struct pefs_mount *) malloc(sizeof(struct pefs_mount),
+ M_PEFSMNT, M_WAITOK | M_ZERO); /* XXX */
- xmp = (struct pefs_mount *) malloc(sizeof(struct pefs_mount),
- M_PEFSMNT, M_WAITOK); /* XXX */
+ mtx_init(&xmp->pm_keys_lock, "pefs_mount lock", NULL, MTX_DEF);
+ LIST_INIT(&xmp->pm_keys);
- SLIST_INIT(&xmp->pm_keys);
+#if 0
// FIXME
- SLIST_INSERT_HEAD(&xmp->pm_keys, pk, pk_entry);
+ struct pefs_key *pk;
+ pk = pefs_key_get("a", 1);
+ pk->pk_entry_lock = &xmp->pm_keys_lock;
+ LIST_INSERT_HEAD(&xmp->pm_keys, pk, pk_entry);
+#endif
/*
* Save reference to underlying FS
@@ -153,7 +152,7 @@
* Save reference. Each mount also holds
* a reference on the root vnode.
*/
- error = pefs_node_get(mp, lowerrootvp, &vp, NULL);
+ error = pefs_node_get(mp, lowerrootvp, NULL, &vp, NULL, NULL);
/*
* Make sure the node alias worked
*/
@@ -220,8 +219,16 @@
*/
pm = VFS_TO_PEFS(mp);
mp->mnt_data = 0;
- //FIXME
- free(SLIST_FIRST(&pm->pm_keys), M_PEFSMNT);
+ mtx_lock(&pm->pm_keys_lock);
+ while (!LIST_EMPTY(&pm->pm_keys)) {
+ struct pefs_key *pk = LIST_FIRST(&pm->pm_keys);
+
+ LIST_REMOVE(pk, pk_entry);
+ pk->pk_entry_lock = NULL;
+ pefs_key_release(pk);
+ }
+ mtx_unlock(&pm->pm_keys_lock);
+ mtx_destroy(&pm->pm_keys_lock);
free(pm, M_PEFSMNT);
return 0;
}
@@ -302,7 +309,7 @@
if (error)
return (error);
- return (pefs_node_get(mp, *vpp, vpp, NULL));
+ return (pefs_node_get(mp, *vpp, NULL, vpp, NULL, NULL));
}
static int
@@ -314,7 +321,7 @@
if (error)
return (error);
- error = pefs_node_get(mp, *vpp, vpp, NULL);
+ error = pefs_node_get(mp, *vpp, NULL, vpp, NULL, NULL);
printf("pefs_fhtovp: error=%d; vp=%p; v_object=%p\n", error,
!error ? *vpp : NULL, !error ? (*vpp)->v_object : NULL);
if (error)
@@ -346,4 +353,4 @@
};
VFS_SET(pefs_vfsops, pefs, VFCF_LOOPBACK);
-MODULE_DEPEND(pefs, rc4, 1, 1, 1);
+MODULE_DEPEND(pefs, salsa20, 1, 1, 1);
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#6 (text+ko) ====
@@ -65,16 +65,6 @@
SYSCTL_INT(_debug, OID_AUTO, pefs_bug_bypass, CTLFLAG_RW,
&pefs_bug_bypass, 0, "");
-const static struct {
- size_t namelen;
- const char *name;
-} _pefs_name_skip_list[] = {
- { 4, ".zfs" },
- { 5, ".snap" },
- { 10, "lost+found" },
- { 0, NULL },
-};
-
struct pefs_enccn {
struct componentname pec_cn;
void *pec_buf;
@@ -86,12 +76,6 @@
{
if (name[0] == '.' && (namelen == 1 || (namelen == 2 && name[1] == '.')))
return (1);
- for (int i = 0; _pefs_name_skip_list[i].namelen &&
- _pefs_name_skip_list[i].namelen <= namelen; i++) {
- if (namelen == _pefs_name_skip_list[i].namelen &&
- memcmp(_pefs_name_skip_list[i].name, name, namelen) == 0)
- return (1);
- }
return (0);
}
@@ -135,7 +119,7 @@
pec->pec_tkey.ptk_key = pk;
PEFSDEBUG("%s: pk=%p\n", __func__, pk);
pec->pec_buf = uma_zalloc(namei_zone, M_WAITOK);
- r = pefs_name_encrypt(&pec->pec_tkey,
+ r = pefs_name_encrypt(NULL, &pec->pec_tkey,
cnp->cn_nameptr, cnp->cn_namelen, pec->pec_buf, MAXPATHLEN);
if (r <= 0) {
uma_zfree(namei_zone, pec->pec_buf);
@@ -165,26 +149,30 @@
static struct dirent*
pefs_enccn_lookup_dirent(struct pefs_key *pk, struct pefs_tkey *ptk, void *mem, size_t sz, char *name, int namelen, char *buf, size_t buf_sz)
{
+ struct pefs_ctx *ctx;
struct dirent *de;
int d_namelen;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list