PERFORCE change 164284 for review
Gleb Kurtsou
gk at FreeBSD.org
Sat Jun 13 16:49:50 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164284
Change 164284 by gk at gk_h1 on 2009/06/13 16:49:12
basic cryptographic functionality
Affected files ...
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#2 edit
.. //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_xbase64.c#1 add
.. //depot/projects/soc2009/gk_pefs/sys/modules/pefs/Makefile#2 edit
Differences ...
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs.h#2 (text+ko) ====
@@ -37,6 +37,8 @@
* $FreeBSD$
*/
+#include <sys/uio.h>
+
struct pe_mount {
struct mount *pem_vfs;
struct vnode *pem_rootvp; /* Reference to root pe_node */
@@ -52,15 +54,35 @@
struct vnode *pe_vnode; /* Back pointer */
};
+struct pe_xuio {
+ struct uio xuio_uio;
+ void **xuio_bases;
+};
+
+typedef void (*pe_tr)(void *mem, size_t size, void *arg);
+
#define MOUNTTOPEMOUNT(mp) ((struct pe_mount *)((mp)->mnt_data))
#define VTOPE(vp) ((struct pe_node *)(vp)->v_data)
#define PETOV(xp) ((xp)->pe_vnode)
+struct vfsconf;
+struct vop_generic_args;
+
int pefs_init(struct vfsconf *vfsp);
int pefs_uninit(struct vfsconf *vfsp);
int pe_nodeget(struct mount *mp, struct vnode *target, struct vnode **vpp);
void pe_hashrem(struct pe_node *xp);
int pe_bypass(struct vop_generic_args *ap);
+struct pe_xuio* pe_xuio_create(struct uio* uio);
+void pe_xuio_finish(struct pe_xuio* xuio, struct uio *src);
+void pe_xuio_transfrom(struct pe_xuio *xuio, struct uio *src, pe_tr tr, void *arg);
+int pe_name_encrypt(const char *plain, size_t plain_len, char *enc, size_t enc_size);
+int pe_name_decrypt(const char *enc, size_t enc_len, char *plain, size_t plain_size);
+
+void pe_xor(void *mem, size_t size, void *arg);
+
+int pe_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
+int pe_b64_pton(char const *src, size_t srclen, u_char *target, size_t targsize);
#ifdef DIAGNOSTIC
struct vnode *pe_checkvp(struct vnode *vp, char *fil, int lno);
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_subr.c#2 (text+ko) ====
@@ -45,6 +45,7 @@
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/proc.h>
+#include <sys/uio.h>
#include <sys/vnode.h>
#include <fs/pefs/pefs.h>
@@ -69,6 +70,7 @@
static MALLOC_DEFINE(M_PEFSHASH, "pefs_hash", "PEFS hash table");
MALLOC_DEFINE(M_PEFSNODE, "pefs_node", "PEFS vnode private part");
+static MALLOC_DEFINE(M_PEFSBUF, "pefs_buf", "PEFS buffers");
static struct vnode * pe_hashget(struct mount *, struct vnode *);
static struct vnode * pe_hashins(struct mount *, struct pe_node *);
@@ -186,7 +188,7 @@
/*
* Make a new or get existing pefs node.
* Vp is the alias vnode, lowervp is the lower vnode.
- *
+ *
* 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 caller's "spare" reference to created pefs vnode.
@@ -241,7 +243,7 @@
if (error != 0)
return (error);
/*
- * Atomically insert our new node into the hash or vget existing
+ * Atomically insert our new node into the hash or vget existing
* if someone else has beaten us to it.
*/
*vpp = pe_hashins(mp, xp);
@@ -270,6 +272,121 @@
mtx_unlock(&pe_hashmtx);
}
+void
+pe_xor(void *mem, size_t size, void *arg)
+{
+ char *b = (char *)mem;
+ char *e = b + size;
+
+ for (; b < e; b++) {
+ *b ^= 0xAA;
+ }
+}
+
+int
+pe_name_encrypt(const char *plain, size_t plain_len, char *enc, size_t enc_size)
+{
+ char b_static[64];
+ char *b;
+ int r;
+
+ if (plain_len <= sizeof(b_static))
+ b = b_static;
+ else
+ b = malloc(plain_len, M_PEFSBUF, M_WAITOK);
+ memcpy(b, plain, plain_len);
+ // FIXME
+ for (int i = 0; i < plain_len; i++)
+ b[i] ^= 0xAA;
+ r = pe_b64_ntop(b, plain_len, enc, enc_size);
+ printf("pe_name_encrypt: %d; %.*s => %.*s\n", r, plain_len, plain, r, enc);
+ if (b != b_static)
+ free(b, M_PEFSBUF);
+ return r;
+}
+
+int
+pe_name_decrypt(const char *enc, size_t enc_len, char *plain, size_t plain_size)
+{
+ int r;
+
+ r = pe_b64_pton(enc, enc_len, plain, plain_size);
+ if (r > 0) {
+ // FIXME
+ for (int i = 0; i < r; i++)
+ plain[i] ^= 0xAA;
+ }
+ printf("pe_name_decrypt: %d; %.*s => %.*s\n", r, enc_len, enc, r < 0 ? 0 : r, plain);
+ return r;
+}
+
+struct pe_xuio*
+pe_xuio_create(struct uio* uio)
+{
+ struct pe_xuio *xuio;
+ size_t len;
+ int iov_cnt;
+
+ len = 0;
+ for (int i = 0; i < uio->uio_iovcnt; i++) {
+ len += uio->uio_iov[i].iov_len;
+ }
+
+ iov_cnt = (len + PAGE_SIZE - 1) / PAGE_SIZE;
+ xuio = malloc(sizeof(struct pe_xuio) + (sizeof(void*) + sizeof(struct iovec)) * iov_cnt,
+ M_PEFSBUF, M_WAITOK);
+ xuio->xuio_uio = *uio;
+ xuio->xuio_uio.uio_segflg = UIO_SYSSPACE;
+ xuio->xuio_uio.uio_iov = (struct iovec *)(xuio + 1);
+ xuio->xuio_bases = (void **)(xuio->xuio_uio.uio_iov + iov_cnt);
+ for (int i = 0; i < iov_cnt; i++) {
+ xuio->xuio_uio.uio_iov[i].iov_len = imin(PAGE_SIZE, len);
+ len -= PAGE_SIZE;
+ xuio->xuio_bases[i] = xuio->xuio_uio.uio_iov[i].iov_base =
+ malloc(xuio->xuio_uio.uio_iov[i].iov_len, M_PEFSBUF, M_WAITOK);
+ }
+
+ return (xuio);
+}
+
+void
+pe_xuio_finish(struct pe_xuio* xuio, struct uio *src)
+{
+ src->uio_offset = xuio->xuio_uio.uio_offset;
+ src->uio_resid = xuio->xuio_uio.uio_resid;
+ for (int i = 0; i < xuio->xuio_uio.uio_iovcnt; i++) {
+ free(xuio->xuio_bases[i], M_PEFSBUF);
+ }
+ free(xuio, M_PEFSBUF);
+}
+
+void
+pe_xuio_transfrom(struct pe_xuio *_xuio, struct uio *src, pe_tr tr, void *arg)
+{
+ struct uio *xuio = &_xuio->xuio_uio;
+
+ KASSERT(xuio->uio_segflg == UIO_SYSSPACE && xuio->uio_rw == src->uio_rw,
+ ("pe_uio_transfrom"));
+ for (int i = 0; i < xuio->uio_iovcnt; i++) {
+ int n;
+ void *base = xuio->uio_iov[i].iov_base;
+
+ if (xuio->uio_rw == UIO_READ) {
+ n = src->uio_iov[i].iov_len - xuio->uio_iov[i].iov_len;
+ base = ((caddr_t) base) - n;
+ } else {
+ n = src->uio_iov[i].iov_len;
+ }
+ if (xuio->uio_rw == UIO_WRITE)
+ uiomove(base, n, src);
+ if (tr)
+ tr(base, n, arg);
+ if (xuio->uio_rw == UIO_READ)
+ uiomove(base, n, src);
+ }
+}
+
+
#ifdef DIAGNOSTIC
#ifdef KDB
==== //depot/projects/soc2009/gk_pefs/sys/fs/pefs/pefs_vnops.c#2 (text+ko) ====
@@ -181,6 +181,7 @@
#include <sys/namei.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
+#include <sys/dirent.h>
#include <fs/pefs/pefs.h>
@@ -189,10 +190,70 @@
#include <vm/vm_object.h>
#include <vm/vnode_pager.h>
-static int pe_bug_bypass = 0; /* for debugging: enables bypass printf'ing */
-SYSCTL_INT(_debug, OID_AUTO, pefs_bug_bypass, CTLFLAG_RW,
+static int pe_bug_bypass = 1; /* for debugging: enables bypass printf'ing */
+SYSCTL_INT(_debug, OID_AUTO, pefs_bug_bypass, CTLFLAG_RW,
&pe_bug_bypass, 0, "");
+const static struct {
+ size_t namelen;
+ const char *name;
+} _pe_name_shadow_list[] = {
+ { 1, "." },
+ { 2, ".." },
+ { 4, ".zfs" },
+ { 5, ".snap" },
+ { 10, "lost+found" },
+ { 0, NULL },
+};
+
+static int
+pe_name_shadow(char *name, int namelen, /*OPTIONAL*/ struct componentname *cnp)
+{
+ if (cnp != NULL && cnp->cn_flags & ISDOTDOT)
+ return (0);
+ for (int i = 0; _pe_name_shadow_list[i].namelen && _pe_name_shadow_list[i].namelen <= namelen; i++) {
+ if (namelen == _pe_name_shadow_list[i].namelen &&
+ memcmp(_pe_name_shadow_list[i].name, name, namelen) == 0)
+ return (0);
+ }
+ return (1);
+}
+
+static int
+pe_cn_shadow_create(struct componentname *cnp, struct componentname *o_cnp)
+{
+ char *pnbuf;
+ int r;
+
+ pnbuf = uma_zalloc(namei_zone, M_WAITOK);
+ r = pe_name_encrypt(cnp->cn_nameptr, cnp->cn_namelen, pnbuf, MAXPATHLEN);
+ if (r <= 0) {
+ uma_zfree(namei_zone, pnbuf);
+ return (EIO);
+ }
+ *o_cnp = *cnp;
+ cnp->cn_pnbuf = pnbuf;
+ cnp->cn_nameptr = pnbuf;
+ cnp->cn_namelen = r;
+ cnp->cn_consume = 0; // XXX??
+
+ printf("%s: ENC cn_nameiop=%lx, cn_pnbuf=%s; cn_nameptr=%.*s; cn_consume=%d, cn_namelen=%d\n",
+ __func__, cnp->cn_nameiop, cnp->cn_pnbuf, (int) cnp->cn_namelen, cnp->cn_nameptr,
+ (int) cnp->cn_consume, (int) cnp->cn_namelen);
+
+ return (0);
+}
+
+static void
+pe_cn_shadow_finish(struct componentname *cnp, const struct componentname *o_cnp)
+{
+ uma_zfree(namei_zone, cnp->cn_pnbuf);
+ cnp->cn_pnbuf = o_cnp->cn_pnbuf;
+ cnp->cn_nameptr = o_cnp->cn_nameptr;
+ cnp->cn_namelen = o_cnp->cn_namelen;
+ cnp->cn_consume = o_cnp->cn_consume;
+}
+
/*
* This is the 10-Apr-92 bypass routine.
* This version has been optimized for speed, throwing away some
@@ -339,14 +400,25 @@
pe_lookup(struct vop_lookup_args *ap)
{
struct componentname *cnp = ap->a_cnp;
+ struct componentname o_cnp = *ap->a_cnp;
struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp, *ldvp, *lvp;
int flags = cnp->cn_flags;
- struct vnode *vp, *ldvp, *lvp;
+ int shadow;
int error;
+ printf("%s: cn_nameiop=%lx, cn_pnbuf=%s; cn_nameptr=%.*s; cn_consume=%d, cn_namelen=%d\n",
+ __func__, cnp->cn_nameiop, cnp->cn_pnbuf, (int) cnp->cn_namelen, cnp->cn_nameptr,
+ (int) cnp->cn_consume, (int) cnp->cn_namelen);
+
if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
return (EROFS);
+
+ shadow = pe_name_shadow(cnp->cn_nameptr, cnp->cn_namelen, cnp);
+ if (shadow)
+ pe_cn_shadow_create(cnp, &o_cnp);
+
/*
* Although it is possible to call pe_bypass(), we'll do
* a direct call to reduce overhead
@@ -359,6 +431,9 @@
(cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME))
error = EROFS;
+ if (shadow)
+ pe_cn_shadow_finish(cnp, &o_cnp);
+
if ((error == 0 || error == EJUSTRETURN) && lvp != NULL) {
if (ldvp == lvp) {
*ap->a_vpp = dvp;
@@ -499,7 +574,7 @@
vrele(fvp);
return (EXDEV);
}
-
+
return (pe_bypass((struct vop_generic_args *)ap));
}
@@ -620,7 +695,7 @@
* on the underlying filesystem. For now we just have to release lowervp
* as soon as possible.
*
- * Note, we can't release any resources nor remove vnode from hash before
+ * Note, we can't release any resources nor remove vnode from hash before
* appropriate VXLOCK stuff is is done because other process can find this
* vnode in hash during inactivation and may be sitting in vget() and waiting
* for pe_inactive to unlock vnode. Thus we will do all those in VOP_RECLAIM.
@@ -715,6 +790,138 @@
return VOP_VPTOFH(lvp, ap->a_fhp);
}
+static void
+pe_readdir_tr(void *mem, size_t sz, void *arg)
+{
+ struct dirent *de;
+ char d_name[MAXNAMLEN];
+ int d_namelen;
+ int de_len;
+
+ // FIXME
+ for (de = (struct dirent*) mem; sz > 0;
+ sz -= de_len,
+ de = (struct dirent *)(((caddr_t)de) + de_len)) {
+ de_len = GENERIC_DIRSIZ(de);
+ if (!pe_name_shadow(de->d_name, de->d_namlen, NULL))
+ continue;
+ d_namelen = pe_name_decrypt(de->d_name, de->d_namlen, d_name, sizeof(d_name));
+ printf("%s =>; res=%d; %.*s --> %.*s\n", __func__, d_namelen,
+ de->d_namlen, de->d_name,
+ d_namelen < 0 ? 0 : d_namelen, d_name);
+ if (d_namelen > 0) {
+ /*
+ * Do not change d_reclen
+ */
+ strlcpy(de->d_name, d_name, de->d_namlen + 1);
+ de->d_namlen = d_namelen;
+ }
+ }
+}
+
+static int
+pe_readdir(struct vop_readdir_args *ap)
+{
+ struct uio *uio = ap->a_uio;
+ struct pe_xuio *xuio;
+ int error;
+
+ if (0)
+ pe_readdir_tr(0, 0, 0);
+ xuio = pe_xuio_create(uio);
+ ap->a_uio = &xuio->xuio_uio;
+ error = pe_bypass((struct vop_generic_args *)ap);
+ ap->a_uio = uio;
+ printf("%s => %d; ncookies=%d\n", __func__, error, ap->a_ncookies ? *ap->a_ncookies : -1);
+ pe_xuio_transfrom(xuio, uio, pe_readdir_tr, NULL);
+ printf("%s: result _ iovec[0]: base=%p, len=%d\n", __func__,
+ uio->uio_iov[0].iov_base, uio->uio_iov[0].iov_len);
+ pe_xuio_finish(xuio, uio);
+ return (error);
+}
+
+static int
+pe_mkdir(struct vop_mkdir_args *ap)
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct componentname o_cnp;
+ int shadow, error;
+
+ shadow = pe_name_shadow(cnp->cn_nameptr, cnp->cn_namelen, cnp);
+ if (shadow)
+ pe_cn_shadow_create(cnp, &o_cnp);
+
+ printf("%s: cn_nameiop=%lx, cn_nameptr=%.*s\n",
+ __func__, cnp->cn_nameiop, (int) cnp->cn_namelen, cnp->cn_nameptr);
+ error = pe_bypass((struct vop_generic_args *)ap);
+
+ if (shadow)
+ pe_cn_shadow_finish(cnp, &o_cnp);
+
+ return (error);
+
+}
+
+static int
+pe_read(struct vop_read_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct pe_xuio *xuio;
+ struct vnode *lvp;
+ int error;
+
+ if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VDIR)
+ return (ENOTSUP);
+ if (uio->uio_resid == 0)
+ return (0);
+ if (uio->uio_offset < 0)
+ return (EINVAL);
+
+ printf("%s: uio_offset=%ju, uio_resid=%u, uio_segflg:sysspace=%d, uio_rw=%x, ioveccnt=%d\n",
+ __func__,
+ (intmax_t) uio->uio_offset, uio->uio_resid,
+ uio->uio_segflg == UIO_SYSSPACE, uio->uio_rw, uio->uio_iovcnt);
+ xuio = pe_xuio_create(uio);
+ lvp = PEVPTOLOWERVP(vp);
+ error = VOP_READ(lvp, &xuio->xuio_uio, ap->a_ioflag, ap->a_cred);
+ pe_xuio_transfrom(xuio, uio, pe_xor, NULL);
+ pe_xuio_finish(xuio, uio);
+
+ return (error);
+}
+
+static int
+pe_write(struct vop_write_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct uio *uio = ap->a_uio;
+ struct pe_xuio *xuio;
+ struct vnode *lvp;
+ int error;
+
+ if (vp->v_type == VCHR || vp->v_type == VBLK)
+ return (ENOTSUP);
+ if (vp->v_type == VDIR)
+ return (EISDIR);
+ if (uio->uio_resid == 0)
+ return (0);
+ if (uio->uio_offset < 0)
+ return (EINVAL);
+
+ printf("%s: uio_offset=%ju, uio_resid=%u, uio_segflg:sysspace=%d, uio_rw=%x, ioveccnt=%d\n",
+ __func__,
+ (intmax_t) uio->uio_offset, uio->uio_resid,
+ uio->uio_segflg == UIO_SYSSPACE, uio->uio_rw, uio->uio_iovcnt);
+ xuio = pe_xuio_create(uio);
+ pe_xuio_transfrom(xuio, uio, pe_xor, NULL);
+ lvp = PEVPTOLOWERVP(vp);
+ error = VOP_WRITE(lvp, &xuio->xuio_uio, ap->a_ioflag, ap->a_cred);
+ pe_xuio_finish(xuio, uio);
+
+ return (error);
+}
+
/*
* Global vfs data structures
*/
@@ -727,14 +934,27 @@
.vop_inactive = pe_inactive,
.vop_islocked = vop_stdislocked,
.vop_lock1 = pe_lock,
- .vop_lookup = pe_lookup,
.vop_open = pe_open,
.vop_print = pe_print,
.vop_reclaim = pe_reclaim,
- .vop_rename = pe_rename,
.vop_setattr = pe_setattr,
.vop_strategy = VOP_EOPNOTSUPP,
.vop_unlock = pe_unlock,
.vop_vptocnp = vop_stdvptocnp,
.vop_vptofh = pe_vptofh,
+ /* */
+ .vop_lookup = pe_lookup,
+ .vop_mkdir = pe_mkdir,
+ .vop_rmdir = VOP_EOPNOTSUPP,
+ .vop_create = VOP_EOPNOTSUPP,
+ .vop_remove = VOP_EOPNOTSUPP,
+ .vop_rename = pe_rename,
+ .vop_link = VOP_EOPNOTSUPP,
+ .vop_symlink = VOP_EOPNOTSUPP,
+ .vop_readlink = VOP_EOPNOTSUPP,
+ .vop_readdir = pe_readdir,
+ .vop_mknod = VOP_EOPNOTSUPP,
+ /* */
+ .vop_read = pe_read,
+ .vop_write = pe_write,
};
==== //depot/projects/soc2009/gk_pefs/sys/modules/pefs/Makefile#2 (text+ko) ====
@@ -4,7 +4,8 @@
KMOD= pefs
SRCS= vnode_if.h \
- pefs_subr.c pefs_vfsops.c pefs_vnops.c
+ pefs_subr.c pefs_vfsops.c pefs_vnops.c pefs_xbase64.c
+DEBUG_FLAGS= -g
.include <bsd.kmod.mk>
More information about the p4-projects
mailing list