Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 May 2012 16:26:07 +0000
From:      gpf@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r236400 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs sys/modules/pefs
Message-ID:  <20120525162607.7AB13106566C@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gpf
Date: Fri May 25 16:26:06 2012
New Revision: 236400
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=236400

Log:
  Require that .pefs.checksum is created outside of target pefs filesystem.
  
  Change pefs_ioctl() kernel panics into printfs() and error returns.
  

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

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Fri May 25 16:26:06 2012	(r236400)
@@ -227,7 +227,7 @@
 	if (checksum_hash_tablep->buckets != NULL) {
 		for (i = 0; i < checksum_hash_tablep->size; i++) {
 			bp = &checksum_hash_tablep->buckets[i];
-			LIST_FOREACH_SAFE(fhp, &(bp->file_headers), bucket_entries, tfhp) {				
+			LIST_FOREACH_SAFE(fhp, &(bp->file_headers), bucket_entries, tfhp) {
 				TAILQ_FOREACH_SAFE(csp, &(fhp->checksums), checksum_entries, tcsp) {
 					TAILQ_REMOVE(&(fhp->checksums), csp, checksum_entries);
 					if (csp->hash != NULL)
@@ -355,6 +355,8 @@
 
 	if (error == 0)
 		fhp->file_id = namemac.pnm_csum;
+	else
+		pefs_warn("failed to fetch file id from kernel");
 
 	close(fd);
 	return (error);
@@ -674,12 +676,52 @@
 }
 
 /*
+ * If .pefs.checksum is created inside pefs mounted fs, then it will obtain an
+ * encrypted filename & encrypted data, which is unacceptable. User should create
+ * checksum file outside of filesystem and then copy it by hand.
+ */
+static int
+pefs_open_checksum_file(int *fdp, char *fsroot, char *csm_path)
+{
+	struct statfs pefs_fs, checksum_fs;
+	int fd;
+
+	*fdp = -1;
+
+	fd = open(csm_path, O_WRONLY | O_CREAT | O_EXCL,  S_IRUSR | S_IWUSR);
+	if (fd == -1) {
+		warn("cannot open %s", csm_path);
+		return (PEFS_ERR_IO);
+	}
+
+	*fdp = fd;
+
+	if (statfs(fsroot, &pefs_fs) == -1) {
+		pefs_warn("statfs failed: %s: %s", fsroot, strerror(errno));
+		return (PEFS_ERR_SYS);
+	}
+
+	if (statfs(csm_path, &checksum_fs) == -1) {
+		pefs_warn("statfs failed: %s: %s", csm_path, strerror(errno));
+		return (PEFS_ERR_SYS);
+	}
+
+	if ((pefs_fs.f_fsid.val[0] == checksum_fs.f_fsid.val[0]) &&
+		(pefs_fs.f_fsid.val[1] == checksum_fs.f_fsid.val[1])) {
+		pefs_warn("%s must be created outside of pefs mounted filesystem %s",
+			csm_path, pefs_fs.f_mntonname);
+		return (PEFS_ERR_INVALID);
+	}
+
+	return (0);
+}
+
+/*
  * XXXgpf: [TODO] proper comment header, I am sleepy Z_Z
  */
 int
-pefs_create_checksum_file(FILE *fpin, char *fsroot, const char *algo)
+pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo)
 {
-	char checksum_path[MAXPATHLEN];
 	struct hash_table checksum_hash_table;
 	struct checksum_file_header cfh;
 	const EVP_MD *md;
@@ -695,21 +737,12 @@
 	}
 	hash_len = EVP_MD_size(md);
 
-	snprintf(checksum_path, sizeof(checksum_path), "%s/%s", fsroot, PEFS_FILE_CHECKSUM);
-	/*
-	 * XXXgpf: [TODO] If pefs fs is mounted when .pefs.checksum is created, then it will obtain an
-	 * encrypted filename & encrypted data. I should make sure that checksum file is not being
-	 * opened inside a mounted pefs filesystem.
-	 * pefs_open_checksum_file()
-	 */
-	fdout = open(checksum_path, O_WRONLY | O_CREAT | O_EXCL,  S_IRUSR | S_IWUSR);
-	if (fdout == -1) {
-		warn("cannot open %s", checksum_path);
-		return (PEFS_ERR_IO);
-	}
-
 	pefs_init_hash_table(&checksum_hash_table);
 
+	error = pefs_open_checksum_file(&fdout, fsroot, csm_path);
+	if (error != 0)
+		goto out;
+
 	error = pefs_create_in_memory_db(fpin, md, hash_len,
 		&checksum_hash_table, fsroot);
 	if (error != 0)
@@ -720,10 +753,11 @@
 	error = pefs_write_checksum_file(fdout, &cfh, &checksum_hash_table);
 
 out:
-	if (fdout >= 0)
+	if (fdout >= 0) {
 		close(fdout);
-	if (error != 0)
-		unlink(checksum_path);
+		if (error != 0)
+			unlink(csm_path);
+	}
 	pefs_free_hash_table(&checksum_hash_table);
 
 	return (error);

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Fri May 25 16:26:06 2012	(r236400)
@@ -1011,27 +1011,33 @@
 /*
  * XXXgpf: Instead of a man page entry:
  *
- * pefs addchecksum [-a algo] [-i inputfile] filesystem
+ * pefs addchecksum [-a algo] [-i inputfile] [-p path] filesystem
  *
  * $command creates .pefs.checksum db file for filesystem.
  * This file will contain all checksums necessary to check integrity
  * of files upon access.
  *
  * algo is the name of the algorithm to be used as a cryptographic
- * hash function; supported algorithms: sha256, sha512.
+ * hash function; supported algorithms: sha256, sha512. sha256 is
+ * used by default.
  *
- * inputfile contains list of files that need integrity checking.
+ * inputfile contains list of files that need integrity checking. An
+ * inputfile must be supplied.
+ *
+ * path defines where .pefs.checksum should be created. By default,
+ * .pefs.checksum is created under $PWD. path should be a directory,
+ * outside of target pefs filesystem.
  *
- * When $command is run, filesystem should be already mounted with 
+ * When $command is run, filesystem should be already mounted with
  * pefs.
- * 
- * [TODO] reference for where .pefs.checksum file should be created.
  *
  */
 static int
 pefs_addchecksum(int argc, char *argv[])
 {
 	char fsroot[MAXPATHLEN];
+	char csm_path[MAXPATHLEN];
+	struct stat sb;
 	FILE *fpin;
 	int error, i, j;
 	const char *algo;
@@ -1039,8 +1045,11 @@
 	fpin = NULL;
 	/* by default use sha256 */
 	algo = supported_digests[0];
+	/* by default create checksum file under $PWD */
+	snprintf(csm_path, sizeof(csm_path), "./%s", PEFS_FILE_CHECKSUM);
 
-	while ((i = getopt(argc, argv, "a:i:")) != -1)
+	/* XXXgpf: [TODO] add argument for user to specify path for .pefs. checksum */
+	while ((i = getopt(argc, argv, "a:i:p:")) != -1)
 		switch(i) {
 		case 'a':
 			for (j=0; j < PEFS_SUPPORTED_DIGESTS; j++)
@@ -1063,6 +1072,23 @@
 				goto out;
 			}
 			break;
+		case 'p':
+			if (stat(optarg, &sb) != 0) {
+				warn("cannot stat file %s", optarg);
+				error = PEFS_ERR_INVALID;
+				goto out;
+			}
+
+			if (S_ISDIR(sb.st_mode) == 0) {
+				pefs_warn("filename: %s is not a directory", optarg);
+				error = PEFS_ERR_INVALID;
+				goto out;
+			}
+
+			snprintf(csm_path, sizeof(csm_path), "%s/%s", optarg,
+					PEFS_FILE_CHECKSUM);
+
+			break;
 		default:
 			if (fpin != NULL)
 				fclose(fpin);
@@ -1079,7 +1105,7 @@
 
 	initfsroot(argc, argv, 0, fsroot, sizeof(fsroot));
 
-	error = pefs_create_checksum_file(fpin, fsroot, algo);
+	error = pefs_create_checksum_file(fpin, fsroot, csm_path, algo);
 
 out:
 	if (fpin != NULL)
@@ -1209,8 +1235,8 @@
 "	pefs randomchain [-fv] [-n min] [-N max] filesystem\n"
 "	pefs showchains [-fp] [-i iterations] [-k keyfile] filesystem\n"
 "	pefs showalgs\n"
-"	pefs addchecksum [-a algo] [-i inputfile] filesystem\n"
-"	pefs addchecklist [-i inputfile] [-o outputfile[ filesystem\n"
+"	pefs addchecksum [-a algo] [-i inputfile] [-p checksumpath] filesystem\n"
+"	pefs addchecklist [-i inputfile] [-o outputfile] filesystem\n"
 );
 	exit(PEFS_ERR_USAGE);
 }

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Fri May 25 16:26:06 2012	(r236400)
@@ -94,7 +94,7 @@
 int	pefs_key_decrypt(struct pefs_xkeyenc *xe,
 	    const struct pefs_xkey *xk_parent);
 uintmax_t	pefs_keyid_as_int(char *keyid);
-int pefs_create_checksum_file(FILE *fpin, char *fsroot, const char *algo);
+int pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo);
 int pefs_create_checklist(FILE *fpin, int fdout, char *fsroot, char *fromfsroot);
 
 const char *	pefs_alg_name(struct pefs_xkey *xk);

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h	Fri May 25 16:26:06 2012	(r236400)
@@ -48,9 +48,16 @@
 	char			pxk_key[PEFS_KEY_SIZE];
 };
 
+/*
+ * XXXgpf: [TODO] gleb says:
+ Adding 'x' to mark
+ it as exported to userspace will also be wise. So it's better be
+ pefs_xnamecsum or pefs_xname_csum.
+ */
 struct pefs_namemac {
-	uint32_t		pnm_namelen;
 	uint64_t		pnm_csum;
+	uint32_t		pnm_namelen;
+	/* XXXgpf: should probably be MAXNAMLEN */
 	char			pnm_filename[MAXPATHLEN];
 };
 

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Fri May 25 16:26:06 2012	(r236400)
@@ -2471,15 +2471,25 @@
 			pefs_flushkey(mp, td, PEFS_FLUSHKEY_ALL, NULL);
 		break;
 	case PEFS_GETNAMEMAC:
-		if (vp->v_type != VDIR)
-			panic("pefs_ioctl: PEFS_GETNAMEMAC vp is not a directory\n");
+		/* XXXgpf: should I change printf to PEFSDEBUG or something else? */
+		if (vp->v_type != VDIR) {
+			printf("pefs_ioctl: PEFS_GETNAMEMAC vp is not a directory\n");
+			error = EINVAL;
+			break;
+		}
 
 		if (strnlen(namemac->pnm_filename, sizeof(namemac->pnm_filename)) !=
-			namemac->pnm_namelen)
-			panic("pefs_ioctl: PEFS_GETNAMEMAC incorrect pnm_namelen\n");
+			namemac->pnm_namelen) {
+			printf("pefs_ioctl: PEFS_GETNAMEMAC incorrect pnm_namelen %d\n", namemac->pnm_namelen);
+			error = EINVAL;
+			break;
+		}
 
-		if (strchr(namemac->pnm_filename, '/') != NULL)
-			panic("pefs_ioctl: PEFS_GETNAMEMAC pnm_filename contains '/'\n");
+		if (strchr(namemac->pnm_filename, '/') != NULL) {
+			printf("pefs_ioctl: PEFS_GETNAMEMAC pnm_filename contains '/'\n");
+			error = EINVAL;
+			break;
+		}
 
 		vn_lock(vp, LK_EXCLUSIVE);
 		pefs_enccn_init(&enccn);
@@ -2500,6 +2510,7 @@
 			enc_len = enccn.pec_cn.cn_namelen;
 
 			if (enc[0] != '.' || enc_len <= 1) {
+				pefs_enccn_free(&enccn);
 				error = EINVAL;
 				break;
 			}

Modified: soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile	Fri May 25 15:16:40 2012	(r236399)
+++ soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile	Fri May 25 16:26:06 2012	(r236400)
@@ -23,4 +23,3 @@
 SRCS+=	hmac_sha512.c
 
 .include <bsd.kmod.mk>
-



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