socsvn commit: r237260 - in soc2012/gpf/pefs_kmod: sbin/pefs
sys/fs/pefs
gpf at FreeBSD.org
gpf at FreeBSD.org
Thu Jun 7 12:46:36 UTC 2012
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);
More information about the svn-soc-all
mailing list