socsvn commit: r238911 - soc2012/gpf/pefs_kmod/sbin/pefs

gpf at FreeBSD.org gpf at FreeBSD.org
Tue Jul 3 13:09:07 UTC 2012


Author: gpf
Date: Tue Jul  3 13:09:04 2012
New Revision: 238911
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=238911

Log:
  - properly handle checksum integrity errors
  - a lot of testing was done and a few minor bugs were fixed
  
  sbin/pefs verify will try to print as many error messages as possible
  and will only exit prematurely if a system error occurs. e.g. could
  not allocate memory in heap or could not open a directory, etc.
  

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

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Tue Jul  3 13:03:36 2012	(r238910)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Tue Jul  3 13:09:04 2012	(r238911)
@@ -57,7 +57,7 @@
 
 #include "pefs_ctl.h"
 
-#define PEFS_INTEGRITY_DEBUG
+//#define PEFS_INTEGRITY_DEBUG
 #if defined (PEFS_INTEGRITY_DEBUG)
 #define dprintf(a)		printf a
 #else
@@ -207,13 +207,13 @@
 		/* feed parent directory to ioctl() */
 		strlcpy(xsl.pxsl_filename, fhp->filename, sizeof(xsl.pxsl_filename));
 		xsl.pxsl_namelen = strnlen(xsl.pxsl_filename, sizeof(xsl.pxsl_filename));
-	
+
 		error = ioctl(fhp->pfd, PEFS_GETSLINKCTEXT, &xsl);
 		if (error != 0) {
 			pefs_warn("error retrieving symlink's ciphertext of %s", fhp->path);
 			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]));
@@ -300,7 +300,7 @@
 			bytes_to_read = PEFS_SECTOR_SIZE;
 		else
 			bytes_to_read = resid;
-		
+
 		if ((flags & PEFS_UNMOUNTED) != 0 || (flags & PEFS_NOKEY) != 0) {
 			fread(sector_buf, bytes_to_read, sizeof(char), fp);
 			if (ferror(fp)) {
@@ -358,14 +358,14 @@
 	}
 
 	/*
-	 * XXXgpf: [TODO] better move the fp into file_header struct and deal with 
+	 * XXXgpf: [TODO] better move the fp into file_header struct and deal with
 	 * closing it during pefs_file_close.
 	 */
 	if (fp != NULL) {
 		fclose(fp);
 		fhp->fd = -1;
 	}
-	
+
 	return (0);
 }
 
@@ -562,7 +562,7 @@
 			elem = elem2;
 	}
 
-	/* XXXgpf: should be left as a warning at least during development phase */
+	/* XXXgpf: should be left as a warning during development phase */
 	pefs_warn("cuckoo_insert resulted in infinite loop!");
 	return (PEFS_ERR_GENERIC);
 }
@@ -574,7 +574,7 @@
 	return (pefs_cuckoo_insert(chtp, fhp));
 }
 
-/* for debugging purposes */
+/* XXXgpf: for debugging purposes */
 static void
 pefs_print_hash_tables(struct cuckoo_hash_table *chtp, uint8_t hash_len)
 {
@@ -670,7 +670,6 @@
 	error = ioctl(fhp->pfd, PEFS_GETNAMECSUM, &xncs);
 
 	if (error == 0) {
-		/* XXXgpf: Is this correct? */
 		memcpy(&temp, xncs.pxnc_csum, sizeof(xncs.pxnc_csum));
 		fhp->file_id = be64toh(temp);
 	}
@@ -775,7 +774,7 @@
 
 	RB_FOREACH(hlcp, hardlink_head, hlc_headp) {
 		if (hlcp->total_links > hlcp->links_found) {
-			pefs_warn("%d hard links of total %d were found in input list for file with inode: %d",
+			pefs_warn("%d hard link(s) of total %d were found in input list for file with inode: %d",
 				hlcp->links_found, hlcp->total_links, hlcp->inode);
 			i = 1;
 			TAILQ_FOREACH(fhp, &(hlcp->file_headers), fh_hardlink_entries) {
@@ -902,7 +901,7 @@
 		sbuf[nchars] = '\0';
 
 		/* turn relative paths to absolute paths */
-		if (sbuf[0] != '/')
+		if (sbuf[0] != '/' && (flags & PEFS_UNMOUNTED) == 0 && (flags & PEFS_NOKEY) == 0)
 			snprintf(fhp->target_path, target_path_size, "%s/%s", fhp->dirpath, sbuf);
 		else
 			strlcpy(fhp->target_path, sbuf, target_path_size);
@@ -925,15 +924,6 @@
 				return (PEFS_ERR_SYS);
 			}
 		}
-
-		/*
-		 * XXXgpf:
-		 * Is there a way to check that symlink file itself exists in pefs filesystem?
-		 * fstatfs() for example requires a fd and we can't open() the symlink without
-		 * either failing, or having to traverse it.
-		 * On the other hand, if the symlink does not reside in pefs fs, then the calls to
-		 * ioctl() later on will fail.
-		 */
 		return (0);
 	}
 	else
@@ -1088,6 +1078,7 @@
 
 	pefs_rb_print(&hlc_head);
 	pefs_rb_warn(&hlc_head);
+	/* XXXgpf: [TODO] rb_free */
 
 	error = pefs_allocate_hash_table(chtp, nfiles, PEFS_EXTEND);
 	if (error != 0)
@@ -1166,9 +1157,6 @@
 	return (0);
 }
 
-/*
- * XXXgpf: [TODO] take a look at chained offsets
- */
 static int
 pefs_write_file_header(int fdout, struct file_header *fhp, uint32_t *buckets_offset)
 {
@@ -1589,6 +1577,7 @@
 			TAILQ_INIT(&(fhp->checksums));
 			hashes_offset = fhp->offset_to_checksums;
 			fhp->found = 0;
+			fhp->target_path = NULL;
 
 			for (k = 0; k < fhp->nhashes; k++) {
 				csp = malloc(sizeof(struct checksum));
@@ -1622,6 +1611,7 @@
 			TAILQ_INIT(&(fhp->checksums));
 			hashes_offset = fhp->offset_to_checksums;
 			fhp->found = 0;
+			fhp->target_path = NULL;
 
 			for (k = 0; k < fhp->nhashes; k++) {
 				csp = malloc(sizeof(struct checksum));
@@ -1652,32 +1642,33 @@
 {
 	struct checksum *csp1, *csp2;
 	uint32_t i;
-	int error;
+	int error, cmp;
 
 	dprintf(("comparing hashes for file with fid: %llu\t%llu\n", fhp->file_id, indexfhp->file_id));
 
+	error = 0;
 	if (fhp->nhashes != indexfhp->nhashes) {
 		pefs_warn("number of hashes differ between on disk file and stored values for file %s: %u vs %u",
 			fhp->path, fhp->nhashes, indexfhp->nhashes);
-		return (1);
+		error = PEFS_ERR_CHECKSUM;
 	}
 
 	csp1 = TAILQ_FIRST(&fhp->checksums);
 	csp2 = TAILQ_FIRST(&indexfhp->checksums);
 	i = 1;
 	while (csp1 != NULL && csp2 != NULL) {
-		error = memcmp(csp1->hash, csp2->hash, hash_len);
-		if (error != 0) {
+		cmp = memcmp(csp1->hash, csp2->hash, hash_len);
+		if (cmp != 0) {
 			pefs_warn("checksum no: %u differs between on disk file and stored values for file %s",
 				i, fhp->path);
-			return (1);
+			error = PEFS_ERR_CHECKSUM;
 		}
 		csp1 = TAILQ_NEXT(csp1, checksum_entries);
 		csp2 = TAILQ_NEXT(csp2, checksum_entries);
 		i++;
 	}
 
-	return (0);
+	return (error);
 }
 
 /*
@@ -1686,7 +1677,7 @@
 static int
 pefs_traverse_fs(struct cuckoo_hash_table *chtp, const EVP_MD *md, uint8_t hash_len, DIR *dirp,
 	char *path, struct statfs *fsp, struct hardlink_head *hlc_headp, struct file_header_head *fh_headp,
-	int flags)
+	int flags, int *checksum_error)
 {
 	char tmpath[MAXPATHLEN];
 	struct stat sb;
@@ -1704,7 +1695,7 @@
 				strcmp(sdp->d_name, ".pefs.checksum") == 0)
 				continue;
 
-			//dprintf(("dirent: %s\n", sdp->d_name));
+			dprintf(("dirent: %s\n", sdp->d_name));
 			snprintf(tmpath, sizeof(tmpath), "%s/%s", path, sdp->d_name);
 			switch (sdp->d_type) {
 			case DT_DIR:
@@ -1714,7 +1705,8 @@
 					closedir(dirp);
 					return (PEFS_ERR_SYS);
 				}
-				error = pefs_traverse_fs(chtp, md, hash_len, dirtmp, tmpath, fsp, hlc_headp, fh_headp, flags);
+				error = pefs_traverse_fs(chtp, md, hash_len, dirtmp, tmpath,
+							fsp, hlc_headp, fh_headp, flags, checksum_error);
 				if (error != 0) {
 					closedir(dirp);
 					return (PEFS_ERR_SYS);
@@ -1747,6 +1739,7 @@
 
 				error = pefs_get_file_id(fhp, flags);
 				if (error != 0) {
+					closedir(dirp);
 					pefs_close_file(fhp);
 					free(fhp);
 					return (error);
@@ -1762,6 +1755,7 @@
 
 				error = pefs_compute_file_checksums(fhp, md, hash_len, flags);
 				if (error != 0) {
+					closedir(dirp);
 					pefs_close_file(fhp);
 					free(fhp);
 					return (error);
@@ -1771,6 +1765,7 @@
 				error = lstat(fhp->path, &sb);
 				if (error != 0) {
 					warn("cannot stat file %s", fhp->path);
+					closedir(dirp);
 					pefs_close_file(fhp);
 					free(fhp);
 					return (PEFS_ERR_SYS);
@@ -1778,23 +1773,19 @@
 
 				error = pefs_rb_insert(hlc_headp, fhp, &sb);
 				if (error != 0) {
+					closedir(dirp);
 					pefs_close_file(fhp);
 					free(fhp);
 					return (error);
 				}
-				
+
 				/*
-				 * XXXgpf: [TODO] if error encountered during 
-				 * pefs_compare_cehcksums, then store this information
-				 * but keep on traversing the fs to find other errors
-				 * as well.
-				 */ 
+				 * if error encountered during pefs_compare_cehcksums,
+				 * keep on traversing the fs to find other errors as well.
+				 */
 				error = pefs_compare_checksums(fhp, indexfhp, hash_len);
-				//if (error != 0) {
-					//pefs_close_file(fhp);
-					//free(fhp);
-					//break;
-				//}
+				if (error != 0)
+					*checksum_error = error;
 
 				TAILQ_INSERT_TAIL(fh_headp, fhp, file_header_entries);
 				pefs_close_file(fhp);
@@ -1809,32 +1800,40 @@
 		}
 	}
 
+	/* unreachable, just to silence compiler */
 	pefs_warn("invalid dirp argument for dir: %s", path);
 	return (PEFS_ERR_SYS);
 }
 
-/* XXXgpf: probably turn this to int */
-static void
+static int
 pefs_found_all_entries(struct cuckoo_hash_table *chtp)
 {
 	struct file_header *fhp;
 	uint32_t i;
+	int error;
 
+	error = 0;
 	for (i = 0; i < chtp->size; i++) {
 		fhp = chtp->buckets1[i].fhp;
 		if (fhp != NULL)
-			if (fhp->found != 1)
+			if (fhp->found != 1) {
 				pefs_warn("file with file id %llu was not found in filesystem but exists in checksum file",
 					fhp->file_id);
+				error = PEFS_ERR_NOENT;
+			}
 	}
 
 	for (i = 0; i < chtp->size; i++) {
 		fhp = chtp->buckets2[i].fhp;
 		if (fhp != NULL)
-			if (fhp->found != 1)
+			if (fhp->found != 1) {
 				pefs_warn("file with file id %llu was not found in filesystem but exists in checksum file",
 					fhp->file_id);
+				error = PEFS_ERR_NOENT;
+			}
 	}
+
+	return (error);
 }
 
 /*
@@ -1850,9 +1849,13 @@
 	struct hardlink_head hlc_head;
 	const EVP_MD *md;
 	DIR *dirp;
-	int error;
+	int error, checksum_error;
 	uint8_t hash_len;
 
+	RB_INIT(&hlc_head);
+	TAILQ_INIT(&fh_head);
+	checksum_error = 0;
+
 	if (statfs(fsroot, &fs) == -1) {
 		pefs_warn("statfs failed: %s: %s", fsroot, strerror(errno));
 		return (PEFS_ERR_SYS);
@@ -1877,32 +1880,35 @@
 
 	error = pefs_read_checksum_file(fdin, &cfh, &cht);
 	if (error != 0)
-		return (error);
+		goto out;
 
-	//pefs_print_hash_tables(&cht, hash_len);
-
-	RB_INIT(&hlc_head);
-	TAILQ_INIT(&fh_head);
+	/* pefs_print_hash_tables(&cht, hash_len); */
 
 	dirp = opendir(fsroot);
 	if (dirp == NULL) {
 		pefs_warn("failed to open dir %s", fsroot);
-		return (PEFS_ERR_SYS);
+		goto out;
 	}
 
-	error = pefs_traverse_fs(&cht, md, hash_len, dirp, fsroot, &fs, &hlc_head, &fh_head, flags);
+	error = pefs_traverse_fs(&cht, md, hash_len, dirp, fsroot, &fs, &hlc_head, &fh_head, flags, &checksum_error);
 	if (error != 0)
-		return (error);
+		goto out;
 
-	//pefs_rb_print(&hlc_head);
-	pefs_rb_warn(&hlc_head);
+	/* pefs_rb_print(&hlc_head); */
+	pefs_rb_warn(&hlc_head);printf("3\n");
 	if ((flags & PEFS_UNMOUNTED) == 0 && (flags & PEFS_NOKEY) == 0)
 		pefs_symlink_warn(&cht, &fh_head);
-	pefs_found_all_entries(&cht);
 
-	/* XXXgpf: [TODO] free mem in the end and when error occurs */
-	/* XXXgpf: [TODO] verify action should also use a signature to verify .pefs.checksum */
-	return (0);
+	error = pefs_found_all_entries(&cht);
+
+	if (error == 0 && checksum_error != 0)
+		error = checksum_error;
+
+out:
+	pefs_free_hash_table(&cht);
+	/* XXXgpf: [TODO] rb_free */
+	/* XXXgpf: [TODO] fh_free */
+	return (error);
 }
 
 RB_GENERATE(hardlink_head, hardlink_counter, hardlink_entries, pefs_rb_cmp);

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Tue Jul  3 13:03:36 2012	(r238910)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Tue Jul  3 13:09:04 2012	(r238911)
@@ -1161,22 +1161,25 @@
 		strlcpy(fsroot, argv[0], sizeof(fsroot));
 		if (stat(fsroot, &sb) != 0) {
 			warn("cannot stat fs root: %s", fsroot);
+			close(fdin);
 			return (PEFS_ERR_NOENT);
 		}
 
 		if (S_ISDIR(sb.st_mode) == 0) {
 			pefs_warn("fs root is not a directory: %s", fsroot);
+			close(fdin);
 			return (PEFS_ERR_SYS);
 		}
 	}
 
 	error = pefs_verify_checksum(fdin, fsroot, flags);
 	if (error == 0)
-		printf("everything's ok!\n");
+		printf("integrity verification ok!\n");
+	else
+		pefs_warn("integrity verification encountered error(s)");
 
 	close(fdin);
 	return (error);
-
 }
 
 static void

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Tue Jul  3 13:03:36 2012	(r238910)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Tue Jul  3 13:09:04 2012	(r238911)
@@ -64,6 +64,7 @@
 #define	PEFS_ERR_NOENT			5
 #define	PEFS_ERR_EXIST			6
 #define	PEFS_ERR_INVALID		7
+#define PEFS_ERR_CHECKSUM		8
 
 #define	PEFS_FS_IGNORE_TYPE		0x0001
 


More information about the svn-soc-all mailing list