Date: Tue, 03 Jul 2012 13:09:04 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r238911 - soc2012/gpf/pefs_kmod/sbin/pefs Message-ID: <20120703130904.DD9D9106564A@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120703130904.DD9D9106564A>