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
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to