Date: Fri, 25 May 2012 16:26:07 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r236400 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs sys/modules/pefs Message-ID: <20120525162607.7AB13106566C@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gpf Date: Fri May 25 16:26:06 2012 New Revision: 236400 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=236400 Log: Require that .pefs.checksum is created outside of target pefs filesystem. Change pefs_ioctl() kernel panics into printfs() and error returns. 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 soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Fri May 25 16:26:06 2012 (r236400) @@ -227,7 +227,7 @@ if (checksum_hash_tablep->buckets != NULL) { for (i = 0; i < checksum_hash_tablep->size; i++) { bp = &checksum_hash_tablep->buckets[i]; - LIST_FOREACH_SAFE(fhp, &(bp->file_headers), bucket_entries, tfhp) { + LIST_FOREACH_SAFE(fhp, &(bp->file_headers), bucket_entries, tfhp) { TAILQ_FOREACH_SAFE(csp, &(fhp->checksums), checksum_entries, tcsp) { TAILQ_REMOVE(&(fhp->checksums), csp, checksum_entries); if (csp->hash != NULL) @@ -355,6 +355,8 @@ if (error == 0) fhp->file_id = namemac.pnm_csum; + else + pefs_warn("failed to fetch file id from kernel"); close(fd); return (error); @@ -674,12 +676,52 @@ } /* + * If .pefs.checksum is created inside pefs mounted fs, then it will obtain an + * encrypted filename & encrypted data, which is unacceptable. User should create + * checksum file outside of filesystem and then copy it by hand. + */ +static int +pefs_open_checksum_file(int *fdp, char *fsroot, char *csm_path) +{ + struct statfs pefs_fs, checksum_fs; + int fd; + + *fdp = -1; + + fd = open(csm_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + if (fd == -1) { + warn("cannot open %s", csm_path); + return (PEFS_ERR_IO); + } + + *fdp = fd; + + if (statfs(fsroot, &pefs_fs) == -1) { + pefs_warn("statfs failed: %s: %s", fsroot, strerror(errno)); + return (PEFS_ERR_SYS); + } + + if (statfs(csm_path, &checksum_fs) == -1) { + pefs_warn("statfs failed: %s: %s", csm_path, strerror(errno)); + return (PEFS_ERR_SYS); + } + + if ((pefs_fs.f_fsid.val[0] == checksum_fs.f_fsid.val[0]) && + (pefs_fs.f_fsid.val[1] == checksum_fs.f_fsid.val[1])) { + pefs_warn("%s must be created outside of pefs mounted filesystem %s", + csm_path, pefs_fs.f_mntonname); + return (PEFS_ERR_INVALID); + } + + return (0); +} + +/* * XXXgpf: [TODO] proper comment header, I am sleepy Z_Z */ int -pefs_create_checksum_file(FILE *fpin, char *fsroot, const char *algo) +pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo) { - char checksum_path[MAXPATHLEN]; struct hash_table checksum_hash_table; struct checksum_file_header cfh; const EVP_MD *md; @@ -695,21 +737,12 @@ } hash_len = EVP_MD_size(md); - snprintf(checksum_path, sizeof(checksum_path), "%s/%s", fsroot, PEFS_FILE_CHECKSUM); - /* - * XXXgpf: [TODO] If pefs fs is mounted when .pefs.checksum is created, then it will obtain an - * encrypted filename & encrypted data. I should make sure that checksum file is not being - * opened inside a mounted pefs filesystem. - * pefs_open_checksum_file() - */ - fdout = open(checksum_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - if (fdout == -1) { - warn("cannot open %s", checksum_path); - return (PEFS_ERR_IO); - } - pefs_init_hash_table(&checksum_hash_table); + error = pefs_open_checksum_file(&fdout, fsroot, csm_path); + if (error != 0) + goto out; + error = pefs_create_in_memory_db(fpin, md, hash_len, &checksum_hash_table, fsroot); if (error != 0) @@ -720,10 +753,11 @@ error = pefs_write_checksum_file(fdout, &cfh, &checksum_hash_table); out: - if (fdout >= 0) + if (fdout >= 0) { close(fdout); - if (error != 0) - unlink(checksum_path); + if (error != 0) + unlink(csm_path); + } pefs_free_hash_table(&checksum_hash_table); return (error); Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c Fri May 25 16:26:06 2012 (r236400) @@ -1011,27 +1011,33 @@ /* * XXXgpf: Instead of a man page entry: * - * pefs addchecksum [-a algo] [-i inputfile] filesystem + * pefs addchecksum [-a algo] [-i inputfile] [-p path] filesystem * * $command creates .pefs.checksum db file for filesystem. * This file will contain all checksums necessary to check integrity * of files upon access. * * algo is the name of the algorithm to be used as a cryptographic - * hash function; supported algorithms: sha256, sha512. + * hash function; supported algorithms: sha256, sha512. sha256 is + * used by default. * - * inputfile contains list of files that need integrity checking. + * inputfile contains list of files that need integrity checking. An + * inputfile must be supplied. + * + * path defines where .pefs.checksum should be created. By default, + * .pefs.checksum is created under $PWD. path should be a directory, + * outside of target pefs filesystem. * - * When $command is run, filesystem should be already mounted with + * When $command is run, filesystem should be already mounted with * pefs. - * - * [TODO] reference for where .pefs.checksum file should be created. * */ static int pefs_addchecksum(int argc, char *argv[]) { char fsroot[MAXPATHLEN]; + char csm_path[MAXPATHLEN]; + struct stat sb; FILE *fpin; int error, i, j; const char *algo; @@ -1039,8 +1045,11 @@ fpin = NULL; /* by default use sha256 */ algo = supported_digests[0]; + /* by default create checksum file under $PWD */ + snprintf(csm_path, sizeof(csm_path), "./%s", PEFS_FILE_CHECKSUM); - while ((i = getopt(argc, argv, "a:i:")) != -1) + /* XXXgpf: [TODO] add argument for user to specify path for .pefs. checksum */ + while ((i = getopt(argc, argv, "a:i:p:")) != -1) switch(i) { case 'a': for (j=0; j < PEFS_SUPPORTED_DIGESTS; j++) @@ -1063,6 +1072,23 @@ goto out; } break; + case 'p': + if (stat(optarg, &sb) != 0) { + warn("cannot stat file %s", optarg); + error = PEFS_ERR_INVALID; + goto out; + } + + if (S_ISDIR(sb.st_mode) == 0) { + pefs_warn("filename: %s is not a directory", optarg); + error = PEFS_ERR_INVALID; + goto out; + } + + snprintf(csm_path, sizeof(csm_path), "%s/%s", optarg, + PEFS_FILE_CHECKSUM); + + break; default: if (fpin != NULL) fclose(fpin); @@ -1079,7 +1105,7 @@ initfsroot(argc, argv, 0, fsroot, sizeof(fsroot)); - error = pefs_create_checksum_file(fpin, fsroot, algo); + error = pefs_create_checksum_file(fpin, fsroot, csm_path, algo); out: if (fpin != NULL) @@ -1209,8 +1235,8 @@ " pefs randomchain [-fv] [-n min] [-N max] filesystem\n" " pefs showchains [-fp] [-i iterations] [-k keyfile] filesystem\n" " pefs showalgs\n" -" pefs addchecksum [-a algo] [-i inputfile] filesystem\n" -" pefs addchecklist [-i inputfile] [-o outputfile[ filesystem\n" +" pefs addchecksum [-a algo] [-i inputfile] [-p checksumpath] filesystem\n" +" pefs addchecklist [-i inputfile] [-o outputfile] filesystem\n" ); exit(PEFS_ERR_USAGE); } Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h Fri May 25 16:26:06 2012 (r236400) @@ -94,7 +94,7 @@ int pefs_key_decrypt(struct pefs_xkeyenc *xe, const struct pefs_xkey *xk_parent); uintmax_t pefs_keyid_as_int(char *keyid); -int pefs_create_checksum_file(FILE *fpin, char *fsroot, const char *algo); +int pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo); int pefs_create_checklist(FILE *fpin, int fdout, char *fsroot, char *fromfsroot); const char * pefs_alg_name(struct pefs_xkey *xk); Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h ============================================================================== --- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs.h Fri May 25 16:26:06 2012 (r236400) @@ -48,9 +48,16 @@ char pxk_key[PEFS_KEY_SIZE]; }; +/* + * XXXgpf: [TODO] gleb says: + Adding 'x' to mark + it as exported to userspace will also be wise. So it's better be + pefs_xnamecsum or pefs_xname_csum. + */ struct pefs_namemac { - uint32_t pnm_namelen; uint64_t pnm_csum; + uint32_t pnm_namelen; + /* XXXgpf: should probably be MAXNAMLEN */ char pnm_filename[MAXPATHLEN]; }; Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c ============================================================================== --- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_vnops.c Fri May 25 16:26:06 2012 (r236400) @@ -2471,15 +2471,25 @@ pefs_flushkey(mp, td, PEFS_FLUSHKEY_ALL, NULL); break; case PEFS_GETNAMEMAC: - if (vp->v_type != VDIR) - panic("pefs_ioctl: PEFS_GETNAMEMAC vp is not a directory\n"); + /* XXXgpf: should I change printf to PEFSDEBUG or something else? */ + if (vp->v_type != VDIR) { + printf("pefs_ioctl: PEFS_GETNAMEMAC vp is not a directory\n"); + error = EINVAL; + break; + } if (strnlen(namemac->pnm_filename, sizeof(namemac->pnm_filename)) != - namemac->pnm_namelen) - panic("pefs_ioctl: PEFS_GETNAMEMAC incorrect pnm_namelen\n"); + namemac->pnm_namelen) { + printf("pefs_ioctl: PEFS_GETNAMEMAC incorrect pnm_namelen %d\n", namemac->pnm_namelen); + error = EINVAL; + break; + } - if (strchr(namemac->pnm_filename, '/') != NULL) - panic("pefs_ioctl: PEFS_GETNAMEMAC pnm_filename contains '/'\n"); + if (strchr(namemac->pnm_filename, '/') != NULL) { + printf("pefs_ioctl: PEFS_GETNAMEMAC pnm_filename contains '/'\n"); + error = EINVAL; + break; + } vn_lock(vp, LK_EXCLUSIVE); pefs_enccn_init(&enccn); @@ -2500,6 +2510,7 @@ enc_len = enccn.pec_cn.cn_namelen; if (enc[0] != '.' || enc_len <= 1) { + pefs_enccn_free(&enccn); error = EINVAL; break; } Modified: soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile ============================================================================== --- soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile Fri May 25 15:16:40 2012 (r236399) +++ soc2012/gpf/pefs_kmod/sys/modules/pefs/Makefile Fri May 25 16:26:06 2012 (r236400) @@ -23,4 +23,3 @@ SRCS+= hmac_sha512.c .include <bsd.kmod.mk> -
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120525162607.7AB13106566C>