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

gpf at FreeBSD.org gpf at FreeBSD.org
Tue Jun 5 13:46:21 UTC 2012


Author: gpf
Date: Tue Jun  5 13:46:19 2012
New Revision: 237137
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237137

Log:
  - check if our input file list is empty
  - check if some file entry corresponds to an empty file
  - check if pefs_next_file_entry encounters an error
  - handle symlinks:
  If file in input list is symlink, get the absolute path of the file that it's
  pointing to. Perform sanity checks on target file. If everything's ok, target
  file is used throughout the codebase. Which means that .pefs.checksum will
  have an entry for that target file, not for the symlink.
  - check for numeric overflows in a few parts
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Tue Jun  5 12:34:08 2012	(r237136)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Tue Jun  5 13:46:19 2012	(r237137)
@@ -54,7 +54,7 @@
 
 #include "pefs_ctl.h"
 
-#define PEFS_INTEGRITY_DEBUG
+//#define PEFS_INTEGRITY_DEBUG
 #if defined (PEFS_INTEGRITY_DEBUG)
 #define dprintf(a)		printf a
 #else
@@ -71,6 +71,8 @@
 #define PEFS_CFH_SIZE 16
 #define PEFS_FH_SIZE 16
 
+/* XXXgpf: [TODO] check pathname string lengths. Some are MAXPATHLEN + 1, some MAXPATHLEN */
+
 /* XXXgpf: unions for on disk structs and move to a different header? */
 struct checksum_file_header {
         uint8_t version;
@@ -169,8 +171,11 @@
 		return (PEFS_ERR_SYS);
 	}
 
-	/* XXXgpf: shouldn't we also check for empty files? */
 	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);
 	if (fd < 0) {
@@ -244,7 +249,10 @@
 	nfiles = 0;
 
 	while (fgets(buf, sizeof(buf), fpin) != NULL) {
-		/* XXXgpf: [TODO] check for numeric overflow */
+		if (nfiles + 1 < nfiles) {
+			pefs_warn("numeric overflow while counting file entries");
+			return (PEFS_ERR_GENERIC);
+		}
 		nfiles++;
 	}
 
@@ -253,6 +261,11 @@
 		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;
 
@@ -287,6 +300,10 @@
 	}
 	else {
 		chtp->size = pefs_next_prime(chtp->size + 1);
+			if (chtp->size < chtp->nelements) {
+			pefs_warn("numeric overflow while computing new hash table size");
+			return (PEFS_ERR_GENERIC);
+		}
 		free(chtp->buckets1);
 		free(chtp->buckets2);
 	}
@@ -533,10 +550,14 @@
 static int
 pefs_file_semantic_checks(struct file_header *fhp, struct statfs *fsp)
 {
+	char parent_dir[MAXPATHLEN];
+	char sbuf[MAXPATHLEN];
 	struct stat sb;
 	struct statfs this_fs;
+	char *pch;
+	int nchars;
 
-	if (stat(fhp->path, &sb) != 0) {
+	if (lstat(fhp->path, &sb) != 0) {
 		warn("cannot stat file %s", fhp->path);
 		return (PEFS_ERR_SYS);
 	}
@@ -549,6 +570,35 @@
 	/*
 	 * XXXgpf: [TODO] deal with other types of files
 	 */
+	if (S_ISLNK(sb.st_mode) != 0) {
+		nchars = readlink(fhp->path, sbuf, sizeof(sbuf));
+		if (nchars == -1) {
+			warn("readlink failed: %s", fhp->path);
+			return (PEFS_ERR_SYS);
+		}
+
+		if (nchars > sizeof(sbuf) - 1)
+			nchars = sizeof(sbuf) - 1;
+		sbuf[nchars] = '\0';
+		/* turn relative paths to absolute paths which are needed for pefs_get_file_id() */
+		if (sbuf[0] != '/') {
+			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';
+			snprintf(fhp->path, sizeof(fhp->path), "%s/%s", parent_dir, sbuf);
+		}
+		else
+			strlcpy(fhp->path, sbuf, sizeof(fhp->path));
+
+		if (lstat(fhp->path, &sb) != 0) {
+			warn("cannot stat file %s", fhp->path);
+			return (PEFS_ERR_SYS);
+		}
+	}
 
 	if (S_ISREG(sb.st_mode) == 0) {
 		pefs_warn("filename: %s is not a regular file", fhp->path);
@@ -652,6 +702,10 @@
 		TAILQ_INSERT_TAIL(&fh_head, fhp, file_header_entries);
 	}
 
+	/* checking I/O error with pefs_next_file()*/
+	if (error != 0)
+		return (error);
+
 cuckoo_insert:
 	TAILQ_FOREACH(fhp, &fh_head, file_header_entries) {
 		error = pefs_add_to_hash_table(chtp, fhp);
@@ -667,7 +721,7 @@
 				return (error);
 			goto cuckoo_insert;
 		}
-	 }
+	}
 	pefs_print_hash_table(chtp, hash_len);
 
 	return (error);


More information about the svn-soc-all mailing list