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>