From owner-svn-soc-all@FreeBSD.ORG Tue Jun 5 13:46:21 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id 44F9E106564A for ; Tue, 5 Jun 2012 13:46:20 +0000 (UTC) (envelope-from gpf@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Tue, 05 Jun 2012 13:46:20 +0000 Date: Tue, 05 Jun 2012 13:46:20 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120605134620.44F9E106564A@hub.freebsd.org> Cc: Subject: socsvn commit: r237137 - soc2012/gpf/pefs_kmod/sbin/pefs X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Jun 2012 13:46:21 -0000 Author: gpf Date: Tue Jun 5 13:46:19 2012 New Revision: 237137 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=237137 Log: - check if our input file list is empty - check if some file entry corresponds to an empty file - check if pefs_next_file_entry encounters an error - handle symlinks: If file in input list is symlink, get the absolute path of the file that it's pointing to. Perform sanity checks on target file. If everything's ok, target file is used throughout the codebase. Which means that .pefs.checksum will have an entry for that target file, not for the symlink. - check for numeric overflows in a few parts Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Tue Jun 5 12:34:08 2012 (r237136) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Tue Jun 5 13:46:19 2012 (r237137) @@ -54,7 +54,7 @@ #include "pefs_ctl.h" -#define PEFS_INTEGRITY_DEBUG +//#define PEFS_INTEGRITY_DEBUG #if defined (PEFS_INTEGRITY_DEBUG) #define dprintf(a) printf a #else @@ -71,6 +71,8 @@ #define PEFS_CFH_SIZE 16 #define PEFS_FH_SIZE 16 +/* XXXgpf: [TODO] check pathname string lengths. Some are MAXPATHLEN + 1, some MAXPATHLEN */ + /* XXXgpf: unions for on disk structs and move to a different header? */ struct checksum_file_header { uint8_t version; @@ -169,8 +171,11 @@ return (PEFS_ERR_SYS); } - /* XXXgpf: shouldn't we also check for empty files? */ resid = sb.st_size; + if (resid == 0) { + pefs_warn("empty files are not allowed: %s", fhp->path); + return (PEFS_ERR_INVALID); + } fd = open(fhp->path, O_RDONLY); if (fd < 0) { @@ -244,7 +249,10 @@ nfiles = 0; while (fgets(buf, sizeof(buf), fpin) != NULL) { - /* XXXgpf: [TODO] check for numeric overflow */ + if (nfiles + 1 < nfiles) { + pefs_warn("numeric overflow while counting file entries"); + return (PEFS_ERR_GENERIC); + } nfiles++; } @@ -253,6 +261,11 @@ 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; @@ -287,6 +300,10 @@ } else { chtp->size = pefs_next_prime(chtp->size + 1); + if (chtp->size < chtp->nelements) { + pefs_warn("numeric overflow while computing new hash table size"); + return (PEFS_ERR_GENERIC); + } free(chtp->buckets1); free(chtp->buckets2); } @@ -533,10 +550,14 @@ static int pefs_file_semantic_checks(struct file_header *fhp, struct statfs *fsp) { + char parent_dir[MAXPATHLEN]; + char sbuf[MAXPATHLEN]; struct stat sb; struct statfs this_fs; + char *pch; + int nchars; - if (stat(fhp->path, &sb) != 0) { + if (lstat(fhp->path, &sb) != 0) { warn("cannot stat file %s", fhp->path); return (PEFS_ERR_SYS); } @@ -549,6 +570,35 @@ /* * XXXgpf: [TODO] deal with other types of files */ + if (S_ISLNK(sb.st_mode) != 0) { + nchars = readlink(fhp->path, sbuf, sizeof(sbuf)); + if (nchars == -1) { + warn("readlink failed: %s", fhp->path); + return (PEFS_ERR_SYS); + } + + if (nchars > sizeof(sbuf) - 1) + nchars = sizeof(sbuf) - 1; + sbuf[nchars] = '\0'; + /* turn relative paths to absolute paths which are needed for pefs_get_file_id() */ + if (sbuf[0] != '/') { + strlcpy(parent_dir, fhp->path, sizeof(parent_dir)); + pch = strrchr(parent_dir, '/'); + if (pch == NULL) { + pefs_warn("error retrieving parent dir of %s", fhp->path); + return (PEFS_ERR_NOENT); + } + *pch = '\0'; + snprintf(fhp->path, sizeof(fhp->path), "%s/%s", parent_dir, sbuf); + } + else + strlcpy(fhp->path, sbuf, sizeof(fhp->path)); + + if (lstat(fhp->path, &sb) != 0) { + warn("cannot stat file %s", fhp->path); + return (PEFS_ERR_SYS); + } + } if (S_ISREG(sb.st_mode) == 0) { pefs_warn("filename: %s is not a regular file", fhp->path); @@ -652,6 +702,10 @@ TAILQ_INSERT_TAIL(&fh_head, fhp, file_header_entries); } + /* checking I/O error with pefs_next_file()*/ + if (error != 0) + return (error); + cuckoo_insert: TAILQ_FOREACH(fhp, &fh_head, file_header_entries) { error = pefs_add_to_hash_table(chtp, fhp); @@ -667,7 +721,7 @@ return (error); goto cuckoo_insert; } - } + } pefs_print_hash_table(chtp, hash_len); return (error);