Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jan 2017 18:16:57 +0000 (UTC)
From:      "Conrad E. Meyer" <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r312393 - in head: sbin/restore sys/sys sys/ufs/ufs
Message-ID:  <201701181816.v0IIGvfW067921@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Wed Jan 18 18:16:57 2017
New Revision: 312393
URL: https://svnweb.freebsd.org/changeset/base/312393

Log:
  restore(8): Handle extended attribute names correctly
  
  UFS2 extended attribute names are not NUL-terminated.  Handle
  appropriately.
  
  Correct the EXTATTR_BASE_LENGTH() macro, which handled ea_namelength ==
  one (mod eight) extended attributes incorrectly.
  
  PR:		216127
  Reported by:	dewayne at heuristicsystems.com.au
  Reviewed by:	kib@
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D9208

Modified:
  head/sbin/restore/dirs.c
  head/sbin/restore/extern.h
  head/sbin/restore/tape.c
  head/sys/sys/extattr.h
  head/sys/ufs/ufs/extattr.h

Modified: head/sbin/restore/dirs.c
==============================================================================
--- head/sbin/restore/dirs.c	Wed Jan 18 18:14:50 2017	(r312392)
+++ head/sbin/restore/dirs.c	Wed Jan 18 18:16:57 2017	(r312393)
@@ -645,7 +645,7 @@ setdirmodes(int flags)
 		if (!Nflag) {
 			if (node.extsize > 0) {
 				if (bufsize >= node.extsize) {
-					set_extattr_file(cp, buf, node.extsize);
+					set_extattr(-1, cp, buf, node.extsize, SXA_FILE);
 				} else {
 					fprintf(stderr, "Cannot restore %s%s\n",
 					    "extended attributes for ", cp);

Modified: head/sbin/restore/extern.h
==============================================================================
--- head/sbin/restore/extern.h	Wed Jan 18 18:14:50 2017	(r312392)
+++ head/sbin/restore/extern.h	Wed Jan 18 18:16:57 2017	(r312393)
@@ -87,7 +87,12 @@ struct direct	*rst_readdir(RST_DIR *);
 void		 rst_closedir(void *);
 void	 	 runcmdshell(void);
 char		*savename(char *);
-void		 set_extattr_file(char *, void *, int);
+enum set_extattr_mode {
+	SXA_FILE,
+	SXA_LINK,
+	SXA_FD,
+};
+void		 set_extattr(int, char *, void *, int, enum set_extattr_mode);
 void	 	 setdirmodes(int);
 void		 setinput(char *, int);
 void		 setup(void);

Modified: head/sbin/restore/tape.c
==============================================================================
--- head/sbin/restore/tape.c	Wed Jan 18 18:14:50 2017	(r312392)
+++ head/sbin/restore/tape.c	Wed Jan 18 18:16:57 2017	(r312393)
@@ -105,8 +105,6 @@ static void	 findinode(struct s_spcl *);
 static void	 findtapeblksize(void);
 static char	*setupextattr(int);
 static void	 xtrattr(char *, size_t);
-static void	 set_extattr_link(char *, void *, int);
-static void	 set_extattr_fd(int, char *, void *, int);
 static void	 skiphole(void (*)(char *, size_t), size_t *);
 static int	 gethead(struct s_spcl *);
 static void	 readtape(char *);
@@ -627,7 +625,7 @@ extractfile(char *name)
 		}
 		if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
 			if (extsize > 0)
-				set_extattr_link(name, buf, extsize);
+				set_extattr(-1, name, buf, extsize, SXA_LINK);
 			(void) lchown(name, uid, gid);
 			(void) lchmod(name, mode);
 			(void) utimensat(AT_FDCWD, name, ctimep,
@@ -658,7 +656,7 @@ extractfile(char *name)
 		} else {
 			buf = setupextattr(extsize);
 			getfile(xtrnull, xtrattr, xtrnull);
-			set_extattr_file(name, buf, extsize);
+			set_extattr(-1, name, buf, extsize, SXA_FILE);
 		}
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
@@ -688,7 +686,7 @@ extractfile(char *name)
 		} else {
 			buf = setupextattr(extsize);
 			getfile(xtrnull, xtrattr, xtrnull);
-			set_extattr_file(name, buf, extsize);
+			set_extattr(-1, name, buf, extsize, SXA_FILE);
 		}
 		(void) chown(name, uid, gid);
 		(void) chmod(name, mode);
@@ -715,7 +713,7 @@ extractfile(char *name)
 		buf = setupextattr(extsize);
 		getfile(xtrfile, xtrattr, xtrskip);
 		if (extsize > 0)
-			set_extattr_fd(ofile, name, buf, extsize);
+			set_extattr(ofile, name, buf, extsize, SXA_FD);
 		(void) fchown(ofile, uid, gid);
 		(void) fchmod(ofile, mode);
 		(void) futimens(ofile, ctimep);
@@ -728,12 +726,16 @@ extractfile(char *name)
 }
 
 /*
- * Set attributes for a file.
+ * Set attributes on a file descriptor, link, or file.
  */
 void
-set_extattr_file(char *name, void *buf, int size)
+set_extattr(int fd, char *name, void *buf, int size, enum set_extattr_mode mode)
 {
 	struct extattr *eap, *eaend;
+	const char *method;
+	ssize_t res;
+	int error;
+	char eaname[EXTATTR_MAXNAMELEN + 1];
 
 	vprintf(stdout, "Set attributes for %s:", name);
 	eaend = buf + size;
@@ -748,77 +750,34 @@ set_extattr_file(char *name, void *buf, 
 		}
 		if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
 			continue;
-		vprintf(stdout, "\n\t%s, (%d bytes), %*s",
+		snprintf(eaname, sizeof(eaname), "%.*s",
+		    (int)eap->ea_namelength, eap->ea_name);
+		vprintf(stdout, "\n\t%s, (%d bytes), %s",
 			namespace_names[eap->ea_namespace], eap->ea_length,
-			eap->ea_namelength, eap->ea_name);
+			eaname);
 		/*
 		 * First we try the general attribute setting interface.
 		 * However, some attributes can only be set by root or
 		 * by using special interfaces (for example, ACLs).
 		 */
-		if (extattr_set_file(name, eap->ea_namespace, eap->ea_name,
-		    EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
-			dprintf(stdout, " (set using extattr_set_file)");
-			continue;
-		}
-		/*
-		 * If the general interface refuses to set the attribute,
-		 * then we try all the specialized interfaces that we
-		 * know about.
-		 */
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
-			if (acl_set_file(name, ACL_TYPE_ACCESS,
-			    EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_file)");
-				continue;
-			}
-		}
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
-			if (acl_set_file(name, ACL_TYPE_DEFAULT,
-			    EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_file)");
-				continue;
-			}
-		}
-		vprintf(stdout, " (unable to set)");
-	}
-	vprintf(stdout, "\n");
-}
-
-/*
- * Set attributes for a symbolic link.
- */
-static void
-set_extattr_link(char *name, void *buf, int size)
-{
-	struct extattr *eap, *eaend;
-
-	vprintf(stdout, "Set attributes for %s:", name);
-	eaend = buf + size;
-	for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
-		/*
-		 * Make sure this entry is complete.
-		 */
-		if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
-			dprintf(stdout, "\n\t%scorrupted",
-				eap == buf ? "" : "remainder ");
-			break;
+		if (mode == SXA_FD) {
+			res = extattr_set_fd(fd, eap->ea_namespace,
+			    eaname, EXTATTR_CONTENT(eap),
+			    EXTATTR_CONTENT_SIZE(eap));
+			method = "extattr_set_fd";
+		} else if (mode == SXA_LINK) {
+			res = extattr_set_link(name, eap->ea_namespace,
+			    eaname, EXTATTR_CONTENT(eap),
+			    EXTATTR_CONTENT_SIZE(eap));
+			method = "extattr_set_link";
+		} else if (mode == SXA_FILE) {
+			res = extattr_set_file(name, eap->ea_namespace,
+			    eaname, EXTATTR_CONTENT(eap),
+			    EXTATTR_CONTENT_SIZE(eap));
+			method = "extattr_set_file";
 		}
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
-			continue;
-		vprintf(stdout, "\n\t%s, (%d bytes), %*s",
-			namespace_names[eap->ea_namespace], eap->ea_length,
-			eap->ea_namelength, eap->ea_name);
-		/*
-		 * First we try the general attribute setting interface.
-		 * However, some attributes can only be set by root or
-		 * by using special interfaces (for example, ACLs).
-		 */
-		if (extattr_set_link(name, eap->ea_namespace, eap->ea_name,
-		    EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
-			dprintf(stdout, " (set using extattr_set_link)");
+		if (res != -1) {
+			dprintf(stdout, " (set using %s)", method);
 			continue;
 		}
 		/*
@@ -827,77 +786,37 @@ set_extattr_link(char *name, void *buf, 
 		 * know about.
 		 */
 		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
-			if (acl_set_link_np(name, ACL_TYPE_ACCESS,
-			    EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_link_np)");
-				continue;
+		    strcmp(eaname, POSIX1E_ACL_ACCESS_EXTATTR_NAME) == 0) {
+			if (mode == SXA_FD) {
+				error = acl_set_fd(fd, EXTATTR_CONTENT(eap));
+				method = "acl_set_fd";
+			} else if (mode == SXA_LINK) {
+				error = acl_set_link_np(name, ACL_TYPE_ACCESS,
+				    EXTATTR_CONTENT(eap));
+				method = "acl_set_link_np";
+			} else if (mode == SXA_FILE) {
+				error = acl_set_file(name, ACL_TYPE_ACCESS,
+				    EXTATTR_CONTENT(eap));
+				method = "acl_set_file";
 			}
-		}
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
-			if (acl_set_link_np(name, ACL_TYPE_DEFAULT,
-			    EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_link_np)");
+			if (error != -1) {
+				dprintf(stdout, " (set using %s)", method);
 				continue;
 			}
 		}
-		vprintf(stdout, " (unable to set)");
-	}
-	vprintf(stdout, "\n");
-}
-
-/*
- * Set attributes on a file descriptor.
- */
-static void
-set_extattr_fd(int fd, char *name, void *buf, int size)
-{
-	struct extattr *eap, *eaend;
-
-	vprintf(stdout, "Set attributes for %s:", name);
-	eaend = buf + size;
-	for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) {
-		/*
-		 * Make sure this entry is complete.
-		 */
-		if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) {
-			dprintf(stdout, "\n\t%scorrupted",
-				eap == buf ? "" : "remainder ");
-			break;
-		}
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY)
-			continue;
-		vprintf(stdout, "\n\t%s, (%d bytes), %*s",
-			namespace_names[eap->ea_namespace], eap->ea_length,
-			eap->ea_namelength, eap->ea_name);
-		/*
-		 * First we try the general attribute setting interface.
-		 * However, some attributes can only be set by root or
-		 * by using special interfaces (for example, ACLs).
-		 */
-		if (extattr_set_fd(fd, eap->ea_namespace, eap->ea_name,
-		    EXTATTR_CONTENT(eap), EXTATTR_CONTENT_SIZE(eap)) != -1) {
-			dprintf(stdout, " (set using extattr_set_fd)");
-			continue;
-		}
-		/*
-		 * If the general interface refuses to set the attribute,
-		 * then we try all the specialized interfaces that we
-		 * know about.
-		 */
 		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_ACCESS_EXTATTR_NAME)) {
-			if (acl_set_fd(fd, EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_fd)");
-				continue;
+		    strcmp(eaname, POSIX1E_ACL_DEFAULT_EXTATTR_NAME) == 0) {
+			if (mode == SXA_LINK) {
+				error = acl_set_link_np(name, ACL_TYPE_DEFAULT,
+				    EXTATTR_CONTENT(eap));
+				method = "acl_set_link_np";
+			} else {
+				error = acl_set_file(name, ACL_TYPE_DEFAULT,
+				    EXTATTR_CONTENT(eap));
+				method = "acl_set_file";
 			}
-		}
-		if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM &&
-		    !strcmp(eap->ea_name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME)) {
-			if (acl_set_file(name, ACL_TYPE_DEFAULT,
-			    EXTATTR_CONTENT(eap)) != -1) {
-				dprintf(stdout, " (set using acl_set_file)");
+			if (error != -1) {
+				dprintf(stdout, " (set using %s)", method);
 				continue;
 			}
 		}

Modified: head/sys/sys/extattr.h
==============================================================================
--- head/sys/sys/extattr.h	Wed Jan 18 18:14:50 2017	(r312392)
+++ head/sys/sys/extattr.h	Wed Jan 18 18:16:57 2017	(r312393)
@@ -57,10 +57,11 @@
 	EXTATTR_NAMESPACE_USER_STRING, \
 	EXTATTR_NAMESPACE_SYSTEM_STRING }
 
+#define	EXTATTR_MAXNAMELEN	NAME_MAX
+
 #ifdef _KERNEL
 #include <sys/types.h>
 
-#define	EXTATTR_MAXNAMELEN	NAME_MAX
 struct thread;
 struct ucred;
 struct vnode;

Modified: head/sys/ufs/ufs/extattr.h
==============================================================================
--- head/sys/ufs/ufs/extattr.h	Wed Jan 18 18:14:50 2017	(r312392)
+++ head/sys/ufs/ufs/extattr.h	Wed Jan 18 18:16:57 2017	(r312393)
@@ -93,12 +93,14 @@ struct extattr {
  *	content referenced by eap.
  */
 #define	EXTATTR_NEXT(eap) \
-	((struct extattr *)(((void *)(eap)) + (eap)->ea_length))
-#define	EXTATTR_CONTENT(eap) (((void *)(eap)) + EXTATTR_BASE_LENGTH(eap))
+	((struct extattr *)(((u_char *)(eap)) + (eap)->ea_length))
+#define	EXTATTR_CONTENT(eap) \
+	(void *)(((u_char *)(eap)) + EXTATTR_BASE_LENGTH(eap))
 #define	EXTATTR_CONTENT_SIZE(eap) \
 	((eap)->ea_length - EXTATTR_BASE_LENGTH(eap) - (eap)->ea_contentpadlen)
+/* -1 below compensates for ea_name[1] */
 #define	EXTATTR_BASE_LENGTH(eap) \
-	((sizeof(struct extattr) + (eap)->ea_namelength + 7) & ~7)
+	roundup2((sizeof(struct extattr) - 1 + (eap)->ea_namelength), 8)
 
 #ifdef _KERNEL
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201701181816.v0IIGvfW067921>