[PVFS-developers] metadata file size checking

Porter Don PorterDE at mercury.hendrix.edu
Thu May 6 17:45:59 EDT 2004


Greetings all,

I wanted to implement some protection against overwriting a metadata file
that has not had the migration script run on it after an upgrade.  So I
ended up stat-ing the file in meta-open and if it is not a directory and its
size is not the same as a struct fmeta, then the manager will return an
EINVAL (open to suggestions for better error code) and print a message to
logs.  See below:

diff -ur pvfs-1.6.3-pre1/mgr/meta/metaio.c
pvfs-1.6.3-pre1-mgr-check/mgr/meta/metaio.c
--- pvfs-1.6.3-pre1/mgr/meta/metaio.c	Thu Jan 15 08:59:38 2004
+++ pvfs-1.6.3-pre1-mgr-check/mgr/meta/metaio.c	Thu May  6 16:13:44 2004
@@ -75,6 +75,21 @@
 int meta_open(char *pathname, int flags)
 {
 	int fd;
+	struct stat st;
+
+	/* Check to make sure that the size is appropriate to prevent old
+		metadata from being clobbered.  This is intended to save the
+		bacon of one who forgets to run the migration script.*/
+	if(0 > stat(pathname, &st)){
+		fprintf(stderr, "Could not stat file: %s, Something is very
wrong here.  Errno = %d\n", pathname, errno);
+		return -1;
+	}
+
+	if(S_ISREG(st.st_mode) && st.st_size != sizeof(struct fmeta)){
+		fprintf(stderr, "Cowardly refusing to open %s because it is
not the size I expect a metadata file to be.\n", pathname);
+		errno = EINVAL;
+		return -1;
+	}
 
 	/* no creating files with this; use meta_creat() */
 	flags &= ~O_CREAT;
@@ -90,6 +105,7 @@
  */
 int meta_creat(char *pathname, int flags)
 {
+	static struct fmeta fm;
 	int fd, old_umask, cflags = O_RDWR | O_CREAT | O_EXCL,
 	    mode = S_IRWXU | S_IRGRP | S_IROTH;
 
@@ -101,7 +117,14 @@
 		return(-1);
 	}
 
-	/* MAYBE WRITE IN DUMMY METADATA? */
+	/* write in dummy fmeta so that meta_open will succeed.  This is ok
+	 * because only md_open calls us directly and it will overwrite
+	 * anyway
+	 */
+	if(sizeof(struct fmeta) != write(fd, &fm, sizeof(struct fmeta))){
+		return(-1);
+	}
+
 	close(fd);
 
 	/* reopen the new file using the specified flags */

Also, in the process of debugging this change, I found that the code for
md_stat could be seriously de-obfuscated with the addition of symbolic
links.  The code is much cleaner to read and a tad more efficient:

diff -ur pvfs-1.6.3-pre1/mgr/meta/md_stat.c
pvfs-1.6.3-pre1-mgr-check/mgr/meta/md_stat.c
--- pvfs-1.6.3-pre1/mgr/meta/md_stat.c	Tue Feb 10 13:47:28 2004
+++ pvfs-1.6.3-pre1-mgr-check/mgr/meta/md_stat.c	Thu May  6 15:16:38
2004
@@ -80,66 +80,45 @@
 	 	COPY_STAT_TO_PSTAT(&metar_p->u_stat, &statbuf);
 		metar_p->u_stat.st_mode = S_IFLNK | (S_IRWXO | S_IRWXG |
S_IRWXU);
 		return(0);
-	}
 
-	/* Open metadata file */	
-	if ((fd = meta_open(name, O_RDONLY)) < 0) {
-		if (errno != ENOENT) perror("md_stat, meta_open");
-		return (-1);
-	}
+	} else if(S_ISDIR(statbuf.st_mode)){
 
-	/* Read metadata file - read is done before access to determine if
its a
-	 * directory or not (if its directory we need to do execute
permission
-	 * checking on the entire directory and not just the parent)  */

-	if (meta_read(fd, &meta1) < 0) {
-		if (errno != EISDIR) {
-			perror("md_stat: meta_read");
-			meta_close(fd); /* try to close */
-			return(-1);
-		}
-		else /* directory - just return the normal stats */ {
-			/* check execute permission on parent dir */
-			strncpy(temp, name, MAXPATHLEN);
-			length = get_parent(temp); /* strip off filename */
-			if (length >= 0) {
-				if (meta_access(0, temp, request->uid,
request->gid, X_OK) < 0)
+		/* directory - just return the normal stats */ 
+		/* check execute permission on parent dir */
+		strncpy(temp, name, MAXPATHLEN);
+		length = get_parent(temp); /* strip off filename */
+		if (length >= 0) {
+			if (meta_access(0, temp, request->uid, request->gid,
X_OK) < 0)
 				{
-					meta_close(fd);
 					return(-1);
 				}
-			}
-			/* else CWD is being used and directory permissions
are not
-			 * checked */
-
-			/* get stats and fill in pvfs specific stuff */
-			{
-				struct stat sb;
-				if (fstat(fd, &sb) < 0) {
-					perror("md_stat: fstat");
-					meta_close(fd); /* try to close */
-					return(-1);
-				}
-				COPY_STAT_TO_PSTAT(&metar_p->u_stat, &sb);
-			}
-			/* Close metadata file */
-			if (meta_close(fd) < 0) {
-				perror("md_stat: meta_close");
-				return(-1);
-			}	
-			if (get_dmeta(name, &dir) < 0) {
-				perror("md_stat: get_dmeta");
-				return(-1);
-			}
-			metar_p->u_stat.st_mode =
-				S_IFDIR | ((S_IRWXO | S_IRWXG | S_IRWXU |
S_ISVTX | S_ISGID) & dir.dr_mode);
-
-			metar_p->u_stat.st_uid = dir.dr_uid;
-			metar_p->u_stat.st_gid = dir.dr_gid;
-			return(0);
 		}
+		/* else CWD is being used and directory permissions are not
+		 * checked */
+
+		if (get_dmeta(name, &dir) < 0) {
+			perror("md_stat: get_dmeta");
+			return(-1);
+		}
+
+		COPY_STAT_TO_PSTAT(&metar_p->u_stat, &statbuf);
+
+		metar_p->u_stat.st_mode =
+			S_IFDIR | ((S_IRWXO | S_IRWXG | S_IRWXU | S_ISVTX |
S_ISGID) & dir.dr_mode);
+
+		metar_p->u_stat.st_uid = dir.dr_uid;
+		metar_p->u_stat.st_gid = dir.dr_gid;
+		return(0);
+	} 
+
+	/* else regular file or followed link */
+		
+	/* Open metadata file */	
+	if ((fd = meta_open(name, O_RDONLY)) < 0) {
+		if (errno != ENOENT) perror("md_stat, meta_open");
+		return (-1);
 	}
 
-	/* ok, we know its a file */
 	/* check execute permission on parent directory */
 	strncpy(temp, name, MAXPATHLEN);
 	length = get_parent(temp); /* strip off filename */
@@ -155,6 +134,13 @@
 		}
 	}
 
+	/* Read metadata file */
+	if (meta_read(fd, &meta1) < 0) {
+		perror("md_stat: meta_read");
+		meta_close(fd); /* try to close */
+		return(-1);
+	}
+
 	/* Close metadata file */
 	if (meta_close(fd) < 0) {
 		perror("md_stat: meta_close");


Thanks and let me know what you all think,
don


More information about the PVFS-developers mailing list