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