socsvn commit: r237225 - in soc2012/gpf/pefs_kmod: sbin/pefs
sys/fs/pefs
gpf at FreeBSD.org
gpf at FreeBSD.org
Wed Jun 6 17:05:56 UTC 2012
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;
More information about the svn-soc-all
mailing list