socsvn commit: r237260 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs

gpf at FreeBSD.org gpf at FreeBSD.org
Thu Jun 7 12:46:36 UTC 2012


Author: gpf
Date: Thu Jun  7 12:46:33 2012
New Revision: 237260
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237260

Log:
  few minor changes:
  - read input from stdin by default if inputfile [-f] is not supplied
  
  - remove read_counts() and place counter in next_file(). With cuckoo hash,
  we populate/allocate hash tables after all entries are read/parsed.
  
  - make use of cuckoo_lookup() in cuckoo_insert for collision checks instead
  of doing them by hand.
  
  - properly return according to what cuckoo_insert() returns
  
  - clearer errors in some cases
  
  - update some comments
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
  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	Thu Jun  7 11:32:09 2012	(r237259)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Thu Jun  7 12:46:33 2012	(r237260)
@@ -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
@@ -261,7 +261,7 @@
 	}
 
 	if (S_ISLNK(sb.st_mode) != 0)
-		return(pefs_compute_symlink_checksum(fhp, md, hash_len));
+		return (pefs_compute_symlink_checksum(fhp, md, hash_len));
 
 	resid = sb.st_size;
 	if (resid == 0) {
@@ -298,9 +298,9 @@
 		EVP_DigestUpdate(&mdctx, xsct.pxsct_ctext, xsct.pxsct_ctext_len);
 
 		dprintf(("read %d bytes from kernel\n\n", bytes_to_read));
-		//dprintf(("printing contents of buffer:"));
-		//for (i=0; i < (int)bytes_to_read; i++) dprintf(("%c", xsct.pxsct_ctext[i]));
-		//dprintf(("!\n"));
+		dprintf(("printing contents of buffer:"));
+		for (i=0; i < (int)bytes_to_read; i++) dprintf(("%c", xsct.pxsct_ctext[i]));
+		dprintf(("!\n"));
 
 		csp = malloc(sizeof(struct checksum));
 		if (csp == NULL) {
@@ -332,38 +332,6 @@
 	return (0);
 }
 
-static int
-pefs_count_file_entries(FILE *fpin, uint32_t *nelementsp)
-{
-	char buf[MAXPATHLEN + 1];
-	uint32_t nfiles;
-
-	nfiles = 0;
-
-	while (fgets(buf, sizeof(buf), fpin) != NULL) {
-		if (nfiles + 1 < nfiles) {
-			pefs_warn("numeric overflow while counting file entries");
-			return (PEFS_ERR_GENERIC);
-		}
-		nfiles++;
-	}
-
-	if (feof(fpin) == 0) {
-		warn("error reading input");
-		return (PEFS_ERR_IO);
-	}
-
-	if (nfiles == 0) {
-		pefs_warn("input file has no entries");
-		return (PEFS_ERR_INVALID);
-	}
-
-	fseek(fpin, 0, SEEK_SET);
-	*nelementsp = nfiles;
-
-	return (0);
-}
-
 static void
 pefs_init_hash_table(struct cuckoo_hash_table *chtp)
 {
@@ -521,31 +489,18 @@
 pefs_cuckoo_insert(struct cuckoo_hash_table *chtp,
 	struct file_header *fhp)
 {
-	struct file_header *elem, *elem1, *elem2;
+	struct file_header *elem, *elem1, *elem2, *res;
 	uint32_t i, max_tries, pos1, pos2;
 
 	max_tries = chtp->size;
 	elem = fhp;
 
 	/* file_id collision check */
-	pos1 = pefs_hash1(chtp, elem);
-	elem1 = chtp->buckets1[pos1].fhp;
-	pos2 = pefs_hash2(chtp, elem);
-	elem2 = chtp->buckets2[pos2].fhp;
-	if (elem1 != NULL) {
-		if (elem1->file_id == fhp->file_id) {
-			pefs_warn("file identifier collision detected between files: %s & %s",
-					fhp->path, elem1->path);
-			return (PEFS_ERR_EXIST);
-		}
-	}
-
-	if (elem2 != NULL) {
-		if (elem2->file_id == fhp->file_id) {
-			pefs_warn("file identifier collision detected between files: %s & %s",
-					fhp->path, elem2->path);
-			return (PEFS_ERR_EXIST);
-		}
+	res = pefs_cuckoo_lookup(chtp, elem);
+	if (res != NULL) {
+		pefs_warn("file identifier collision detected between files: %s & %s",
+				res->path, elem->path);
+		return (PEFS_ERR_EXIST);
 	}
 
 	for (i = 0; i < max_tries; i++) {
@@ -671,12 +626,9 @@
 	return (error);
 }
 
-// XXXgpf: void?
 static void
-pefs_symlink_warn(struct cuckoo_hash_table *chtp, struct file_header_head *fhhp,
-			struct statfs *fsp)
+pefs_symlink_warn(struct cuckoo_hash_table *chtp, struct file_header_head *fhhp)
 {
-	struct statfs this_fs;
 	struct stat sb;
 	struct file_header targetfh;
 	struct file_header *fhp, *res;
@@ -684,20 +636,17 @@
 
 	TAILQ_FOREACH(fhp, fhhp, file_header_entries) {
 		/*
-		 * If fhp == symlink and target file resides in pefs filesystem and
-		 * target file == regular file || symlink, then grab target's filename MAC and
-		 * look it up in our hash table. Print a warning message if it is not found.
+		 * If fhp == symlink and target file == regular file || symlink,
+		 * then grab target's filename MAC and look it up in our hash table.
+		 * Print a warning message if it is not found.
+		 * symlink target referes to the file that is immediately pointed to by
+		 * our symlink. therefore in a syml1->syml2->file example, we only check
+		 * syml2 if we are supplied syml1. This is by choise so that user will
+		 * receive warning for intermediate parts of a symlink chain.
+		 *
+		 * XXXgpf: perhaps relax restrictions on warning messages
 		 */
 		if (fhp->target_path != NULL) {
-			if (statfs(fhp->target_path, &this_fs) == -1) {
-				pefs_warn("statfs failed: %s: %s", fhp->target_path, strerror(errno));
-				continue;
-			}
-
-			if ((fsp->f_fsid.val[0] != this_fs.f_fsid.val[0]) ||
-				(fsp->f_fsid.val[1] != this_fs.f_fsid.val[1]))
-				continue;
-
 			if (lstat(fhp->target_path, &sb) != 0) {
 				warn("cannot stat file %s", fhp->target_path);
 				continue;
@@ -826,8 +775,10 @@
 		 * in input file-list, since symlinks are not traversed. User will have to
 		 * provide fullpaths for both symlink & target file if he wants integrity
 		 * checking for both. However, we will print warning messages in case
-		 * target file does reside in pefs filesystem but is not provided in
-		 * user supplied input list.
+		 * target file is not provided in user supplied input list.
+		 *
+		 * Target referes to the file immediately pointed to by our symlink, not
+		 * the final target of a possible symlink chain.
 		 */
 		target_path_size = MAXPATHLEN;
 		fhp->target_path = malloc(target_path_size);
@@ -853,7 +804,7 @@
 
 		/*
 		 * The only semantic check that is performed on target file is an attempt
-		 * to stat() the file, in order to make sure the file exists. This is
+		 * to lstat() the file, in order to make sure the file exists. This is
 		 * intentional since target file is allowed to reside on a different
 		 * filesystem or in the same filesystem, but not be a regular file or a
 		 * symlink.
@@ -902,7 +853,7 @@
 }
 
 static struct file_header *
-pefs_next_file(FILE *fpin, int *error)
+pefs_next_file(FILE *fpin, int *error, int *nfiles)
 {
 	char buf[MAXPATHLEN + 1];
 	struct file_header *fhp;
@@ -929,6 +880,7 @@
 	}
 
 	strlcpy(fhp->path, buf, sizeof(fhp->path));
+	(*nfiles)++;
 
 	return (fhp);
 }
@@ -968,22 +920,15 @@
 	int error;
 	uint32_t nfiles;
 
+	nfiles = 0;
 	if (statfs(fsroot, &fs) == -1) {
 		pefs_warn("statfs failed: %s: %s", fsroot, strerror(errno));
 		return (PEFS_ERR_SYS);
 	}
 
-	error = pefs_count_file_entries(fpin, &nfiles);
-	if (error != 0)
-		return (error);
-
-	error = pefs_allocate_hash_table(chtp, nfiles, 0);
-	if (error != 0)
-		return (error);
-
 	TAILQ_INIT(&fh_head);
 	RB_INIT(&hlc_head);
-	while((fhp = pefs_next_file(fpin, &error)) != NULL) {
+	while((fhp = pefs_next_file(fpin, &error, &nfiles)) != NULL) {
 		error = pefs_file_semantic_checks(fhp, &fs, &hlc_head);
 		if (error != 0)
 			return (error);
@@ -1006,15 +951,22 @@
 	pefs_rb_print(&hlc_head);
 	pefs_rb_warn(&hlc_head);
 
+	error = pefs_allocate_hash_table(chtp, nfiles, 0);
+	if (error != 0)
+		return (error);
+
 cuckoo_insert:
 	TAILQ_FOREACH(fhp, &fh_head, file_header_entries) {
 		error = pefs_add_to_hash_table(chtp, fhp);
+		/* collision error */
+		if (error == PEFS_ERR_EXIST)
+			return (error);
 		/*
 		 * cuckoo insertion algorithm fell into an infinite loop!
 		 * Create new, larger hash tables where size = next_prime(old_size)
 		 * and try again.
 		 */
-		if (error != 0) {
+		else if (error != 0) {
 			dprintf(("fell into an infinite loop!\n"));
 			error = pefs_allocate_hash_table(chtp, nfiles, 1);
 			if (error != 0)
@@ -1023,7 +975,7 @@
 		}
 	}
 	pefs_print_hash_table(chtp, hash_len);
-	pefs_symlink_warn(chtp, &fh_head, &fs);
+	pefs_symlink_warn(chtp, &fh_head);
 
 	return (error);
 }

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Thu Jun  7 11:32:09 2012	(r237259)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Thu Jun  7 12:46:33 2012	(r237260)
@@ -1011,8 +1011,8 @@
  * hash function; supported algorithms: sha256, sha512. sha256 is
  * used by default.
  *
- * inputfile contains list of files that need integrity checking. An
- * inputfile must be supplied.
+ * inputfile contains list of files that need integrity checking. If
+ * the argument is not supplied, input is read from stdin by default.
  *
  * path defines where .pefs.checksum should be created. By default,
  * .pefs.checksum is created under $PWD. path should be a directory,
@@ -1032,13 +1032,7 @@
 	int error, i, j;
 	const char *algo;
 
-	/*
-	 * XXXgpf: [TODO] Now, all input file entries are kept in a 'global' tail structure
-	 * and insertion into hash table occurs after all of them are read/parsed. Therefore,
-	 * it is possible to have fpin = stdin by default and not require an input file, since
-	 * we will not have to go through the input list twice, thus requiring a rewind().
-	 */
-	fpin = NULL;
+	fpin = stdin;
 	/* by default use sha256 */
 	algo = supported_digests[0];
 	/* by default create checksum file under $PWD */
@@ -1093,11 +1087,6 @@
 	argc -= optind;
 	argv += optind;
 
-	if (fpin == NULL) {
-		pefs_warn("please supply an input file [-i]");
-		return (PEFS_ERR_USAGE);
-	}
-
 	initfsroot(argc, argv, 0, fsroot, sizeof(fsroot));
 
 	error = pefs_create_checksum_file(fpin, fsroot, csm_path, algo);

Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Thu Jun  7 11:32:09 2012	(r237259)
+++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c	Thu Jun  7 12:46:33 2012	(r237260)
@@ -2512,7 +2512,6 @@
 		pefs_chunk_create(&pc, pn, xsct->pxsct_ctext_len);
 		puio = pefs_chunk_uio(&pc, xsct->pxsct_offset, UIO_READ);
 
-
 		error = VOP_READ(lvp, puio, IO_UNIT | IO_NODELOCKED, cred);
 
 		if (error == 0)
@@ -2527,7 +2526,7 @@
 		if (vp->v_type != VDIR) {
 			printf("pefs_ioctl: PEFS_GETNAMEMAC vp is not a directory\n");
 			VOP_UNLOCK(vp, 0);
-			return (EINVAL);
+			return (ENOTDIR);
 		}
 
 		if (strnlen(xncs->pxnc_filename, sizeof(xncs->pxnc_filename)) !=
@@ -2587,7 +2586,7 @@
 		if (vp->v_type != VDIR) {
 			printf("pefs_ioctl: PEFS_GETSLINKCTEXT vp is not a directory\n");
 			VOP_UNLOCK(vp, 0);
-			return (EINVAL);
+			return (ENOTDIR);
 		}
 
 		if (strnlen(xsl->pxsl_filename, sizeof(xsl->pxsl_filename)) !=
@@ -2618,21 +2617,22 @@
 		cn.cn_pnbuf = NULL;
 		cn.cn_consume = 0;
 
+		/* XXXgpf: gleb says that maybe using namei() would be better */
 		error = pefs_lookup(&la);
 		if (error != 0) {
 			printf("pefs_ioctl: PEFS_GETSLINKCTEXT lookup error %d", error);
 			VOP_UNLOCK(vp, 0);
-			return (EINVAL);
+			return (error);
 		}
 
 		if (svp->v_type != VLNK) {
 			printf("pefs_ioctl: PEFS_GETSLINKCTEXT svp is not a symlink '/'\n");
 			vput(svp);
 			VOP_UNLOCK(vp, 0);
-			return (EINVAL);
+			return (EFTYPE);
 		}
 
-		/* VOP_READLINK our lvp */
+		/* VOP_READLINK our slvp */
 		slvp = PEFS_LOWERVP(svp);
 		pn = VP_TO_PN(svp);
 		pefs_chunk_create(&pc, pn, MAXPATHLEN);


More information about the svn-soc-all mailing list