Date: Thu, 07 Jun 2012 12:46:34 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r237260 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs Message-ID: <20120607124634.566D2106564A@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120607124634.566D2106564A>