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