Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 06 Jun 2012 17:05:54 +0000
From:      gpf@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r237225 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs
Message-ID:  <20120606170554.B9CA0106566B@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gpf
Date: Wed Jun  6 17:05:54 2012
New Revision: 237225
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237225

Log:
  -extend ioctl() so that it can retrieve an encrypted target filename from
  kerneland in case of symlink.
  -make sbin/pefs use that ioctl() to generate checksum for encrypted target
  filename in case of symlink.
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
  soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h
  soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Wed Jun  6 16:51:33 2012	(r237224)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Wed Jun  6 17:05:54 2012	(r237225)
@@ -55,7 +55,7 @@
 
 #include "pefs_ctl.h"
 
-#define PEFS_INTEGRITY_DEBUG
+//#define PEFS_INTEGRITY_DEBUG
 #if defined (PEFS_INTEGRITY_DEBUG)
 #define dprintf(a)		printf a
 #else
@@ -166,10 +166,83 @@
 }
 
 static int
-pefs_compute_file_checksums(struct file_header *fhp, const EVP_MD *md,
+pefs_compute_symlink_checksum(struct file_header *fhp, const EVP_MD *md,
 	uint8_t hash_len)
 {
+	struct pefs_xslink_ctext xsl;
+	char parent_dir[MAXPATHLEN];
+	EVP_MD_CTX mdctx;
+	int error, i, fd, md_len;
+	struct checksum *csp;
+	char *pch;
+
+	fhp->nhashes = 0;
+
+	/* feed parent directory to ioctl() */
+	strlcpy(parent_dir, fhp->path, sizeof(parent_dir));
+	pch = strrchr(parent_dir, '/');
+	if (pch == NULL) {
+		pefs_warn("error retrieving parent dir of %s", fhp->path);
+		return (PEFS_ERR_NOENT);
+	}
+	*pch = '\0';
+
+	strlcpy(xsl.pxsl_filename, pch + 1, sizeof(xsl.pxsl_filename));
+	xsl.pxsl_namelen = strnlen(xsl.pxsl_filename, sizeof(xsl.pxsl_filename));
+
+	fd = open(parent_dir, O_RDONLY);
+	if (fd < 0) {
+		warn("failed to open file: %s", parent_dir);
+		return (PEFS_ERR_IO);
+	}
 
+	error = ioctl(fd, PEFS_GETSLINKCTEXT, &xsl);
+	if (error != 0) {
+		pefs_warn("error retrieving symlink's ciphertext of %s", fhp->path);
+		close(fd);
+		return (PEFS_ERR_IO);
+	}
+
+	dprintf(("read %d bytes from kernel\n\n", xsl.pxsl_slink_len));
+	dprintf(("printing contents of buf:"));
+	for (i=0; i < (int)xsl.pxsl_slink_len; i++) dprintf(("%c", xsl.pxsl_slink[i]));
+	dprintf(("!\n"));
+
+	EVP_MD_CTX_init(&mdctx);
+	EVP_DigestInit_ex(&mdctx, md, NULL);
+	EVP_DigestUpdate(&mdctx, xsl.pxsl_slink, xsl.pxsl_slink_len);
+
+	csp = malloc(sizeof(struct checksum));
+	if (csp == NULL) {
+		pefs_warn("memory allocation error");
+		close(fd);
+		return (PEFS_ERR_SYS);
+	}
+	csp->hash = malloc(hash_len);
+	if (csp->hash == NULL) {
+		pefs_warn("memory allocation error");
+		free(csp);
+		close(fd);
+		return (PEFS_ERR_SYS);
+	}
+
+	EVP_DigestFinal_ex(&mdctx, csp->hash, &md_len);
+
+	dprintf(("Digest is: "));
+	for (i = 0; i < md_len; i++) dprintf(("%02x", csp->hash[i]));
+	dprintf(("\n"));
+
+	EVP_MD_CTX_cleanup(&mdctx);
+	TAILQ_INSERT_TAIL(&(fhp->checksums), csp, checksum_entries);
+	fhp->nhashes++;
+
+	return (0);
+}
+
+static int
+pefs_compute_file_checksums(struct file_header *fhp, const EVP_MD *md,
+	uint8_t hash_len)
+{
 	struct pefs_xsector_ctext xsct;
 	EVP_MD_CTX mdctx;
 	struct stat sb;
@@ -180,23 +253,22 @@
 
 	TAILQ_INIT(&(fhp->checksums));
 
-	/*
-	 * XXXgpf: [TODO] deal with symlinks
-	 */
-
 	/* XXXgpf: what happens if file size > 2^64? */
-	if (stat(fhp->path, &sb) != 0) {
+	if (lstat(fhp->path, &sb) != 0) {
 		warn("cannot stat file %s", fhp->path);
 		return (PEFS_ERR_SYS);
 	}
 
+	if (S_ISLNK(sb.st_mode) != 0)
+		return(pefs_compute_symlink_checksum(fhp, md, hash_len));
+
 	resid = sb.st_size;
 	if (resid == 0) {
 		pefs_warn("empty files are not allowed: %s", fhp->path);
 		return (PEFS_ERR_INVALID);
 	}
 
-	fd = open(fhp->path, O_RDONLY);
+	fd = open(fhp->path, O_RDONLY | O_NOFOLLOW);
 	if (fd < 0) {
 		warn("failed to open file: %s", fhp->path);
 		return (PEFS_ERR_IO);

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Wed Jun  6 16:51:33 2012	(r237224)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Wed Jun  6 17:05:54 2012	(r237225)
@@ -61,6 +61,13 @@
 	char			pxsct_ctext[PEFS_SECTOR_SIZE];
 };
 
+struct pefs_xslink_ctext {
+	uint32_t		pxsl_namelen;
+	uint32_t		pxsl_slink_len;
+	char			pxsl_filename[MAXPATHLEN];
+	char			pxsl_slink[PEFS_SECTOR_SIZE];
+};
+
 #ifdef _IO
 #define	PEFS_GETKEY			_IOWR('p', 0, struct pefs_xkey)
 #define	PEFS_ADDKEY			_IOWR('p', 1, struct pefs_xkey)
@@ -70,6 +77,7 @@
 #define	PEFS_GETNODEKEY			_IOWR('p', 5, struct pefs_xkey)
 #define PEFS_GETNAMECSUM		_IOWR('p', 6, struct pefs_xnamecsum)
 #define PEFS_GETSECTORCTEXT		_IOWR('p', 7, struct pefs_xsector_ctext)
+#define PEFS_GETSLINKCTEXT		_IOWR('p', 8, struct pefs_xslink_ctext)
 #endif
 
 #ifdef _KERNEL

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Wed Jun  6 16:51:33 2012	(r237224)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Wed Jun  6 17:05:54 2012	(r237225)
@@ -2358,12 +2358,15 @@
 	struct pefs_enccn enccn;
 	struct componentname cn;
 	struct pefs_chunk pc;
+	struct vop_cachedlookup_args la;
 	u_quad_t fsize;
 	struct vnode *vp = ap->a_vp;
 	struct vnode *lvp = PEFS_LOWERVP(vp);
+	struct vnode *svp;
 	struct pefs_xkey *xk = ap->a_data;
 	struct pefs_xnamecsum *xncs = ap->a_data;
 	struct pefs_xsector_ctext *xsct = ap->a_data;
+	struct pefs_xslink_ctext *xsl = ap->a_data;
 	struct ucred *cred = ap->a_cred;
 	struct thread *td = ap->a_td;
 	struct mount *mp = vp->v_mount;
@@ -2531,13 +2534,13 @@
 
 		if (strnlen(xncs->pxnc_filename, sizeof(xncs->pxnc_filename)) !=
 			xncs->pxnc_namelen) {
-			printf("pefs_ioctl: PEFS_GETNAMEMAC incorrect pnm_namelen %d\n", xncs->pxnc_namelen);
+			printf("pefs_ioctl: PEFS_GETNAMEMAC incorrect pxnc_namelen %d\n", xncs->pxnc_namelen);
 			VOP_UNLOCK(vp, 0);
 			return (EINVAL);
 		}
 
 		if (strchr(xncs->pxnc_filename, '/') != NULL) {
-			printf("pefs_ioctl: PEFS_GETNAMEMAC pnm_filename contains '/'\n");
+			printf("pefs_ioctl: PEFS_GETNAMEMAC pxnc_filename contains '/'\n");
 			VOP_UNLOCK(vp, 0);
 			return (EINVAL);
 		}
@@ -2580,6 +2583,80 @@
 			free(buf, M_TEMP);
 		}
 		break;
+	case PEFS_GETSLINKCTEXT:
+		vn_lock(vp, LK_EXCLUSIVE);
+
+		if (vp->v_type != VDIR) {
+			printf("pefs_ioctl: PEFS_GETSLINKCTEXT vp is not a directory\n");
+			VOP_UNLOCK(vp, 0);
+			return (EINVAL);
+		}
+
+		if (strnlen(xsl->pxsl_filename, sizeof(xsl->pxsl_filename)) !=
+			xsl->pxsl_namelen) {
+			printf("pefs_ioctl: PEFS_GETSLINKCTEXT incorrect namelen %d\n", xsl->pxsl_namelen);
+			VOP_UNLOCK(vp, 0);
+			return (EINVAL);
+		}
+
+		if (strchr(xsl->pxsl_filename, '/') != NULL) {
+			printf("pefs_ioctl: PEFS_GETSLINKCTEXT filename contains '/'\n");
+			VOP_UNLOCK(vp, 0);
+			return (EINVAL);
+		}
+
+		/* pefs_lookup() so that we can grab a vp for our symlink */
+		la.a_dvp = vp;
+		la.a_vpp = &svp;
+		la.a_cnp = &cn;
+
+		cn.cn_nameiop = LOOKUP;
+		cn.cn_thread = td;
+		cn.cn_cred = cred;
+		cn.cn_lkflags = LK_EXCLUSIVE;
+		cn.cn_flags = LOCKPARENT | LOCKLEAF | NOFOLLOW;
+		cn.cn_nameptr = xsl->pxsl_filename;
+		cn.cn_namelen = xsl->pxsl_namelen;
+		cn.cn_pnbuf = NULL;
+		cn.cn_consume = 0;
+
+		/*
+		 * XXXgpf: if lookup succeeds, it should(?) raise reference count for svp
+		 * by one, therefore a vrele is needed before we return? For both svp & lvp?
+		 */
+		error = pefs_lookup(&la);
+		if (error != 0) {
+			printf("pefs_ioctl: PEFS_GETSLINKCTEXT lookup error %d", error);
+			VOP_UNLOCK(vp, 0);
+			return (EINVAL);
+		}
+
+		if (svp->v_type != VLNK) {
+			printf("pefs_ioctl: PEFS_GETSLINKCTEXT svp is not a symlink '/'\n");
+			VOP_UNLOCK(svp, 0);
+			VOP_UNLOCK(vp, 0);
+			return (EINVAL);
+		}
+
+		/* VOP_READLINK our lvp */
+		lvp = PEFS_LOWERVP(svp);
+		pn = VP_TO_PN(svp);
+		pefs_chunk_create(&pc, pn, MAXPATHLEN);
+		puio = pefs_chunk_uio(&pc, 0, UIO_READ);
+
+		/* XXXgpf: is this lock really necessary? */
+		vn_lock(lvp, LK_EXCLUSIVE);
+		error = VOP_READLINK(lvp, puio, cred);
+		VOP_UNLOCK(lvp, 0);
+
+		xsl->pxsl_slink_len = pc.pc_size - pc.pc_uio.uio_resid;
+		if (error == 0)
+			memcpy(xsl->pxsl_slink, pc.pc_base, xsl->pxsl_slink_len);
+
+		pefs_chunk_free(&pc, pn);
+		VOP_UNLOCK(svp, 0);
+		VOP_UNLOCK(vp, 0);
+		break;
 	default:
 		error = ENOTTY;
 		break;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120606170554.B9CA0106566B>